diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/lib/libpkix | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/lib/libpkix')
221 files changed, 83509 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/Makefile b/security/nss/lib/libpkix/Makefile new file mode 100644 index 0000000000..bb88772853 --- /dev/null +++ b/security/nss/lib/libpkix/Makefile @@ -0,0 +1,45 @@ +#! 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/include/Makefile b/security/nss/lib/libpkix/include/Makefile new file mode 100644 index 0000000000..d714361be7 --- /dev/null +++ b/security/nss/lib/libpkix/include/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/include/exports.gyp b/security/nss/lib/libpkix/include/exports.gyp new file mode 100644 index 0000000000..92baaaa9d2 --- /dev/null +++ b/security/nss/lib/libpkix/include/exports.gyp @@ -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/. +{ + 'includes': [ + '../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'lib_libpkix_include_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix.h', + 'pkix_certsel.h', + 'pkix_certstore.h', + 'pkix_checker.h', + 'pkix_crlsel.h', + 'pkix_errorstrings.h', + 'pkix_params.h', + 'pkix_pl_pki.h', + 'pkix_pl_system.h', + 'pkix_results.h', + 'pkix_revchecker.h', + 'pkix_sample_modules.h', + 'pkix_util.h', + 'pkixt.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/include/include.gyp b/security/nss/lib/libpkix/include/include.gyp new file mode 100644 index 0000000000..c435015910 --- /dev/null +++ b/security/nss/lib/libpkix/include/include.gyp @@ -0,0 +1,12 @@ +# 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': [], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/include/manifest.mn b/security/nss/lib/libpkix/include/manifest.mn new file mode 100644 index 0000000000..3792dbb869 --- /dev/null +++ b/security/nss/lib/libpkix/include/manifest.mn @@ -0,0 +1,29 @@ +# +# 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.h \ + pkix_crlsel.h \ + pkix_errorstrings.h \ + pkix_results.h \ + pkixt.h \ + pkix_certsel.h \ + pkix_params.h \ + pkix_revchecker.h \ + pkix_certstore.h \ + pkix_pl_pki.h \ + pkix_sample_modules.h \ + pkix_checker.h \ + pkix_pl_system.h \ + pkix_util.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + $(NULL) + +REQUIRES = dbm diff --git a/security/nss/lib/libpkix/include/pkix.h b/security/nss/lib/libpkix/include/pkix.h new file mode 100644 index 0000000000..4ef3cf1fbd --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix.h @@ -0,0 +1,301 @@ +/* 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/. */ +/* + * This file defines the public API for libpkix. These are the top-level + * functions in the library. They perform the primary operations of this + * library: building and validating chains of X.509 certificates. + * + */ + +#ifndef _PKIX_H +#define _PKIX_H + +#include "pkixt.h" +#include "pkix_util.h" +#include "pkix_results.h" +#include "pkix_certstore.h" +#include "pkix_certsel.h" +#include "pkix_crlsel.h" +#include "pkix_checker.h" +#include "pkix_revchecker.h" +#include "pkix_pl_system.h" +#include "pkix_pl_pki.h" +#include "pkix_params.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* + * FUNCTION: PKIX_Initialize + * DESCRIPTION: + * + * No PKIX_* types and functions should be used before this function is called + * and returns successfully. This function should only be called once. If it + * is called more than once, the behavior is undefined. + * + * NSS applications are expected to call NSS_Init, and need not know that + * NSS will call this function (with "platformInitNeeded" set to PKIX_FALSE). + * PKIX applications are expected instead to call this function with + * "platformInitNeeded" set to PKIX_TRUE. + * + * This function initializes data structures critical to the operation of + * libpkix. It also ensures that the API version (major.minor) desired by the + * caller (the "desiredMajorVersion", "minDesiredMinorVersion", and + * "maxDesiredMinorVersion") is compatible with the API version supported by + * the library. As such, the library must support the "desiredMajorVersion" + * of the API and must support a minor version that falls between + * "minDesiredMinorVersion" and "maxDesiredMinorVersion", inclusive. If + * compatibility exists, the function returns NULL and stores the library's + * actual minor version at "pActualMinorVersion" (which may be greater than + * "desiredMinorVersion"). If no compatibility exists, the function returns a + * PKIX_Error pointer. If the caller wishes to specify that the largest + * minor version available should be used, then maxDesiredMinorVersion should + * be set to the macro PKIX_MAX_MINOR_VERSION (defined in pkixt.h). + * + * PARAMETERS: + * "platformInitNeeded" + * Boolean indicating whether the platform layer initialization code + * has previously been run, or should be called from this function. + * "desiredMajorVersion" + * The major version of the libpkix API the application wishes to use. + * "minDesiredMinorVersion" + * The minimum minor version of the libpkix API the application wishes + * to use. + * "maxDesiredMinorVersion" + * The maximum minor version of the libpkix API the application wishes + * to use. + * "pActualMinorVersion" + * Address where PKIX_UInt32 will be stored. Must be non-NULL. + * "pPlContext" + * Address at which platform-specific context pointer is stored. Must + * be non-NULL. + * THREAD SAFETY: + * Not Thread Safe + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Initialize 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_Initialize( + PKIX_Boolean platformInitNeeded, + PKIX_UInt32 desiredMajorVersion, + PKIX_UInt32 minDesiredMinorVersion, + PKIX_UInt32 maxDesiredMinorVersion, + PKIX_UInt32 *pActualMinorVersion, + void **pPlContext); + +/* + * FUNCTION: PKIX_Shutdown + * DESCRIPTION: + * + * This function deallocates any memory used by libpkix and shuts down any + * ongoing operations. This function should only be called once. If it is + * called more than once, the behavior is undefined. + * + * No PKIX_* types and functions should be used after this function is called + * and returns successfully. + * PARAMETERS: + * "plContext" - Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_Shutdown(void *plContext); + +/* + * FUNCTION: PKIX_ValidateChain + * DESCRIPTION: + * + * This function attempts to validate the CertChain that has been set in the + * ValidateParams pointed to by "params" using an RFC 3280-compliant + * algorithm. If successful, this function returns NULL and stores the + * ValidateResult at "pResult", which holds additional information, such as + * the policy tree and the target's public key. If unsuccessful, an Error is + * returned. Note: This function does not currently support non-blocking I/O. + * + * 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. + * + * PARAMETERS: + * "params" + * Address of ValidateParams used to validate CertChain. Must be non-NULL. + * "pResult" + * Address where object pointer will be 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_ValidateChain( + PKIX_ValidateParams *params, + PKIX_ValidateResult **pResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext); + +/* + * FUNCTION: PKIX_ValidateChain_NB + * DESCRIPTION: + * + * This function is the equivalent of PKIX_ValidateChain, except that it + * supports non-blocking I/O. When called with "pNBIOContext" pointing to NULL + * it initiates a new chain validation as in PKIX_ValidateChain, ignoring the + * value in all input variables except "params". If forced to suspend + * processing by a WOULDBLOCK return from some operation, such as a CertStore + * request, it stores the platform-dependent I/O context at "pNBIOContext" and + * stores other intermediate variables at "pCertIndex", "pAnchorIndex", + * "pCheckerIndex", "pRevChecking", and "pCheckers". + * + * When called subsequently with that non-NULL value at "pNBIOContext", it + * relies on those intermediate values to be untouched, and it resumes chain + * validation where it left off. Its behavior is undefined if any of the + * intermediate values was not preserved. + * + * PARAMETERS: + * "params" + * Address of ValidateParams used to validate CertChain. Must be non-NULL. + * "pCertIndex" + * The UInt32 value of the index to the Cert chain, indicating which Cert + * is currently being processed. + * "pAnchorIndex" + * The UInt32 value of the index to the Anchor chain, indicating which + * Trust Anchor is currently being processed. + * "pCheckerIndex" + * The UInt32 value of the index to the List of CertChainCheckers, + * indicating which Checker is currently processing. + * "pRevChecking" + * The Boolean flag indicating whether normal checking or revocation + * checking is occurring for the Cert indicated by "pCertIndex". + * "pCheckers" + * The address of the List of CertChainCheckers. Must be non-NULL. + * "pNBIOContext" + * The address of the platform-dependend I/O context. Must be a non-NULL + * pointer to a NULL value for the call to initiate chain validation. + * "pResult" + * Address where ValidateResult object pointer will be 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_ValidateChain_NB( + PKIX_ValidateParams *params, + 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); + +/* + * FUNCTION: PKIX_BuildChain + * DESCRIPTION: + * + * If called with a NULL "state", this function attempts to build and validate + * a CertChain according to the ProcessingParams pointed to by "params", using + * an RFC 3280-compliant validation algorithm. If successful, this function + * returns NULL and stores the BuildResult at "pResult", which holds the built + * CertChain, as well as additional information, such as the policy tree and + * the target's public key. If unsuccessful, an Error is returned. + * + * If the chain building is blocked by a CertStore using non-blocking I/O, this + * function stores platform-dependent non-blocking I/O context at + * "pNBIOContext", its state at "pState", and NULL at "pResult". The caller + * may be able to determine, in a platform-dependent way, when the I/O has + * completed. In any case, calling the function again with "pState" containing + * the returned value will allow the chain building to resume. + * + * If chain building is completed, either successfully or unsuccessfully, NULL + * is stored at "pNBIOContext". + * + * If "pVerifyTree" is non-NULL, a tree of VerifyNodes is created which + * tracks the results of the building. That is, each node of the tree either + * has a NULL Error component, or it is a leaf node and it contains an Error + * which indicates why the chain building could not proceed on this branch. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams used to build and validate CertChain. + * Must be non-NULL. + * "pNBIOContext" + * Address where platform-dependent information is store if the build + * is suspended waiting for non-blocking I/O. Must be non-NULL. + * "pState" + * Address of BuildChain state. Must be NULL on initial call, and the + * value previously returned on subsequent calls. + * "pResult" + * Address where object pointer will be 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 Build 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_BuildChain( + PKIX_ProcessingParams *params, + void **pNBIOContext, + void **pState, + PKIX_BuildResult **pResult, + PKIX_VerifyNode **pVerifyNode, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_H */ diff --git a/security/nss/lib/libpkix/include/pkix_certsel.h b/security/nss/lib/libpkix/include/pkix_certsel.h new file mode 100644 index 0000000000..e6b20c8c50 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_certsel.h @@ -0,0 +1,1826 @@ +/* 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/. */ +/* + * This file defines functions associated with the PKIX_CertSelector and the + * PKIX_ComCertSelParams types. + * + */ + +#ifndef _PKIX_CERTSEL_H +#define _PKIX_CERTSEL_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_CertSelector + * + * PKIX_CertSelectors provide a standard way for the caller to select + * certificates based on particular criteria. A CertSelector is typically used + * by the caller to specify the constraints they wish to impose on the target + * certificate in a chain. (see pkix_params.h) A CertSelector is also often + * used to retrieve certificates from a CertStore that match the selector's + * criteria. (See pkix_certstore.h) For example, the caller may wish to only + * select those certificates that have a particular Subject Distinguished Name + * and a particular value for a private certificate extension. The + * MatchCallback allows the caller to specify the custom matching logic to be + * used by a CertSelector. + * + * By default, the MatchCallback is set to point to the default implementation + * provided by libpkix, which understands how to process the most common + * parameters. If the default implementation is used, the caller should set + * these common parameters using PKIX_CertSelector_SetCommonCertSelectorParams. + * Any common parameter that is not set is assumed to be disabled, which means + * the default MatchCallback implementation will select all certificates + * without regard to that particular disabled parameter. For example, if the + * SerialNumber parameter is not set, MatchCallback 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 of NULL, or -1 for PKIX_ComCertSelParams_GetBasicConstraints + * and PKIX_ComCertSelParams_GetVersion, or 0 for + * PKIX_ComCertSelParams_GetKeyUsage. + * + * If a custom implementation is desired, the default implementation can be + * overridden by calling PKIX_CertSelector_SetMatchCallback. In this case, the + * CertSelector can be initialized with a certSelectorContext, which is where + * the caller can specify the desired parameters the caller wishes to match + * against. Note that this certSelectorContext must be an Object (although any + * object type), allowing it to be reference-counted and allowing it to + * provide the standard Object functions (Equals, Hashcode, ToString, Compare, + * Duplicate). + * + */ + +/* + * FUNCTION: PKIX_CertSelector_MatchCallback + * DESCRIPTION: + * + * This callback 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 matches the CertSelector's criteria, an exception will + * be thrown. + * + * 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: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * 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. + */ +typedef PKIX_Error * +(*PKIX_CertSelector_MatchCallback)( + PKIX_CertSelector *selector, + PKIX_PL_Cert *cert, + void *plContext); + +/* + * FUNCTION: PKIX_CertSelector_Create + * DESCRIPTION: + * + * Creates a new CertSelector using the Object pointed to by + * "certSelectorContext" (if any) and stores it at "pSelector". As noted + * above, by default, the MatchCallback is set to point to the default + * implementation provided by libpkix, which understands how to process + * ComCertSelParams objects. This is overridden if the MatchCallback pointed + * to by "callback" is not NULL, in which case the parameters are specified + * using the certSelectorContext. + * + * PARAMETERS: + * "callback" + * The MatchCallback function to be used. + * "certSelectorContext" + * Address of Object representing the CertSelector's context (if any). + * "pSelector" + * 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 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_Create( + PKIX_CertSelector_MatchCallback callback, + PKIX_PL_Object *certSelectorContext, + PKIX_CertSelector **pSelector, + void *plContext); + +/* + * FUNCTION: PKIX_CertSelector_GetMatchCallback + * DESCRIPTION: + * + * Retrieves a pointer to "selector's" Match callback function and puts it in + * "pCallback". + * + * PARAMETERS: + * "selector" + * The CertSelector whose Match callback is desired. Must be non-NULL. + * "pCallback" + * Address where Match callback function 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 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_GetMatchCallback( + PKIX_CertSelector *selector, + PKIX_CertSelector_MatchCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertSelector_GetCertSelectorContext + * DESCRIPTION: + * + * Retrieves a pointer to a PKIX_PL_Object representing the context (if any) + * of the CertSelector pointed to by "selector" and stores it at + * "pCertSelectorContext". + * + * PARAMETERS: + * "selector" + * Address of CertSelector whose context is to be stored. + * Must be non-NULL. + * "pCertSelectorContext" + * 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 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_GetCertSelectorContext( + PKIX_CertSelector *selector, + PKIX_PL_Object **pCertSelectorContext, + void *plContext); + +/* + * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams + * DESCRIPTION: + * + * Retrieves a pointer to the ComCertSelParams object that represent the + * common parameters of the CertSelector pointed to by "selector" and stores + * it at "pCommonCertSelectorParams". If there are no common parameters + * stored with the CertSelector, this function stores NULL at + * "pCommonCertSelectorParams". + * + * PARAMETERS: + * "selector" + * Address of CertSelector whose ComCertSelParams object is to be stored. + * Must be non-NULL. + * "pCommonCertSelectorParams" + * 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 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_GetCommonCertSelectorParams( + PKIX_CertSelector *selector, + PKIX_ComCertSelParams **pCommonCertSelectorParams, + void *plContext); + +/* + * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams + * DESCRIPTION: + * + * Sets the common parameters for the CertSelector pointed to by "selector" + * using the ComCertSelParams object pointed to by "commonCertSelectorParams". + * + * PARAMETERS: + * "selector" + * Address of CertSelector whose common parameters are to be set. + * Must be non-NULL. + * "commonCertSelectorParams" + * Address of ComCertSelParams object representing the common parameters. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "selector" + * (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_SetCommonCertSelectorParams( + PKIX_CertSelector *selector, + PKIX_ComCertSelParams *commonCertSelectorParams, + void *plContext); + +/* PKIX_ComCertSelParams + * + * PKIX_ComCertSelParams objects are X.509 parameters commonly used with + * CertSelectors, especially when enforcing constraints on a target + * certificate or determining which certificates to retrieve from a CertStore. + * ComCertSelParams objects are typically used with those CertSelectors that + * use the default implementation of MatchCallback, which understands how to + * process ComCertSelParams objects. + */ + +/* + * FUNCTION: PKIX_ComCertSelParams_Create + * DESCRIPTION: + * + * Creates a new ComCertSelParams object and stores it at "pParams". + * + * PARAMETERS: + * "pParams" + * 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 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_ComCertSelParams_Create( + PKIX_ComCertSelParams **pParams, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjAltNames + * DESCRIPTION: + * + * Retrieves a pointer to the List of GeneralNames (if any) representing the + * subject alternative names criterion that is set in the ComCertSelParams + * object pointed to by "params" and stores it at "pNames". In order to match + * against this criterion, a certificate must contain all or at least one of + * the criterion's subject alternative names (depending on the result of + * PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default behavior + * requires a certificate to contain all of the criterion's subject + * alternative names in order to match. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pNames", in which case all certificates are considered to match this + * criterion. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject alternative names + * criterion (if any) is to be stored. Must be non-NULL. + * "pNames" + * 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 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_ComCertSelParams_GetSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_List **pNames, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjAltNames + * DESCRIPTION: + * + * Sets the subject alternative names criterion of the ComCertSelParams object + * pointed to by "params" using a List of GeneralNames pointed to by "names". + * In order to match against this criterion, a certificate must contain all or + * at least one of the criterion's subject alternative names (depending on the + * result of PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default + * behavior requires a certificate to contain all of the criterion's subject + * alternative names in order to match. + * + * If "names" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject alternative + * names criterion is to be set. Must be non-NULL. + * "names" + * Address of List of GeneralNames used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_List *names, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_AddSubjAltName + * DESCRIPTION: + * + * Adds to the subject alternative names criterion of the ComCertSelParams + * object pointed to by "params" using the GeneralName pointed to by "name". + * In order to match against this criterion, a certificate must contain all + * or at least one of the criterion's subject alternative names (depending on + * the result of PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default + * behavior requires a certificate to contain all of the criterion's subject + * alternative names in order to match. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject alternative names + * criterion is to be added to. Must be non-NULL. + * "name" + * Address of GeneralName to be added. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_AddSubjAltName( + PKIX_ComCertSelParams *params, + PKIX_PL_GeneralName *name, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetPathToNames + * DESCRIPTION: + * + * Retrieves a pointer to the List of GeneralNames (if any) representing the + * path to names criterion that is set in the ComCertSelParams object pointed + * to by "params" and stores it at "pNames". In order to match against this + * criterion, a certificate must not include name constraints that would + * prohibit building a path to the criterion's specified names. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pNames", in which case all certificates are considered to match this + * criterion. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose path to names criterion + * (if any) is to be stored. Must be non-NULL. + * "pNames" + * 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 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_ComCertSelParams_GetPathToNames( + PKIX_ComCertSelParams *params, + PKIX_List **pNames, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetPathToNames + * DESCRIPTION: + * + * Sets the path to names criterion of the ComCertSelParams object pointed to + * by "params" using a List of GeneralNames pointed to by "names". In order to + * match against this criterion, a certificate must not include name + * constraints that would prohibit building a path to the criterion's + * specified names. + * + * If "names" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose path to names criterion + * is to be set. Must be non-NULL. + * "names" + * Address of List of GeneralNames used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetPathToNames( + PKIX_ComCertSelParams *params, + PKIX_List *names, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_AddPathToName + * DESCRIPTION: + * + * Adds to the path to names criterion of the ComCertSelParams object pointed + * to by "params" using the GeneralName pointed to by "pathToName". In order + * to match against this criterion, a certificate must not include name + * constraints that would prohibit building a path to the criterion's + * specified names. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose path to names criterion is to + * be added to. Must be non-NULL. + * "pathToName" + * Address of GeneralName to be added. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_AddPathToName( + PKIX_ComCertSelParams *params, + PKIX_PL_GeneralName *pathToName, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetAuthorityKeyIdentifier + * DESCRIPTION: + * + * Retrieves a pointer to the ByteArray (if any) representing the authority + * key identifier criterion that is set in the ComCertSelParams object + * pointed to by "params" and stores it at "pAuthKeyId". In order to match + * against this criterion, a certificate must contain an + * AuthorityKeyIdentifier extension whose value matches the criterion's + * authority key identifier value. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pAuthKeyId", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose authority key identifier + * criterion (if any) is to be stored. Must be non-NULL. + * "pAuthKeyId" + * 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 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_ComCertSelParams_GetAuthorityKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray **pAuthKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetAuthorityKeyIdentifier + * DESCRIPTION: + * + * Sets the authority key identifier criterion of the ComCertSelParams object + * pointed to by "params" to the ByteArray pointed to by "authKeyId". In + * order to match against this criterion, a certificate must contain an + * AuthorityKeyIdentifier extension whose value matches the criterion's + * authority key identifier value. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose authority key identifier + * criterion is to be set. Must be non-NULL. + * "authKeyId" + * Address of ByteArray used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetAuthorityKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray *authKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjKeyIdentifier + * DESCRIPTION: + * + * Retrieves a pointer to the ByteArray (if any) representing the subject key + * identifier criterion that is set in the ComCertSelParams object pointed to + * by "params" and stores it at "pSubjKeyId". In order to match against this + * criterion, a certificate must contain a SubjectKeyIdentifier extension + * whose value matches the criterion's subject key identifier value. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pSubjKeyId", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject key identifier + * criterion (if any) is to be stored. Must be non-NULL. + * "pSubjKeyId" + * 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 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_ComCertSelParams_GetSubjKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray **pSubjKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjKeyIdentifier + * DESCRIPTION: + * + * Sets the subject key identifier criterion of the ComCertSelParams object + * pointed to by "params" using a ByteArray pointed to by "subjKeyId". In + * order to match against this criterion, a certificate must contain an + * SubjectKeyIdentifier extension whose value matches the criterion's subject + * key identifier value. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject key identifier + * criterion is to be set. Must be non-NULL. + * "subjKeyId" + * Address of ByteArray used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubjKeyIdentifier( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray *subKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjPubKey + * DESCRIPTION: + * + * Retrieves a pointer to the PublicKey (if any) representing the subject + * public key criterion that is set in the ComCertSelParams object pointed to + * by "params" and stores it at "pPubKey". In order to match against this + * criterion, a certificate must contain a SubjectPublicKey that matches the + * criterion's public key. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pPubKey", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject public key criterion + * (if any) is to be stored. Must be non-NULL. + * "pPubKey" + * 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 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_ComCertSelParams_GetSubjPubKey( + PKIX_ComCertSelParams *params, + PKIX_PL_PublicKey **pPubKey, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjPubKey + * DESCRIPTION: + * + * Sets the subject public key criterion of the ComCertSelParams object + * pointed to by "params" using a PublicKey pointed to by "pubKey". In order + * to match against this criterion, a certificate must contain a + * SubjectPublicKey that matches the criterion's public key. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject public key + * criterion is to be set. Must be non-NULL. + * "pubKey" + * Address of PublicKey used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubjPubKey( + PKIX_ComCertSelParams *params, + PKIX_PL_PublicKey *pubKey, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjPKAlgId + * DESCRIPTION: + * + * Retrieves a pointer to the OID (if any) representing the subject public key + * algorithm identifier criterion that is set in the ComCertSelParams object + * pointed to by "params" and stores it at "pPubKey". In order to match + * against this criterion, a certificate must contain a SubjectPublicKey with + * an algorithm that matches the criterion's algorithm. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pAlgId", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject public key algorithm + * identifier (if any) is to be stored. Must be non-NULL. + * "pAlgId" + * 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 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_ComCertSelParams_GetSubjPKAlgId( + PKIX_ComCertSelParams *params, + PKIX_PL_OID **pAlgId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjPKAlgId + * DESCRIPTION: + * + * Sets the subject public key algorithm identifier criterion of the + * ComCertSelParams object pointed to by "params" using an OID pointed to by + * "algId". In order to match against this criterion, a certificate must + * contain a SubjectPublicKey with an algorithm that matches the criterion's + * algorithm. + * + * If "algId" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject public key + * algorithm identifier criterion is to be set. Must be non-NULL. + * "algId" + * Address of OID used to set criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubjPKAlgId( + PKIX_ComCertSelParams *params, + PKIX_PL_OID *algId, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetBasicConstraints + * DESCRIPTION: + * + * Retrieves a pointer to the minimum path length (if any) representing the + * basic constraints criterion that is set in the ComCertSelParams object + * pointed to by "params" and stores it at "pMinPathLength". 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. + * + * The semantics of other values of the criterion's minimum path length are + * undefined but may be defined in future versions of the API. + * + * If "params" does not have this criterion set, this function stores -1 at + * "pMinPathLength", in which case all certificates are considered to match + * this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose basic constraints criterion + * (if any) is to be stored. Must be non-NULL. + * "pMinPathLength" + * Address where PKIX_Int32 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 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_ComCertSelParams_GetBasicConstraints( + PKIX_ComCertSelParams *params, + PKIX_Int32 *pMinPathLength, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetBasicConstraints + * DESCRIPTION: + * + * Sets the basic constraints criterion of the ComCertSelParams object + * pointed to by "params" using the integer value of "minPathLength". 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. + * + * The semantics of other values of the criterion's minimum path length are + * undefined but may be defined in future versions of the API. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose basic constraints + * criterion is to be set. Must be non-NULL. + * "minPathLength" + * Value of PKIX_Int32 used to set the criterion + * (or -1 to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetBasicConstraints( + PKIX_ComCertSelParams *params, + PKIX_Int32 minPathLength, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetCertificate + * DESCRIPTION: + * + * Retrieves a pointer to the Cert (if any) representing the certificate + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pCert". In order to match against this + * criterion, a certificate must be equal to the criterion's certificate. If + * this criterion is specified, it is usually not necessary to specify any + * other criteria, since this criterion requires an exact certificate match. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pCert", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose certificate criterion + * (if any) is to be stored. Must be non-NULL. + * "pCert" + * 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 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_ComCertSelParams_GetCertificate( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert **pCert, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetCertificate + * DESCRIPTION: + * + * Sets the certificate criterion of the ComCertSelParams object pointed to by + * "params" using a Cert pointed to by "cert". In order to match against this + * criterion, a certificate must be equal to the criterion's certificate. + * If this criterion is specified, it is usually not necessary to specify + * any other criteria, since this criterion requires an exact certificate + * match. + * + * If "cert" is NULL, all certificates are considered to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose certificate criterion is to be + * set. Must be non-NULL. + * "cert" + * Address of Cert used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetCertificate( + PKIX_ComCertSelParams *params, + PKIX_PL_Cert *cert, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetCertificateValid + * DESCRIPTION: + * + * Retrieves a pointer to the Date (if any) representing the certificate + * validity criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pDate". In order to match against this + * criterion, a certificate's validity period must include the criterion's + * Date. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pDate", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose certificate validity criterion + * (if any) is to be stored. Must be non-NULL. + * "pDate" + * 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 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_ComCertSelParams_GetCertificateValid( + PKIX_ComCertSelParams *params, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetCertificateValid + * DESCRIPTION: + * + * Sets the certificate validity criterion of the ComCertSelParams object + * pointed to by "params" using a Date pointed to by "date". In order to + * match against this criterion, a certificate's validity period must include + * the criterion's Date. + * + * If "date" is NULL, all certificates are considered to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose certificate validity criterion + * is to be set. Must be non-NULL. + * "date" + * Address of Date used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetCertificateValid( + PKIX_ComCertSelParams *params, + PKIX_PL_Date *date, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSerialNumber + * DESCRIPTION: + * + * Retrieves a pointer to the BigInt (if any) representing the serial number + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pSerialNumber". In order to match against this + * criterion, a certificate must have a serial number equal to the + * criterion's serial number. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pSerialNumber", in which case all certificates are considered to match + * this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose serial number criterion + * (if any) is to be stored. Must be non-NULL. + * "pSerialNumber" + * 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 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_ComCertSelParams_GetSerialNumber( + PKIX_ComCertSelParams *params, + PKIX_PL_BigInt **pSerialNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSerialNumber + * DESCRIPTION: + * + * Sets the serial number criterion of the ComCertSelParams object pointed to + * by "params" using a BigInt pointed to by "serialNumber". In order to match + * against this criterion, a certificate must have a serial number equal to + * the criterion's serial number. + * + * If "serialNumber" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose serial number criterion is to + * be set. Must be non-NULL. + * "serialNumber" + * Address of BigInt used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSerialNumber( + PKIX_ComCertSelParams *params, + PKIX_PL_BigInt *serialNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetVersion + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the version criterion that is + * set in the ComCertSelParams object pointed to by "params" and stores it at + * "pVersion". In order to match against this criterion, a certificate's + * version must be equal to the criterion's version. + * + * The version number will either be 0, 1, or 2 (corresponding to + * v1, v2, or v3, respectively). + * + * If "params" does not have this criterion set, this function stores + * 0xFFFFFFFF at "pVersion", in which case all certificates are considered + * to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose version criterion (if any) is + * to be stored. Must be non-NULL. + * "pVersion" + * Address where PKIX_Int32 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 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_ComCertSelParams_GetVersion( + PKIX_ComCertSelParams *params, + PKIX_UInt32 *pVersion, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetVersion + * DESCRIPTION: + * + * Sets the version criterion of the ComCertSelParams object pointed to by + * "params" using the integer value of "version". In order to match against + * this criterion, a certificate's version must be equal to the criterion's + * version. If the criterion's version is -1, no version check is done and + * all certificates are considered to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose version criterion is to be + * set. Must be non-NULL. + * "version" + * Value of PKIX_Int32 used to set the criterion + * (or -1 to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetVersion( + PKIX_ComCertSelParams *params, + PKIX_Int32 version, + void *plContext); + + +/* + * FUNCTION: PKIX_ComCertSelParams_GetKeyUsage + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the key usage criterion that + * is set in the ComCertSelParams object pointed to by "params" and stores it + * at "pKeyUsage". In order to match against this criterion, a certificate + * must allow the criterion's key usage values. Note that a certificate that + * has no KeyUsage extension implicity allows all key usages. Note also that + * this functions supports a maximum of 32 key usage bits. + * + * If "params" does not have this criterion set, this function stores zero at + * "pKeyUsage", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose key usage criterion (if any) + * is to be stored. Must be non-NULL. + * "pKeyUsage" + * Address where PKIX_UInt32 will be stored. Must not 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. + */ +PKIX_Error * +PKIX_ComCertSelParams_GetKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_UInt32 *pKeyUsage, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetKeyUsage + * DESCRIPTION: + * + * Sets the key usage criterion of the ComCertSelParams object pointed to by + * "params" using the integer value of "keyUsage". In order to match against + * this criterion, a certificate must allow the criterion's key usage values. + * Note that a certificate that has no KeyUsage extension implicity allows + * all key usages. Note also that this functions supports a maximum of 32 key + * usage bits. + * + * If the criterion's key usage value is zero, no key usage check is done and + * all certificates are considered to match this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose key usage criterion is to be + * set. Must be non-NULL. + * "keyUsage" + * Value of PKIX_Int32 used to set the criterion + * (or zero to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_UInt32 keyUsage, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetExtendedKeyUsage + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (if any) representing the extended + * key usage criterion that is set in the ComCertSelParams object pointed to + * by "params" and stores it at "pExtKeyUsage". In order to match against this + * criterion, a certificate's ExtendedKeyUsage extension must allow the + * criterion's extended key usages. Note that a certificate that has no + * ExtendedKeyUsage extension implicity allows all key purposes. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pExtKeyUsage", in which case all certificates are considered to match + * this criterion. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose extended key usage criterion + * (if any) is to be stored. Must be non-NULL. + * "pExtKeyUsage" + * 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 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_ComCertSelParams_GetExtendedKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_List **pExtKeyUsage, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetExtendedKeyUsage + * DESCRIPTION: + * + * Sets the extended key usage criterion of the ComCertSelParams object + * pointed to by "params" using a List of OIDs pointed to by "extKeyUsage". + * In order to match against this criterion, a certificate's ExtendedKeyUsage + * extension must allow the criterion's extended key usages. Note that a + * certificate that has no ExtendedKeyUsage extension implicitly allows all + * key purposes. + * + * If "extKeyUsage" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose extended key usage criterion + * is to be set. Must be non-NULL. + * "extKeyUsage" + * Address of List of OIDs used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetExtendedKeyUsage( + PKIX_ComCertSelParams *params, + PKIX_List *extKeyUsage, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetPolicy + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (if any) representing the policy + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pPolicy". In order to match against this + * criterion, a certificate's CertificatePolicies extension must include at + * least one of the criterion's policies. If "params" has this criterion set, + * but the List of OIDs is empty, then a certificate's CertificatePolicies + * extension must include at least some policy. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pPolicy", in which case all certificates are considered to match this + * criterion. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose policy criterion (if any) is + * to be stored. Must be non-NULL. + * "pPolicy" + * 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 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_ComCertSelParams_GetPolicy( + PKIX_ComCertSelParams *params, + PKIX_List **pPolicy, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetPolicy + * DESCRIPTION: + * + * Sets the policy criterion of the ComCertSelParams object pointed to by + * "params" using a List of OIDs pointed to by "policy". In order to match + * against this criterion, a certificate's CertificatePolicies extension must + * include at least one of the criterion's policies. If "params" has this + * criterion set, but the List of OIDs is empty, then a certificate's + * CertificatePolicies extension must include at least some policy. + * + * If "policy" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose policy criterion is to be set. + * Must be non-NULL. + * "policy" + * Address of List of OIDs used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetPolicy( + PKIX_ComCertSelParams *params, + PKIX_List *policy, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetIssuer + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name (if any) representing the issuer + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pIssuer". In order to match against this + * criterion, a certificate's IssuerName must match the criterion's issuer + * name. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pIssuer", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose issuer criterion (if any) is + * to be stored. Must be non-NULL. + * "pIssuer" + * 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 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_ComCertSelParams_GetIssuer( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name **pIssuer, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetIssuer + * DESCRIPTION: + * + * Sets the issuer criterion of the ComCertSelParams object pointed to by + * "params" using an X500Name pointed to by "issuer". In order to match + * against this criterion, a certificate's IssuerName must match the + * criterion's issuer name. + * + * If "issuer" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose issuer criterion is to be set. + * Must be non-NULL. + * "issuer" + * Address of X500Name used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetIssuer( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name *issuer, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubject + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name (if any) representing the subject + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pSubject". In order to match against this + * criterion, a certificate's SubjectName must match the criterion's subject + * name. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pSubject", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject criterion (if any) is + * to be stored. Must be non-NULL. + * "pSubject" + * 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 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_ComCertSelParams_GetSubject( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name **pSubject, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubject + * DESCRIPTION: + * + * Sets the subject criterion of the ComCertSelParams object pointed to by + * "params" using an X500Name pointed to by "subject". In order to match + * against this criterion, a certificate's SubjectName must match the + * criterion's subject name. + * + * If "subject" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject criterion is to be + * set. Must be non-NULL. + * "subject" + * Address of X500Name used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubject( + PKIX_ComCertSelParams *params, + PKIX_PL_X500Name *subject, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetSubjectAsByteArray + * DESCRIPTION: + * + * Retrieves a pointer to the ByteArray (if any) representing the subject + * criterion that is set in the ComCertSelParams object pointed to by + * "params" and stores it at "pSubject". In order to match against this + * criterion, a certificate's SubjectName must match the criterion's subject + * name. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pSubject", in which case all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject criterion (if any) is + * to be stored. Must be non-NULL. + * "pSubject" + * 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 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_ComCertSelParams_GetSubjectAsByteArray( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray **pSubject, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetSubjectAsByteArray + * DESCRIPTION: + * + * Sets the subject criterion of the ComCertSelParams object pointed to by + * "params" using a ByteArray pointed to by "subject". In order to match + * against this criterion, a certificate's SubjectName must match the + * criterion's subject name. + * + * If "subject" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose subject criterion is to be + * set. Must be non-NULL. + * "subject" + * Address of ByteArray used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetSubjectAsByteArray( + PKIX_ComCertSelParams *params, + PKIX_PL_ByteArray *subject, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetNameConstraints + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name (if any) representing the name + * constraints criterion that is set in the ComCertSelParams object pointed + * to by "params" and stores it at "pConstraints". In order to match against + * this criterion, a certificate's subject and subject alternative names must + * be allowed by the criterion's name constraints. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pConstraints", in which case all certificates are considered to match + * this criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose name constraints criterion + * (if any) is to be stored. Must be non-NULL. + * "pConstraints" + * 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 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_ComCertSelParams_GetNameConstraints( + PKIX_ComCertSelParams *params, + PKIX_PL_CertNameConstraints **pConstraints, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetNameConstraints + * DESCRIPTION: + * + * Sets the name constraints criterion of the ComCertSelParams object pointed + * to by "params" using the CertNameConstraints pointed to by "constraints". + * In order to match against this criterion, a certificate's subject and + * subject alternative names must be allowed by the criterion's name + * constraints. + * + * If "constraints" is NULL, all certificates are considered to match this + * criterion. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose name constraints criterion is + * to be set. Must be non-NULL. + * "constraints" + * Address of CertNameConstraints used to set the criterion + * (or NULL to disable the criterion). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetNameConstraints( + PKIX_ComCertSelParams *params, + PKIX_PL_CertNameConstraints *constraints, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetMatchAllSubjAltNames + * DESCRIPTION: + * + * Checks whether the ComCertSelParams object pointed to by "params" indicate + * that all subject alternative names are to be matched and stores the Boolean + * result at "pMatch". This Boolean value determines the behavior of the + * subject alternative names criterion. + * + * In order to match against the subject alternative names criterion, if the + * Boolean value at "pMatch" is PKIX_TRUE, a certificate must contain all of + * the criterion's subject alternative names. If the Boolean value at + * "pMatch" is PKIX_FALSE, a certificate must contain at least one of the + * criterion's subject alternative names. The default behavior is as if the + * Boolean value at "pMatch" is PKIX_TRUE. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object used to determine whether all + * subject alternative names must be matched. Must be non-NULL. + * "pMatch" + * 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 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_ComCertSelParams_GetMatchAllSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_Boolean *pMatch, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetMatchAllSubjAltNames + * DESCRIPTION: + * + * Sets the match flag of the ComCertSelParams object pointed to by "params" + * using the Boolean value of "match". This Boolean value determines the + * behavior of the subject alternative names criterion. + * + * In order to match against the subject alternative names criterion, if the + * "match" is PKIX_TRUE, a certificate must contain all of the criterion's + * subject alternative names. If the "match" is PKIX_FALSE, a certificate + * must contain at least one of the criterion's subject alternative names. + * The default behavior is as if "match" is PKIX_TRUE. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose match flag is to be set. + * Must be non-NULL. + * "match" + * Boolean value used to set the match flag. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetMatchAllSubjAltNames( + PKIX_ComCertSelParams *params, + PKIX_Boolean match, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_GetLeafCertFlag + * DESCRIPTION: + * + * Return "leafCert" flag of the ComCertSelParams structure. If set to true, + * the flag indicates that a selector should filter out all cert that are not + * qualified to be a leaf cert according to the specified key/ekey usages. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object used to determine whether all + * subject alternative names must be matched. Must be non-NULL. + * "pLeafFlag" + * Address of returned value. + * "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. + */ +PKIX_Error* +PKIX_ComCertSelParams_GetLeafCertFlag( + PKIX_ComCertSelParams *params, + PKIX_Boolean *pLeafFlag, + void *plContext); + +/* + * FUNCTION: PKIX_ComCertSelParams_SetLeafCertFlag + * DESCRIPTION: + * + * Sets a flag that if its value is true, indicates that the selector + * should only pick certs that qualifies to be leaf for this cert path + * validation. + * + * PARAMETERS: + * "params" + * Address of ComCertSelParams object whose match flag is to be set. + * Must be non-NULL. + * "leafFlag" + * Boolean value used to set the leaf flag. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCertSelParams_SetLeafCertFlag( + PKIX_ComCertSelParams *params, + PKIX_Boolean leafFlag, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CERTSEL_H */ diff --git a/security/nss/lib/libpkix/include/pkix_certstore.h b/security/nss/lib/libpkix/include/pkix_certstore.h new file mode 100644 index 0000000000..fb705644eb --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_certstore.h @@ -0,0 +1,714 @@ +/* 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/. */ +/* + * This file defines functions associated with the PKIX_CertStore type. + * + */ + +#ifndef _PKIX_CERTSTORE_H +#define _PKIX_CERTSTORE_H + +#include "pkixt.h" +#include "certt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_CertStore + * + * A PKIX_CertStore provides a standard way for the caller to retrieve + * certificates and CRLs from a particular repository (or "store") of + * certificates and CRLs, including LDAP directories, flat files, local + * databases, etc. The CertCallback allows custom certificate retrieval logic + * to be used while the CRLCallback allows custom CRL retrieval logic to be + * used. Additionally, a CertStore can be initialized with a certStoreContext, + * which is where the caller can specify configuration data such as the host + * name of an LDAP server. Note that this certStoreContext must be an + * Object (although any object type), allowing it to be reference-counted and + * allowing it to provide the standard Object functions (Equals, Hashcode, + * ToString, Compare, Duplicate). Please note that each certStoreContext must + * provide Equals and Hashcode functions in order for the caching (on Cert and + * CertChain) to work correctly. When providing those two functions, it is not + * required that all the components of the object be hashed or checked for + * equality, but merely that the functions distinguish between unique + * instances of the certStoreContext. + * + * Once the caller has created the CertStore object, the caller then specifies + * these CertStore objects in a ProcessingParams object and passes that object + * to PKIX_ValidateChain or PKIX_BuildChain, which uses the objects to call the + * user's callback functions as needed during the validation or building + * process. + * + * The order of CertStores stored (as a list) at ProcessingParams determines + * the order in which certificates are retrieved. Trusted CertStores should + * precede non-trusted ones on the list of CertStores so their certificates + * are evaluated ahead of other certificates selected on the basis of the same + * selector criteria. + * + * The CheckTrustCallback function is used when the CertStore object + * supports trust status, which means a Cert's trust status can be altered + * dynamically. When a CertStore object is created, if the + * CheckTrustCallback is initialized to be non-NULL, this CertStore is + * defaulted as supporting trust. Then whenever a Cert needs to (re)check its + * trust status, this callback can be invoked. When a Cert is retrieved by + * a CertStore supports trust, at its GetCertCallback, the CertStore + * information should be updated in Cert's data structure so the link between + * the Cert and CertStore exists. + * + */ + +/* + * FUNCTION: PKIX_CertStore_CertCallback + * DESCRIPTION: + * + * This callback function retrieves from the CertStore pointed to by "store" + * all the certificates that match the CertSelector pointed to by "selector". + * It places these certificates in a List and stores a pointer to the List at + * "pCerts". If no certificates are found which match the CertSelector's + * criteria, this function stores an empty List at "pCerts". In either case, if + * the operation is completed, NULL is stored at "pNBIOContext". + * + * A CertStore which uses non-blocking I/O may store platform-dependent + * information at "pNBIOContext" and NULL at "pCerts" to indicate that I/O is + * pending. A subsequent call to PKIX_CertStore_CertContinue is required to + * finish the operation and to obtain the List of Certs. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "store" + * Address of CertStore from which Certs are to be retrieved. + * Must be non-NULL. + * "selector" + * Address of CertSelector whose criteria must be satisfied. + * Must be non-NULL. + * "verifyNode" + * Parent log node for tracking of filtered out certs. + * "pNBIOContext" + * Address at which platform-dependent information is stored if the + * operation is suspended for non-blocking I/O. Must be non-NULL. + * "pCerts" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_CertStore_CertCallback)( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCerts, /* list of PKIX_PL_Cert */ + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_CertContinue + * DESCRIPTION: + * + * This function continues the non-blocking operation initiated by an earlier + * call to the CertCallback function, for the CertStore pointed to by "store". + * If an earlier call did not terminate with the WOULDBLOCK indication (non-NULL + * value returned in "pNBIOContext") calling this function will return a fatal + * error. If the operation is completed the certificates found are placed in a + * List, a pointer to which is stored at "pCerts". If no certificates are found + * which match the CertSelector's criteria, this function stores an empty List + * at "pCerts". In either case, if the operation is completed, NULL is stored + * at "pNBIOContext". + * + * If non-blocking I/O is still pending this function stores platform-dependent + * information at "pNBIOContext" and NULL at "pCerts". A subsequent call to + * PKIX_CertStore_CertContinue is required to finish the operation and to + * obtain the List of Certs. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "store" + * Address of CertStore from which Certs are to be retrieved. + * Must be non-NULL. + * "selector" + * Address of CertSelector whose criteria must be satisfied. + * Must be non-NULL. + * "verifyNode" + * Parent log node for tracking of filtered out certs. + * "pNBIOContext" + * Address at which platform-dependent information is stored if the + * operation is suspended for non-blocking I/O. Must be non-NULL. + * "pCerts" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore 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_CertStore_CertContinue( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCerts, /* list of PKIX_PL_Cert */ + void *plContext); + +typedef PKIX_Error * +(*PKIX_CertStore_CertContinueFunction)( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCerts, /* list of PKIX_PL_Cert */ + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_CRLCallback + * DESCRIPTION: + * + * This callback function retrieves from the CertStore pointed to by "store" + * all the CRLs that match the CRLSelector pointed to by "selector". It + * places these CRLs in a List and stores a pointer to the List at "pCRLs". + * If no CRLs are found which match the CRLSelector's criteria, this function + * stores an empty List at "pCRLs". In either case, if the operation is + * completed, NULL is stored at "pNBIOContext". + * + * A CertStore which uses non-blocking I/O may store platform-dependent + * information at "pNBIOContext" and NULL at "pCrls" to indicate that I/O is + * pending. A subsequent call to PKIX_CertStore_CRLContinue is required to + * finish the operation and to obtain the List of Crls. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "store" + * Address of CertStore from which CRLs are to be retrieved. + * Must be non-NULL. + * "selector" + * Address of CRLSelector whose criteria must be satisfied. + * Must be non-NULL. + * "pCrls" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_CertStore_CRLCallback)( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrls, /* list of PKIX_PL_CRL */ + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_ImportCrlCallback + * DESCRIPTION: + * + * The function imports crl list into a cert store. Stores that + * have local cache may only have that function defined. + * + * PARAMETERS: + * "store" + * Address of CertStore from which CRLs are to be retrieved. + * Must be non-NULL. + * "issuerName" + * Name of the issuer that will be used to track bad der crls. + * "crlList" + * Address on the importing crl list. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_CertStore_ImportCrlCallback)( + PKIX_CertStore *store, + PKIX_PL_X500Name *issuerName, + PKIX_List *crlList, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_CheckRevokationByCrlCallback + * DESCRIPTION: + * + * The function checks revocation status of a cert with specified + * issuer, date. It returns revocation status of a cert and + * a reason code(if any) if a cert was revoked. + * + * PARAMETERS: + * "store" + * Address of CertStore from which CRLs are to be retrieved. + * Must be non-NULL. + * "cert" + * Certificate which revocation status will be checked. + * "issuer" + * Issuer certificate of the "crl". + * "date" + * Date of the revocation check. + * "crlDownloadDone" + * Indicates, that all needed crl downloads are done by the time of + * the revocation check. + * "reasonCode" + * If cert is revoked, returned reason code for which a cert was revoked. + * "revStatus" + * Returned revocation status of the cert. See PKIX_RevocationStatus + * for more details + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_CertStore_CheckRevokationByCrlCallback)( + PKIX_CertStore *store, + PKIX_PL_Cert *cert, + PKIX_PL_Cert *issuer, + PKIX_PL_Date *date, + PKIX_Boolean crlDownloadDone, + CERTCRLEntryReasonCode *reasonCode, + PKIX_RevocationStatus *revStatus, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_CrlContinue + * DESCRIPTION: + * + * This function continues the non-blocking operation initiated by an earlier + * call to the CRLCallback function, for the CertStore pointed to by "store". + * If an earlier call did not terminate with the WOULDBLOCK indication (non-NULL + * value returned in "pNBIOContext") calling this function will return a fatal + * error. If the operation is completed the crls found are placed in a List, a + * pointer to which is stored at "pCrls". If no crls are found which match the + * CRLSelector's criteria, this function stores an empty List at "pCrls". In + * either case, if the operation is completed, NULL is stored at "pNBIOContext". + * + * If non-blocking I/O is still pending this function stores platform-dependent + * information at "pNBIOContext" and NULL at "pCrls". A subsequent call to + * PKIX_CertStore_CrlContinue is required to finish the operation and to + * obtain the List of Crls. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "store" + * Address of CertStore from which Crls are to be retrieved. + * Must be non-NULL. + * "selector" + * Address of CRLSelector whose criteria must be satisfied. + * Must be non-NULL. + * "pNBIOContext" + * Address at which platform-dependent information is stored if the + * operation is suspended for non-blocking I/O. Must be non-NULL. + * "pCrls" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore 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_CertStore_CrlContinue( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrls, /* list of PKIX_PL_CRL */ + void *plContext); + +typedef PKIX_Error * +(*PKIX_CertStore_CrlContinueFunction)( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrls, /* list of PKIX_PL_CRL */ + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_CheckTrustCallback + * DESCRIPTION: + * + * This callback function rechecks "cert's" trust status from the CertStore + * pointed to by "store". + * + * PARAMETERS: + * "store" + * Address of CertStore from which Certs are to be checked. + * Must be non-NULL. + * "cert" + * Address of Cert whose trust status needs to be rechecked. + * Must be non-NULL. + * "pTrusted" + * Address of PKIX_Boolean where the trust status is returned. + * Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertStore Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_CertStore_CheckTrustCallback)( + PKIX_CertStore *store, + PKIX_PL_Cert *cert, + PKIX_Boolean *pTrusted, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_Create + * DESCRIPTION: + * + * Creates a new CertStore and stores it at "pStore". The new CertStore uses + * the CertCallback pointed to by "certCallback" and the CRLCallback pointed + * to by "crlCallback" as its callback functions and uses the Object pointed + * to by "certStoreContext" as its context . Note that this certStoreContext + * must be an Object (although any object type), allowing it to be + * reference-counted and allowing it to provide the standard Object functions + * (Equals, Hashcode, ToString, Compare, Duplicate). Once created, a + * CertStore object is immutable, although the underlying repository can + * change. For example, a CertStore will often be a front-end for a database + * or directory. The contents of that directory can change after the + * CertStore object is created, but the CertStore object remains immutable. + * + * PARAMETERS: + * "certCallback" + * The CertCallback function to be used. Must be non-NULL. + * "crlCallback" + * The CRLCallback function to be used. Must be non-NULL. + * "certContinue" + * The function to be used to resume a certCallback that returned with a + * WOULDBLOCK condition. Must be non-NULL if certStore supports non-blocking + * I/O. + * "crlContinue" + * The function to be used to resume a crlCallback that returned with a + * WOULDBLOCK condition. Must be non-NULL if certStore supports non-blocking + * I/O. + * "trustCallback" + * Address of PKIX_CertStore_CheckTrustCallback which is called to + * verify the trust status of Certs in this CertStore. + * "certStoreContext" + * Address of Object representing the CertStore's context (if any). + * "cachedFlag" + * If TRUE indicates data retrieved from CertStore should be cached. + * "localFlag" + * Boolean value indicating whether this CertStore is local. + * "pStore" + * 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 CertStore 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_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 cachedFlag, + PKIX_Boolean localFlag, + PKIX_CertStore **pStore, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetCertCallback + * DESCRIPTION: + * + * Retrieves a pointer to "store's" Cert callback function and put it in + * "pCallback". + * + * PARAMETERS: + * "store" + * The CertStore whose Cert callback is desired. Must be non-NULL. + * "pCallback" + * Address where Cert callback function 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_CertStore_GetCertCallback( + PKIX_CertStore *store, + PKIX_CertStore_CertCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetCRLCallback + * DESCRIPTION: + * + * Retrieves a pointer to "store's" CRL callback function and put it in + * "pCallback". + * + * PARAMETERS: + * "store" + * The CertStore whose CRL callback is desired. Must be non-NULL. + * "pCallback" + * Address where CRL callback function 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_CertStore_GetCRLCallback( + PKIX_CertStore *store, + PKIX_CertStore_CRLCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetImportCrlCallback + * DESCRIPTION: + * + * Retrieves a pointer to "store's" Import CRL callback function and put it in + * "pCallback". + * + * PARAMETERS: + * "store" + * The CertStore whose CRL callback is desired. Must be non-NULL. + * "pCallback" + * Address where CRL callback function 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_CertStore_GetImportCrlCallback( + PKIX_CertStore *store, + PKIX_CertStore_ImportCrlCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetCheckRevByCrl + * DESCRIPTION: + * + * Retrieves a pointer to "store's" CRL revocation checker callback function + * and put it in "pCallback". + * + * PARAMETERS: + * "store" + * The CertStore whose CRL callback is desired. Must be non-NULL. + * "pCallback" + * Address where CRL callback function 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_CertStore_GetCrlCheckerFn( + PKIX_CertStore *store, + PKIX_CertStore_CheckRevokationByCrlCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetTrustCallback + * DESCRIPTION: + * + * Retrieves the function pointer to the CheckTrust callback function of the + * CertStore pointed to by "store" and stores it at "pCallback". + * + * PARAMETERS: + * "store" + * The CertStore whose CheckTrust callback is desired. Must be non-NULL. + * "pCallback" + * Address where CheckTrust callback function 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_CertStore_GetTrustCallback( + PKIX_CertStore *store, + PKIX_CertStore_CheckTrustCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetCertStoreContext + * DESCRIPTION: + * + * Retrieves a pointer to the Object representing the context (if any) + * of the CertStore pointed to by "store" and stores it at + * "pCertStoreContext". + * + * PARAMETERS: + * "store" + * Address of CertStore whose context is to be stored. Must be non-NULL. + * "pCertStoreContext" + * 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_CertStore_GetCertStoreContext( + PKIX_CertStore *store, + PKIX_PL_Object **pCertStoreContext, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetCertStoreCacheFlag + * DESCRIPTION: + * + * Retrieves the Boolean cache flag of the CertStore pointed to by "store" and + * stores it at "pCachedFlag". + * + * PARAMETERS: + * "store" + * Address of CertStore whose cache flag is to be stored. Must be non-NULL. + * "pCacheFlag" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_CertStore_GetCertStoreCacheFlag( + PKIX_CertStore *store, + PKIX_Boolean *pCacheFlag, + void *plContext); + +/* + * FUNCTION: PKIX_CertStore_GetLocalFlag + * DESCRIPTION: + * + * Retrieves the Boolean localFlag for the CertStore pointed to by "store" and + * stores it at "pLocalFlag". The localFlag is TRUE if the CertStore can + * fulfill a request without performing network I/O. + * + * PARAMETERS: + * "store" + * The CertStore whose Local flag is desired. Must be non-NULL. + * "pCallback" + * Address where the Boolean LocalFlag 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_CertStore_GetLocalFlag( + PKIX_CertStore *store, + PKIX_Boolean *pLocalFlag, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CERTSTORE_H */ diff --git a/security/nss/lib/libpkix/include/pkix_checker.h b/security/nss/lib/libpkix/include/pkix_checker.h new file mode 100644 index 0000000000..97e29a8403 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_checker.h @@ -0,0 +1,394 @@ +/* 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/. */ +/* + * This file defines functions associated with the PKIX_CertChainChecker type. + * + */ + +#ifndef _PKIX_CHECKER_H +#define _PKIX_CHECKER_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_CertChainChecker + * + * PKIX_CertChainCheckers provide a standard way for the caller to insert their + * own custom checks to validate certificates. This may be useful in many + * scenarios, including when the caller wishes to validate private certificate + * extensions. The CheckCallback allows custom certificate processing to take + * place. Additionally, a CertChainChecker can optionally maintain state + * between successive calls to the CheckCallback. This certChainCheckerState + * must be an Object (although any object type), allowing it to be + * reference-counted and allowing it to provide the standard Object functions + * (Equals, Hashcode, ToString, Compare, Duplicate). If the caller wishes + * their CertChainChecker to be used during chain building, their + * certChainCheckerState object must implement an appropriate Duplicate + * function. The builder uses this Duplicate function when backtracking. + * + * Once the caller has created a CertChainChecker object, the caller then + * specifies a CertChainChecker object in a ProcessingParams object + * and passes the ProcessingParams object to PKIX_ValidateChain or + * PKIX_BuildChain, which uses the objects to call the user's callback + * functions as needed during the validation or building process. + * + * A CertChainChecker may be presented certificates in the "reverse" direction + * (from trust anchor to target) or in the "forward" direction (from target to + * trust anchor). All CertChainCheckers must support "reverse checking", while + * support for "forward checking" is optional, but recommended. If "forward + * checking" is not supported, building chains may be much less efficient. The + * PKIX_CertChainChecker_IsForwardCheckingSupported function is used to + * determine whether forward checking is supported, and the + * PKIX_CertChainChecker_IsForwardDirectionExpected function is used to + * determine whether the CertChainChecker has been initialized to expect the + * certificates to be presented in the "forward" direction. + */ + +/* + * FUNCTION: PKIX_CertChainChecker_CheckCallback + * DESCRIPTION: + * + * This callback function checks whether the specified Cert pointed to by + * "cert" is valid using "checker's" internal certChainCheckerState (if any) + * and removes the critical extensions that it processes (if any) from the + * List of OIDs (possibly empty) pointed to by "unresolvedCriticalExtensions". + * If the checker finds that the certificate is not valid, an Error pointer is + * returned. + * + * If the checker uses non-blocking I/O, the address of a platform-dependent + * non-blocking I/O context ("nbioContext") will be stored at "pNBIOContext", + * which the caller may use, in a platform-dependent way, to wait, poll, or + * otherwise determine when to try again. If the checker does not use + * non-blocking I/O, NULL will always be stored at "pNBIOContext". If a non-NULL + * value was stored, on a subsequent call the checker will attempt to complete + * the pending I/O and, if successful, NULL will be stored at "pNBIOContext". + * + * PARAMETERS: + * "checker" + * Address of CertChainChecker whose certChainCheckerState and + * CheckCallback logic is to be used. Must be non-NULL. + * "cert" + * Address of Cert that is to be validated using "checker". + * Must be non-NULL. + * "unresolvedCriticalExtensions" + * Address of List of OIDs that represents the critical certificate + * extensions that have yet to be resolved. This parameter may be + * modified during the function call. Must be non-NULL. + * "pNBIOContext" + * Address at which is stored a platform-dependent structure indicating + * whether checking was suspended for non-blocking I/O. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * 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. + */ +typedef PKIX_Error * +(*PKIX_CertChainChecker_CheckCallback)( + PKIX_CertChainChecker *checker, + PKIX_PL_Cert *cert, + PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */ + void **pNBIOContext, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_Create + * DESCRIPTION: + * + * Creates a new CertChainChecker and stores it at "pChecker". The new + * CertChainChecker uses the CheckCallback pointed to by "callback" as its + * callback function. It uses the Object pointed to by "initialState" (if + * any) as its initial state. As noted above, the initial state Object must + * provide a custom implementation of PKIX_PL_Object_Duplicate if the + * CertChainChecker is to be used during certificate chain building. + * + * A CertChainChecker may be presented certificates in the "reverse" + * direction (from trust anchor to target) or in the "forward" direction + * (from target to trust anchor). All CertChainCheckers must support + * "reverse checking", while support for "forward checking" is optional. The + * CertChainChecker is initialized with two Boolean flags that deal with this + * distinction: "forwardCheckingSupported" and "forwardDirectionExpected". + * If the "forwardCheckingSupported" Boolean flag is TRUE, it indicates that + * this CertChainChecker is capable of checking certificates in the "forward" + * direction (as well as the "reverse" direction, which all CertChainCheckers + * MUST support). The "forwardDirectionExpected" Boolean flag indicates in + * which direction the CertChainChecker should expect the certificates to be + * presented. This is particularly useful for CertChainCheckers that are + * capable of checking in either the "forward" direction or the "reverse" + * direction, but have different processing steps depending on the direction. + * + * The CertChainChecker also uses the List of OIDs pointed to by "extensions" + * as the supported certificate extensions. All certificate extensions that + * the CertChainChecker might possibly recognize and be able to process + * should be included in the List of supported extensions. If "checker" does + * not recognize or process any certificate extensions, "extensions" should + * be set to NULL. + * + * PARAMETERS: + * "callback" + * The CheckCallback function to be used. Must be non-NULL. + * "forwardCheckingSupported" + * A Boolean value indicating whether or not this CertChainChecker is + * capable of checking certificates in the "forward" direction. + * "forwardDirectionExpected" + * A Boolean value indicating whether or not this CertChainChecker should + * be used to check in the "forward" direction. + * "extensions" + * Address of List of OIDs representing the supported extensions. + * "initialState" + * Address of Object representing the CertChainChecker's initial state + * (if any). + * "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_CertChainChecker_Create( + PKIX_CertChainChecker_CheckCallback callback, + PKIX_Boolean forwardCheckingSupported, + PKIX_Boolean forwardDirectionExpected, + PKIX_List *extensions, /* list of PKIX_PL_OID */ + PKIX_PL_Object *initialState, + PKIX_CertChainChecker **pChecker, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_GetCheckCallback + * DESCRIPTION: + * + * Retrieves a pointer to "checker's" Check callback function and puts it in + * "pCallback". + * + * PARAMETERS: + * "checker" + * The CertChainChecker whose Check callback is desired. Must be non-NULL. + * "pCallback" + * Address where Check callback function 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_CertChainChecker_GetCheckCallback( + PKIX_CertChainChecker *checker, + PKIX_CertChainChecker_CheckCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_IsForwardCheckingSupported + * DESCRIPTION: + * + * Checks whether forward checking is supported by the CertChainChecker + * pointed to by "checker" and stores the Boolean result at + * "pForwardCheckingSupported". + * + * A CertChainChecker may be presented certificates in the "reverse" + * direction (from trust anchor to target) or in the "forward" direction + * (from target to trust anchor). All CertChainCheckers must support + * "reverse checking", while support for "forward checking" is optional. This + * function is used to determine whether forward checking is supported. + * + * PARAMETERS: + * "checker" + * The CertChainChecker whose ability to validate certificates in the + * "forward" direction is to be checked. Must be non-NULL. + * "pForwardCheckingSupported" + * Destination of the Boolean result. 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_CertChainChecker_IsForwardCheckingSupported( + PKIX_CertChainChecker *checker, + PKIX_Boolean *pForwardCheckingSupported, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_IsForwardDirectionExpected + * DESCRIPTION: + * + * Checks whether the CertChainChecker pointed to by "checker" has been + * initialized to expect the certificates to be presented in the "forward" + * direction and stores the Boolean result at "pForwardDirectionExpected". + * + * A CertChainChecker may be presented certificates in the "reverse" + * direction (from trust anchor to target) or in the "forward" direction + * (from target to trust anchor). All CertChainCheckers must support + * "reverse checking", while support for "forward checking" is optional. This + * function is used to determine in which direction the CertChainChecker + * expects the certificates to be presented. + * + * PARAMETERS: + * "checker" + * The CertChainChecker that has been initialized to expect certificates + * in either the "forward" or "reverse" directions. Must be non-NULL. + * "pForwardDirectionExpected" + * Destination of the Boolean result. 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_CertChainChecker_IsForwardDirectionExpected( + PKIX_CertChainChecker *checker, + PKIX_Boolean *pForwardDirectionExpected, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_GetSupportedExtensions + * DESCRIPTION: + * + * Retrieves a pointer to a List of OIDs (each OID corresponding to a + * certificate extension supported by the CertChainChecker pointed to by + * "checker") and stores it at "pExtensions". All certificate extensions that + * the CertChainChecker might possibly recognize and be able to process + * should be included in the List of supported extensions. If "checker" does + * not recognize or process any certificate extensions, this function stores + * NULL at "pExtensions". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "checker" + * Address of CertChainChecker whose supported extension OIDs are to be + * stored. Must be non-NULL. + * "pExtensions" + * 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_CertChainChecker_GetSupportedExtensions( + PKIX_CertChainChecker *checker, + PKIX_List **pExtensions, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_GetCertChainCheckerState + * DESCRIPTION: + * + * Retrieves a pointer to a PKIX_PL_Object representing the internal state + * (if any) of the CertChainChecker pointed to by "checker" and stores it at + * "pCertChainCheckerState". + * + * PARAMETERS: + * "checker" + * Address of CertChainChecker whose state is to be stored. + * Must be non-NULL. + * "pCertChainCheckerState" + * 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 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_CertChainChecker_GetCertChainCheckerState( + PKIX_CertChainChecker *checker, + PKIX_PL_Object **pCertChainCheckerState, + void *plContext); + +/* + * FUNCTION: PKIX_CertChainChecker_SetCertChainCheckerState + * DESCRIPTION: + * + * Sets the internal state of the CertChainChecker pointed to by "checker" + * using the Object pointed to by "certChainCheckerState". If "checker" needs + * a NULL internal state, "certChainCheckerState" should be set to NULL. + * + * PARAMETERS: + * "checker" + * Address of CertChainChecker whose state is to be set. Must be non-NULL. + * "certChainCheckerState" + * Address of Object representing internal state. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "checker" + * (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_CertChainChecker_SetCertChainCheckerState( + PKIX_CertChainChecker *checker, + PKIX_PL_Object *certChainCheckerState, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CHECKER_H */ diff --git a/security/nss/lib/libpkix/include/pkix_crlsel.h b/security/nss/lib/libpkix/include/pkix_crlsel.h new file mode 100644 index 0000000000..491e72f43b --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_crlsel.h @@ -0,0 +1,759 @@ +/* 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/. */ +/* + * This file defines functions associated with the PKIX_CRLSelector and the + * PKIX_ComCRLSelParams types. + * + */ + + +#ifndef _PKIX_CRLSEL_H +#define _PKIX_CRLSEL_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_CRLSelector + * + * PKIX_CRLSelectors provide a standard way for the caller to select CRLs + * based on particular criteria. A CRLSelector is typically used by libpkix + * to retrieve CRLs from a CertStore during certificate chain validation or + * building. (see pkix_certstore.h) For example, the caller may wish to only + * select those CRLs that have a particular issuer or a particular value for a + * private CRL extension. The MatchCallback allows the caller to specify the + * custom matching logic to be used by a CRLSelector. + + * By default, the MatchCallback is set to point to the default implementation + * provided by libpkix, which understands how to process the most common + * parameters. If the default implementation is used, the caller should set + * these common parameters using PKIX_CRLSelector_SetCommonCRLSelectorParams. + * Any common parameter that is not set is assumed to be disabled, which means + * the default MatchCallback implementation will select all CRLs without + * regard to that particular disabled parameter. For example, if the + * MaxCRLNumber parameter is not set, MatchCallback will not filter out any + * CRL based on its CRL number. As such, if no parameters are set, all are + * disabled and any CRL will match. If a parameter is disabled, its associated + * PKIX_ComCRLSelParams_Get* function returns a default value of NULL. + * + * If a custom implementation is desired, the default implementation can be + * overridden by calling PKIX_CRLSelector_SetMatchCallback. In this case, the + * CRLSelector can be initialized with a crlSelectorContext, which is where + * the caller can specify the desired parameters the caller wishes to match + * against. Note that this crlSelectorContext must be a PKIX_PL_Object, + * allowing it to be reference-counted and allowing it to provide the standard + * PKIX_PL_Object functions (Equals, Hashcode, ToString, Compare, Duplicate). + * + */ + +/* + * FUNCTION: PKIX_CRLSelector_MatchCallback + * DESCRIPTION: + * + * This callback function determines whether the specified CRL pointed to by + * "crl" matches the criteria of the CRLSelector pointed to by "selector". + * If the CRL matches the CRLSelector's criteria, PKIX_TRUE is stored at + * "pMatch". Otherwise PKIX_FALSE is stored at "pMatch". + * + * PARAMETERS: + * "selector" + * Address of CRLSelector whose MatchCallback logic and parameters are + * to be used. Must be non-NULL. + * "crl" + * Address of CRL that is to be matched using "selector". Must be non-NULL. + * "pMatch" + * Address at which Boolean result is stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * 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. + */ +typedef PKIX_Error * +(*PKIX_CRLSelector_MatchCallback)( + PKIX_CRLSelector *selector, + PKIX_PL_CRL *crl, + PKIX_Boolean *pMatch, + void *plContext); + +/* + * FUNCTION: PKIX_CRLSelector_Create + * DESCRIPTION: + * + * Creates a new CRLSelector using the Object pointed to by + * "crlSelectorContext" (if any) and stores it at "pSelector". As noted + * above, by default, the MatchCallback is set to point to the default + * implementation provided by libpkix, which understands how to process + * ComCRLSelParams. This is overridden if the MatchCallback pointed to by + * "callback" is not NULL, in which case the parameters are specified using + * the Object pointed to by "crlSelectorContext". + * + * PARAMETERS: + * "issue" + * crl issuer. + * "crlDpList" + * distribution points list + * "callback" + * The MatchCallback function to be used. + * "pSelector" + * 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 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_Create( + PKIX_PL_Cert *issuer, + PKIX_List *crlDpList, + PKIX_PL_Date *date, + PKIX_CRLSelector **pSelector, + void *plContext); + +/* + * FUNCTION: PKIX_CRLSelector_GetMatchCallback + * DESCRIPTION: + * + * Retrieves a pointer to "selector's" Match callback function and puts it in + * "pCallback". + * + * PARAMETERS: + * "selector" + * The CRLSelector whose Match callback is desired. Must be non-NULL. + * "pCallback" + * Address where Match callback function 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 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_GetMatchCallback( + PKIX_CRLSelector *selector, + PKIX_CRLSelector_MatchCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_CRLSelector_GetCRLSelectorContext + * DESCRIPTION: + * + * Retrieves a pointer to a PKIX_PL_Object representing the context (if any) + * of the CRLSelector pointed to by "selector" and stores it at + * "pCRLSelectorContext". + * + * PARAMETERS: + * "selector" + * Address of CRLSelector whose context is to be stored. Must be non-NULL. + * "pCRLSelectorContext" + * 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 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_GetCRLSelectorContext( + PKIX_CRLSelector *selector, + void **pCRLSelectorContext, + void *plContext); + +/* + * FUNCTION: PKIX_CRLSelector_GetCommonCRLSelectorParams + * DESCRIPTION: + * + * Retrieves a pointer to the ComCRLSelParams object that represent the common + * parameters of the CRLSelector pointed to by "selector" and stores it at + * "pCommonCRLSelectorParams". If there are no common parameters stored with + * the CRLSelector, this function stores NULL at "pCommonCRLSelectorParams". + * + * PARAMETERS: + * "selector" + * Address of CRLSelector whose ComCRLSelParams are to be stored. + * Must be non-NULL. + * "pCommonCRLSelectorParams" + * 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 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_GetCommonCRLSelectorParams( + PKIX_CRLSelector *selector, + PKIX_ComCRLSelParams **pCommonCRLSelectorParams, + void *plContext); + +/* + * FUNCTION: PKIX_CRLSelector_SetCommonCRLSelectorParams + * DESCRIPTION: + * + * Sets the common parameters for the CRLSelector pointed to by "selector" + * using the ComCRLSelParams pointed to by "commonCRLSelectorParams". + * + * PARAMETERS: + * "selector" + * Address of CRLSelector whose common parameters are to be set. + * Must be non-NULL. + * "commonCRLSelectorParams" + * Address of ComCRLSelParams representing the common parameters. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "selector" + * (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_SetCommonCRLSelectorParams( + PKIX_CRLSelector *selector, + PKIX_ComCRLSelParams *commonCRLSelectorParams, + void *plContext); + +/* PKIX_ComCRLSelParams + * + * PKIX_ComCRLSelParams are X.509 parameters commonly used with CRLSelectors, + * especially determining which CRLs to retrieve from a CertStore. + * PKIX_ComCRLSelParams are typically used with those CRLSelectors that use + * the default implementation of MatchCallback, which understands how to + * process ComCRLSelParams. + */ + +/* + * FUNCTION: PKIX_ComCRLSelParams_Create + * DESCRIPTION: + * + * Creates a new ComCRLSelParams object and stores it at "pParams". + * + * PARAMETERS: + * "pParams" + * 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 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_ComCRLSelParams_Create( + PKIX_ComCRLSelParams **pParams, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetIssuerNames + * DESCRIPTION: + * + * Retrieves a pointer to the List of X500Names (if any) representing the + * issuer names criterion that is set in the ComCRLSelParams pointed to by + * "params" and stores it at "pNames". In order to match against this + * criterion, a CRL's IssuerName must match at least one of the criterion's + * issuer names. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pNames", in which case all CRLs are considered to match. + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose issuer names criterion (if any) is to + * be stored. Must be non-NULL. + * "pNames" + * 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 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_ComCRLSelParams_GetIssuerNames( + PKIX_ComCRLSelParams *params, + PKIX_List **pNames, /* list of PKIX_PL_X500Name */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetIssuerNames + * DESCRIPTION: + * + * Sets the issuer names criterion of the ComCRLSelParams pointed to by + * "params" using a List of X500Names pointed to by "names". In order to match + * against this criterion, a CRL's IssuerName must match at least one of the + * criterion's issuer names. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose issuer names criterion is to be + * set. Must be non-NULL. + * "names" + * Address of List of X500Names used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetIssuerNames( + PKIX_ComCRLSelParams *params, + PKIX_List *names, /* list of PKIX_PL_X500Name */ + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_AddIssuerName + * DESCRIPTION: + * + * Adds to the issuer names criterion of the ComCRLSelParams pointed to by + * "params" using the X500Name pointed to by "name". In order to match + * against this criterion, a CRL's IssuerName must match at least one of the + * criterion's issuer names. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose issuer names criterion is to be added + * to. Must be non-NULL. + * "name" + * Address of X500Name to be added. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_AddIssuerName( + PKIX_ComCRLSelParams *params, + PKIX_PL_X500Name *name, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetCertificateChecking + * DESCRIPTION: + * + * Retrieves a pointer to the Cert (if any) representing the certificate whose + * revocation status is being checked. This is not a criterion. It is simply + * optional information that may help a CertStore find relevant CRLs. + * + * If "params" does not have a certificate set, this function stores NULL at + * "pCert", in which case there is no optional information to provide. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose certificate being checked (if any) is + * to be stored. Must be non-NULL. + * "pCert" + * 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 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_ComCRLSelParams_GetCertificateChecking( + PKIX_ComCRLSelParams *params, + PKIX_PL_Cert **pCert, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetCertificateChecking + * DESCRIPTION: + * + * Sets the ComCRLSelParams pointed to by "params" with the certificate + * (pointed to by "cert") whose revocation status is being checked. This is + * not a criterion. It is simply optional information that may help a + * CertStore find relevant CRLs. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose certificate being checked is to be + * set. Must be non-NULL. + * "cert" + * Address of Cert whose revocation status is being checked + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetCertificateChecking( + PKIX_ComCRLSelParams *params, + PKIX_PL_Cert *cert, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime + * DESCRIPTION: + * + * Retrieves a pointer to the Date (if any) representing the dateAndTime + * criterion that is set in the ComCRLSelParams pointed to by "params" and + * stores it at "pDate". In order to match against this criterion, a CRL's + * thisUpdate component must be less than or equal to the criterion's + * dateAndTime and the CRL's nextUpdate component must be later than the + * criterion's dateAndTime. There is no match if the CRL does not contain a + * nextUpdate component. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pDate", in which case all CRLs are considered to match. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose dateAndTime criterion (if any) is to + * be stored. Must be non-NULL. + * "pDate" + * 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 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_ComCRLSelParams_GetDateAndTime( + PKIX_ComCRLSelParams *params, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime + * DESCRIPTION: + * + * Sets the dateAndTime criterion of the ComCRLSelParams pointed to by + * "params" using a Date pointed to by "date". In order to match against this + * criterion, a CRL's thisUpdate component must be less than or equal to the + * criterion's dateAndTime and the CRL's nextUpdate component must be later + * than the criterion's dateAndTime. There is no match if the CRL does not + * contain a nextUpdate component. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose dateAndTime criterion is to be + * set. Must be non-NULL. + * "date" + * Address of Date used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetDateAndTime( + PKIX_ComCRLSelParams *params, + PKIX_PL_Date *date, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetNISTPolicyEnabled + * DESCRIPTION: + * + * Retrieves a pointer to the Boolean representing the NIST CRL policy + * activation flag that is set in the ComCRLSelParams pointed to by "params" + * and stores it at "enabled". If enabled, a CRL must have nextUpdate field. + * + * Default value for this flag is TRUE. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose NIST CRL policy criterion is to + * be stored. Must be non-NULL. + * "pEnabled" + * 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 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_ComCRLSelParams_GetNISTPolicyEnabled( + PKIX_ComCRLSelParams *params, + PKIX_Boolean *pEnabled, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetNISTPolicyEnabled + * DESCRIPTION: + * + * Sets the NIST crl policy criterion of the ComCRLSelParams pointed to by + * "params" using a "enabled" flag. In order to match against this + * criterion, a CRL's nextUpdate must be available and criterion's + * dataAndTime must be within thisUpdate and nextUpdate time period. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose NIST CRL policy criterion + * is to be set. Must be non-NULL. + * "enabled" + * Address of Bollean used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetNISTPolicyEnabled( + PKIX_ComCRLSelParams *params, + PKIX_Boolean enabled, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetMaxCRLNumber + * DESCRIPTION: + * + * Retrieves a pointer to the BigInt (if any) representing the maxCRLNumber + * criterion that is set in the ComCRLSelParams pointed to by "params" and + * stores it at "pNumber". In order to match against this criterion, a CRL + * must have a CRL number extension whose value is less than or equal to the + * criterion's value. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pNumber", in which case all CRLs are considered to match. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose maxCRLNumber criterion (if any) is to + * be stored. Must be non-NULL. + * "pNumber" + * 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 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_ComCRLSelParams_GetMaxCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt **pNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetMaxCRLNumber + * DESCRIPTION: + * + * Sets the maxCRLNumber criterion of the ComCRLSelParams pointed to by + * "params" using a BigInt pointed to by "number". In order to match against + * this criterion, a CRL must have a CRL number extension whose value is less + * than or equal to the criterion's value. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose maxCRLNumber criterion is to be + * set. Must be non-NULL. + * "number" + * Address of BigInt used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetMaxCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt *number, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_GetMinCRLNumber + * DESCRIPTION: + * + * Retrieves a pointer to the BigInt (if any) representing the minCRLNumber + * criterion that is set in the ComCRLSelParams pointed to by "params" and + * stores it at "pNumber". In order to match against this criterion, a CRL + * must have a CRL number extension whose value is greater than or equal to + * the criterion's value. + * + * If "params" does not have this criterion set, this function stores NULL at + * "pNumber", in which case all CRLs are considered to match. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParams whose minCRLNumber criterion (if any) is to + * be stored. Must be non-NULL. + * "pNumber" + * 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 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_ComCRLSelParams_GetMinCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt **pNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetMinCRLNumber + * DESCRIPTION: + * + * Sets the minCRLNumber criterion of the ComCRLSelParams pointed to by + * "params" using a BigInt pointed to by "number". In order to match against + * this criterion, a CRL must have a CRL number extension whose value is + * greater than or equal to the criterion's value. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose minCRLNumber criterion is to be + * set. Must be non-NULL. + * "number" + * Address of BigInt used to set the criterion + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetMinCRLNumber( + PKIX_ComCRLSelParams *params, + PKIX_PL_BigInt *number, + void *plContext); + +/* + * FUNCTION: PKIX_ComCRLSelParams_SetCrlDp + * DESCRIPTION: + * + * Sets crldp list that can be used to download a crls. + * + * PARAMETERS: + * "params" + * Address of ComCRLSelParamsParams whose minCRLNumber criterion is to be + * set. Must be non-NULL. + * "crldpList" + * A list of CRLDPs. Can be an emptry list. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (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_ComCRLSelParams_SetCrlDp( + PKIX_ComCRLSelParams *params, + PKIX_List *crldpList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_CRLSEL_H */ diff --git a/security/nss/lib/libpkix/include/pkix_errorstrings.h b/security/nss/lib/libpkix/include/pkix_errorstrings.h new file mode 100644 index 0000000000..0519bff0e6 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_errorstrings.h @@ -0,0 +1,1099 @@ +/* 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/. */ + +/* + * This file is intended to be included after different definitions of + * PKIX_ERRORENTRY. It is included in pkixt.h to define a number for each error + * by defining PKIX_ERRORENTRY(x,y) as PKIX_ ## x and then listing thim within + * an enum. It is included in pkix_error.c to define an array of error strings + * by defining PKIX_ERRORENTRY(x,y) #y and then listing thim within an array + * const char * const PKIX_ErrorText[] + */ +/* ALLOCERROR should always be the first */ +PKIX_ERRORENTRY(ALLOCERROR,Allocation Error,SEC_ERROR_NO_MEMORY), +PKIX_ERRORENTRY(ADDHEADERFUNCTIONNOTSUPPORTED,AddHeader function not supported,0), +PKIX_ERRORENTRY(ADDTOVERIFYLOGFAILED,pkix_AddToVerifyLog failed,0), +PKIX_ERRORENTRY(AIAMGRCREATEFAILED,PKIX_PL_AIAMgr_Create failed,0), +PKIX_ERRORENTRY(AIAMGRFINDLDAPCLIENTFAILED,pkix_pl_AiaMgr_FindLDAPClient failed,0), +PKIX_ERRORENTRY(AIAMGRGETAIACERTSFAILED,PKIX_PL_AIAMgr_GetAIACerts failed,SEC_ERROR_UNKNOWN_ISSUER), +PKIX_ERRORENTRY(AIAMGRGETHTTPCERTSFAILED,pkix_pl_AIAMgr_GetHTTPCerts failed,0), +PKIX_ERRORENTRY(AIAMGRGETLDAPCERTSFAILED,pkix_pl_AIAMgr_GetLDAPCerts failed,0), +PKIX_ERRORENTRY(ALGORITHMBYTESLENGTH0,Algorithm bytes length is 0,0), +PKIX_ERRORENTRY(ALLOCATENEWCERTGENERALNAMEFAILED,Allocate new CERTGeneralName failed,0), +PKIX_ERRORENTRY(AMBIGUOUSPARENTAGEOFVERIFYNODE,Ambiguous parentage of VerifyNode,0), +PKIX_ERRORENTRY(ANCHORDIDNOTCHAINTOCERT,Anchor did not chain to Cert,SEC_ERROR_UNKNOWN_ISSUER), +PKIX_ERRORENTRY(ANCHORDIDNOTPASSCERTSELECTORCRITERIA,Anchor did not pass CertSelector criteria,0), +PKIX_ERRORENTRY(APPENDLISTFAILED,pkix_pl_AppendList failed,0), +PKIX_ERRORENTRY(ARGUMENTNOTSTRING,Argument is not a String,0), +PKIX_ERRORENTRY(ARGUMENTSNOTBIGINTS,Arguments are not BigInts,0), +PKIX_ERRORENTRY(ARGUMENTSNOTBYTEARRAYS,Arguments are not Byte Arrays,0), +PKIX_ERRORENTRY(ARGUMENTSNOTDATES,Arguments are not Dates,0), +PKIX_ERRORENTRY(ARGUMENTSNOTOIDS,Arguments are not OIDs,0), +PKIX_ERRORENTRY(ATTEMPTTOADDDUPLICATEKEY,Attempt to add duplicate key,0), +PKIX_ERRORENTRY(ATTEMPTTODECODEANINCOMPLETERESPONSE,Attempt to decode an incomplete response,SEC_ERROR_BAD_DER), +PKIX_ERRORENTRY(ATTEMPTTODECREFALLOCERROR,Attempt to DecRef Alloc Error,0), +PKIX_ERRORENTRY(ATTEMPTTOINCREFALLOCERROR,Attempt to IncRef Alloc Error,0), +PKIX_ERRORENTRY(BADHTTPRESPONSE,Bad Http Response,SEC_ERROR_BAD_HTTP_RESPONSE), +PKIX_ERRORENTRY(BASICCONSTRAINTSCHECKERINITIALIZEFAILED,pkix_BasicConstraintsChecker_Initialize failed,0), +PKIX_ERRORENTRY(BASICCONSTRAINTSCHECKERSTATECREATEFAILED,PKIX_BasicConstraintsCheckerState_Create failed,0), +PKIX_ERRORENTRY(BASICCONSTRAINTSGETCAFLAGFAILED,PKIX_PL_BasicConstraints_GetCAFlag failed,0), +PKIX_ERRORENTRY(BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED,PKIX_PL_BasicConstraints_GetPathLenConstraint failed,0), +PKIX_ERRORENTRY(BASICCONSTRAINTSVALIDATIONFAILEDCA,PKIX_BasicConstraints validation failed: CA Flag not set,SEC_ERROR_CA_CERT_INVALID), +PKIX_ERRORENTRY(BASICCONSTRAINTSVALIDATIONFAILEDLN,PKIX_BasicConstraints validation failed: maximum length mismatch,SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID), +PKIX_ERRORENTRY(BIGINTCOMPARATORFAILED,pkix_pl_BigInt_Comparator failed,0), +PKIX_ERRORENTRY(BIGINTCREATEWITHBYTESFAILED,pkix_pl_BigInt_CreateWithBytes failed,0), +PKIX_ERRORENTRY(BIGINTEQUALSFAILED,PKIX_PL_BigInt_Equals failed,0), +PKIX_ERRORENTRY(BIGINTLENGTH0INVALID,BigInt length 0 is invalid,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(BIGINTTOSTRINGFAILED,pkix_pl_BigInt_ToString failed,0), +PKIX_ERRORENTRY(BIGINTTOSTRINGHELPERFAILED,PKIX_PL_BigInt_ToString_Helper failed,0), +PKIX_ERRORENTRY(BINDREJECTEDBYSERVER,BIND rejected by server,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(BUILDANDVALIDATECHAINFAILED,Failed to build and validate a chain,0), +PKIX_ERRORENTRY(BUILDBUILDSELECTORANDPARAMSFAILED,pkix_Build_BuildSelectorAndParams failed,0), +PKIX_ERRORENTRY(BUILDCOMBINEWITHTRUSTFAILED,pkix_Build_CombineWithTrust failed,0), +PKIX_ERRORENTRY(BUILDFORWARDDEPTHFIRSTSEARCHFAILED,pkix_BuildForwardDepthFirstSearch failed,0), +PKIX_ERRORENTRY(BUILDGATHERCERTSFAILED,pkix_Build_GatherCerts failed,0), +PKIX_ERRORENTRY(BUILDGETRESOURCELIMITSFAILED,pkix_Build_GetResourceLimits failed,0), +PKIX_ERRORENTRY(BUILDINITIATEBUILDCHAINFAILED,pkix_Build_InitiateBuildChain failed,0), +PKIX_ERRORENTRY(BUILDRESULTCREATEFAILED,pkix_BuildResult_Create failed,0), +PKIX_ERRORENTRY(BUILDRESULTGETCERTCHAINFAILED,PKIX_BuildResult_GetCertChain failed,0), +PKIX_ERRORENTRY(BUILDRESULTGETVALIDATERESULTFAILED,PKIX_BuildResult_GetValidateResult failed,0), +PKIX_ERRORENTRY(BUILDREVCHECKPREPFAILED,pkix_Build_RevCheckPrep failed,0), +PKIX_ERRORENTRY(BUILDSORTCANDIDATECERTSFAILED,pkix_Build_SortCandidateCerts failed,0), +PKIX_ERRORENTRY(BUILDSTATECREATEFAILED,pkix_BuildState_Create failed,0), +PKIX_ERRORENTRY(BUILDTRYSHORTCUTFAILED,pkix_Build_TryShortcut failed,0), +PKIX_ERRORENTRY(BUILDUPDATEDATEFAILED,pkix_Build_UpdateDate failed,0), +PKIX_ERRORENTRY(BUILDVALIDATEENTIRECHAINFAILED,pkix_Build_ValidateEntireChain failed,0), +PKIX_ERRORENTRY(BUILDVALIDATIONCHECKERSFAILED,pkix_Build_ValidationCheckers failed,0), +PKIX_ERRORENTRY(BUILDVERIFYCERTIFICATEFAILED,pkix_Build_VerifyCertificate failed,0), +PKIX_ERRORENTRY(BYTEARRAYCOMPARATORFAILED,pkix_pl_ByteArray_Comparator failed,0), +PKIX_ERRORENTRY(BYTEARRAYCREATEFAILED,PKIX_PL_ByteArray_Create failed,0), +PKIX_ERRORENTRY(BYTEARRAYEQUALSFAILED,PKIX_PL_ByteArray_Equals failed,0), +PKIX_ERRORENTRY(BYTEARRAYGETLENGTHFAILED,PKIX_PL_ByteArray_GetLength failed,0), +PKIX_ERRORENTRY(BYTEARRAYGETPOINTERFAILED,PKIX_PL_ByteArray_GetPointer failed,0), +PKIX_ERRORENTRY(BYTEARRAYTOHEXSTRINGFAILED,pkix_pl_ByteArray_ToHexString failed,0), +PKIX_ERRORENTRY(BYTEARRAYTOSTRINGFAILED,PKIX_PL_ByteArray_ToString failed,0), +PKIX_ERRORENTRY(CACHECERTADDFAILED,pkix_CacheCert_Add failed,0), +PKIX_ERRORENTRY(CACHECERTCHAINADDFAILED,pkix_CacheCertChain_Add failed,0), +PKIX_ERRORENTRY(CACHECERTCHAINLOOKUPFAILED,pkix_CacheCertChain_Lookup failed,0), +PKIX_ERRORENTRY(CACHECERTCHAINREMOVEFAILED,pkix_CacheCertChain_Remove failed,0), +PKIX_ERRORENTRY(CACHECRLENTRYADDFAILED,pkix_CacheCrlEntry_Add failed,0), +PKIX_ERRORENTRY(CACHECRLENTRYLOOKUPFAILED,pkix_CacheCrlEntry_Lookup failed,0), +PKIX_ERRORENTRY(CALLOCFAILED,PKIX_PL_Calloc failed,0), +PKIX_ERRORENTRY(CANNOTAQUIRECRLDER,Failed to get DER CRL,0), +PKIX_ERRORENTRY(CANNOTCONVERTCERTUSAGETOPKIXKEYANDEKUSAGES, Fail to convert certificate usage to pkix KU and EKU,0), +PKIX_ERRORENTRY(CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY,Cannot open CollectionCertStoreContext directory,0), +PKIX_ERRORENTRY(CANTCREATESTRING,Cannot create PKIX_PL_String,0), +PKIX_ERRORENTRY(CANTDECODEBINDRESPONSEFROMSERVER,Cannot decode BIND response from server,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(CANTDECODESEARCHRESPONSEFROMSERVER,Cannot decode SEARCH response from server,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(CANTENABLEREVOCATIONWITHOUTCERTSTORE,Cannot enable Revocation without CertStore,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(CANTLOADLIBSMIME,Cannot load smime3 library,0), +PKIX_ERRORENTRY(CANTREREGISTERSYSTEMTYPE,Cannot reregister system type,0), +PKIX_ERRORENTRY(CERTARECERTPOLICIESCRITICALFAILED,PKIX_PL_Cert_AreCertPoliciesCritical failed,0), +PKIX_ERRORENTRY(CERTBASICCONSTRAINTSCREATEFAILED,pkix_pl_CertBasicConstraints_Create failed,0), +PKIX_ERRORENTRY(CERTBASICCONSTRAINTSTOSTRINGFAILED,PKIX_PL_CertBasicConstraints_ToString failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERCHECKCALLBACKFAILED,PKIX_CertChainChecker_CheckCallback failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERCHECKFAILED,PKIX_CertChainChecker_Check failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERCREATEFAILED,PKIX_CertChainChecker_Create failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED,PKIX_CertChainChecker_GetCertChainCheckerState failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERGETCHECKCALLBACKFAILED,PKIX_CertChainChecker_GetCheckCallback failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED,PKIX_CertChainChecker_GetSupportedExtensions failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED,PKIX_CertChainChecker_IsForwardCheckingSupported failed,0), +PKIX_ERRORENTRY(CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED,PKIX_CertChainChecker_SetCertChainCheckerState failed,0), +PKIX_ERRORENTRY(CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION,CertChain fails Certificate Policy validation,SEC_ERROR_POLICY_VALIDATION_FAILED), +PKIX_ERRORENTRY(CERTCHAINTONSSCHAINFAILED,Fail to convert pkix cert chain to nss cert chain,0), +PKIX_ERRORENTRY(CERTCHAINTOPKIXCERTLISTFAILED,Failed to convert nss cert chain to pkix cert chain,0), +PKIX_ERRORENTRY(CERTCHECKCERTTYPEFAILED,Check cert type failed,SEC_ERROR_INADEQUATE_CERT_TYPE), +PKIX_ERRORENTRY(CERTCHECKCERTVALIDTIMESFAILED,CERT_CheckCertValidTimes failed,SEC_ERROR_EXPIRED_CERTIFICATE), +PKIX_ERRORENTRY(CERTCHECKCRLFAILED,Fail to get crl cache issued by cert,0), +PKIX_ERRORENTRY(CERTCHECKEXTENDEDKEYUSAGEFAILED,pkix_pl_Cert_CheckExtendedKeyUsage failed,0), +PKIX_ERRORENTRY(CERTCHECKKEYUSAGEFAILED,CERT_CheckKeyUsage failed,SEC_ERROR_INADEQUATE_KEY_USAGE), +PKIX_ERRORENTRY(CERTCHECKNAMECONSTRAINTSFAILED,PKIX_PL_Cert_CheckNameConstraints failed,0), +PKIX_ERRORENTRY(CERTCHECKVALIDITYFAILED,PKIX_PL_Cert_CheckValidity failed,0), +PKIX_ERRORENTRY(CERTCOMPLETECRLDECODEDENTRIESFAILED,CERT_CompleteCRLDecodedEntries failed,0), +PKIX_ERRORENTRY(CERTCOPYNAMECONSTRAINTFAILED,CERT_CopyNameConstraint failed,0), +PKIX_ERRORENTRY(CERTCOPYNAMEFAILED,CERT_CopyName failed,0), +PKIX_ERRORENTRY(CERTCREATEFAILED,PKIX_PL_Cert_Create failed,0), +PKIX_ERRORENTRY(CERTCREATEGENERALNAMELISTFAILED,CERT_CreateGeneralNameList failed,0), +PKIX_ERRORENTRY(CERTCREATETOLISTFAILED,pkix_pl_Cert_CreateToList failed,0), +PKIX_ERRORENTRY(CERTCREATEWITHNSSCERTFAILED,pkix_pl_Cert_CreateWithNSSCert failed,0), +PKIX_ERRORENTRY(CERTDECODEALTNAMEEXTENSIONFAILED,CERT_DecodeAltNameExtension failed,0), +PKIX_ERRORENTRY(CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED,CERT_DecodeCertificatePoliciesExtension failed,0), +PKIX_ERRORENTRY(CERTDECODEDERCERTIFICATEFAILED,CERT_DecodeDERCertificate failed,0), +PKIX_ERRORENTRY(CERTDECODEDERCRLFAILED,CERT_DecodeDERCrl failed,0), +PKIX_ERRORENTRY(CERTDECODEINHIBITANYEXTENSIONFAILED,CERT_DecodeInhibitAnyExtension failed,0), +PKIX_ERRORENTRY(CERTDECODEINHIBITANYPOLICYFAILED,pkix_pl_Cert_DecodeInhibitAnyPolicy failed,0), +PKIX_ERRORENTRY(CERTDECODEOIDSEQUENCEFAILED,CERT_DecodeOidSequence failed,0), +PKIX_ERRORENTRY(CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED,CERT_DecodePolicyConstraintsExtension failed,0), +PKIX_ERRORENTRY(CERTDECODEPOLICYCONSTRAINTSFAILED,pkix_pl_Cert_DecodePolicyConstraints failed,0), +PKIX_ERRORENTRY(CERTDECODEPOLICYINFOFAILED,pkix_pl_Cert_DecodePolicyInfo failed,0), +PKIX_ERRORENTRY(CERTDECODEPOLICYMAPPINGFAILED,pkix_pl_Cert_DecodePolicyMapping failed,0), +PKIX_ERRORENTRY(CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED,CERT_DecodePolicyMappingsExtension failed,0), +PKIX_ERRORENTRY(CERTEQUALSFAILED,pkix_pl_Cert_Equals failed,0), +PKIX_ERRORENTRY(CERTFAILEDNAMECONSTRAINTSCHECKING,Cert failed NameConstraints checking,SEC_ERROR_CERT_NOT_IN_NAME_SPACE), +PKIX_ERRORENTRY(CERTGETALLSUBJECTNAMESFAILED,PKIX_PL_Cert_GetAllSubjectNames failed,0), +PKIX_ERRORENTRY(CERTGETAUTHORITYINFOACCESSFAILED,PKIX_PL_Cert_GetAuthorityInfoAccess failed,0), +PKIX_ERRORENTRY(CERTGETAUTHORITYKEYIDENTIFIERFAILED,PKIX_PL_Cert_GetAuthorityKeyIdentifier failed,0), +PKIX_ERRORENTRY(CERTGETBASICCONSTRAINTFAILED,PKIX_PL_Cert_GetBasicConstraint failed,0), +PKIX_ERRORENTRY(CERTGETBASICCONSTRAINTSFAILED,PKIX_PL_Cert_GetBasicConstraints failed,0), +PKIX_ERRORENTRY(CERTGETCACHEFLAGFAILED,PKIX_Cert_GetCacheFlag failed,0), +PKIX_ERRORENTRY(CERTGETCERTCERTIFICATEFAILED,PKIX_PL_Cert_GetCERTCertificate failed,0), +PKIX_ERRORENTRY(CERTGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_Cert_GetCriticalExtensionOIDs failed,0), +PKIX_ERRORENTRY(CERTGETCRLDPFAILED,Failed to get cert crldp extension, 0), +PKIX_ERRORENTRY(CERTGETEXTENDEDKEYUSAGEFAILED,PKIX_PL_Cert_GetExtendedKeyUsage failed,0), +PKIX_ERRORENTRY(CERTGETINHIBITANYPOLICYFAILED,PKIX_PL_Cert_GetInhibitAnyPolicy failed,0), +PKIX_ERRORENTRY(CERTGETISSUERFAILED,PKIX_PL_Cert_GetIssuer failed,0), +PKIX_ERRORENTRY(CERTGETNAMECONSTRAINTSFAILED,PKIX_PL_CertGetNameConstraints failed,0), +PKIX_ERRORENTRY(CERTGETNSSSUBJECTALTNAMESFAILED,pkix_pl_Cert_GetNssSubjectAltNames failed,0), +PKIX_ERRORENTRY(CERTGETPOLICYINFORMATIONFAILED,PKIX_PL_Cert_GetPolicyInformation failed,0), +PKIX_ERRORENTRY(CERTGETPOLICYMAPPINGINHIBITEDFAILED,PKIX_PL_Cert_GetPolicyMappingInhibited failed,0), +PKIX_ERRORENTRY(CERTGETPOLICYMAPPINGSFAILED,PKIX_PL_Cert_GetPolicyMappings failed,0), +PKIX_ERRORENTRY(CERTGETREQUIREEXPLICITPOLICYFAILED,PKIX_PL_Cert_GetRequireExplicitPolicy failed,0), +PKIX_ERRORENTRY(CERTGETSERIALNUMBERFAILED,PKIX_PL_Cert_GetSerialNumber failed,0), +PKIX_ERRORENTRY(CERTGETSUBJALTNAMESFAILED,PKIX_PL_Cert_GetSubjAltNames failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTALTNAMESFAILED,PKIX_PL_Cert_GetSubjectAltNames failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTFAILED,PKIX_PL_Cert_GetSubject failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTINFOACCESSFAILED,PKIX_PL_Cert_GetSubjectInfoAccess failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTKEYIDENTIFIERFAILED,PKIX_PL_Cert_GetSubjectKeyIdentifier failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTPUBLICKEYALGIDFAILED,PKIX_PL_Cert_GetSubjectPublicKeyAlgId failed,0), +PKIX_ERRORENTRY(CERTGETSUBJECTPUBLICKEYFAILED,PKIX_PL_Cert_GetSubjectPublicKey failed,0), +PKIX_ERRORENTRY(CERTGETVALIDITYNOTAFTERFAILED,PKIX_PL_Cert_GetValidityNotAfter failed,0), +PKIX_ERRORENTRY(CERTGETVERSIONFAILED,PKIX_PL_Cert_GetVersion failed,0), +PKIX_ERRORENTRY(CERTHASHCODEFAILED,PKIX_PL_Cert_Hashcode failed,0), +PKIX_ERRORENTRY(CERTIFICATEDOESNTHAVEVALIDCRL,Certificate does not have a valid CRL,SEC_ERROR_CRL_NOT_FOUND), +PKIX_ERRORENTRY(CERTIFICATEREVOKED,Certificate is revoked,SEC_ERROR_REVOKED_CERTIFICATE), +PKIX_ERRORENTRY(CERTIMPORTCERTIFICATEFUNCTIONFAILED,CERTImportCertificate function failed,0), +PKIX_ERRORENTRY(CERTISCERTTRUSTEDFAILED,PKIX_PL_Cert_IsCertTrusted failed,SEC_ERROR_UNTRUSTED_CERT), +PKIX_ERRORENTRY(CERTISEXTENSIONCRITICALFAILED,pkix_pl_Cert_IsExtensionCritical failed,0), +PKIX_ERRORENTRY(CERTMERGENAMECONSTRAINTSFAILED,PKIX_PL_Cert_MergeNameConstraints failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED,PKIX_PL_CertNameConstraints_CheckNameInNameSpace failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED,PKIX_PL_CertNameConstraints_CheckNamesInNameSpace failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED,pkix_pl_CertNameConstraints_CheckNameSpaceNssNames failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED,pkix_pl_CertNameConstraints_CopyNssNameConstraints failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEBYMERGEFAILED,pkix_pl_CertNameConstraints_CreateByMerge failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEFAILED,pkix_pl_CertNameConstraints_Create failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEHELPERFAILED,pkix_pl_CertNameConstraints_Create_Helper failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSGETEXCLUDEDFAILED,pkix_pl_CertNameConstraints_GetExcluded failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSGETPERMITTEDFAILED,pkix_pl_CertNameConstraints_GetPermitted failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSMERGEFAILED,pkix_pl_CertNameConstraints_Merge failed,0), +PKIX_ERRORENTRY(CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED,pkix_pl_CertNameConstraints_ToString_Helper failed,0), +PKIX_ERRORENTRY(CERTNAMETOASCIIFAILED,CERT_NameToAscii failed,0), +PKIX_ERRORENTRY(CERTNOTALLOWEDTOSIGNCERTIFICATES,Cert not allowed to sign certificates,SEC_ERROR_CA_CERT_INVALID), +PKIX_ERRORENTRY(CERTPOLICYINFOCREATEFAILED,pkix_pl_CertPolicyInfo_Create failed,0), +PKIX_ERRORENTRY(CERTPOLICYINFOGETPOLICYIDFAILED,PKIX_PL_CertPolicyInfo_GetPolicyId failed,0), +PKIX_ERRORENTRY(CERTPOLICYINFOGETPOLQUALIFIERSFAILED,PKIX_PL_CertPolicyInfo_GetPolQualifiers failed,0), +PKIX_ERRORENTRY(CERTPOLICYMAPCREATEFAILED,pkix_pl_CertPolicyMap_Create failed,0), +PKIX_ERRORENTRY(CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED,PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy failed,0), +PKIX_ERRORENTRY(CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED,PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy failed,0), +PKIX_ERRORENTRY(CERTPOLICYQUALIFIERCREATEFAILED,pkix_pl_CertPolicyQualifier_Create failed,0), +PKIX_ERRORENTRY(CERTREJECTEDBYREVOCATIONCHECKER,Cert rejected by revocation checker,0), +PKIX_ERRORENTRY(CERTSELECTORCHECKFAILED,Validation failed: CertSelector check failed,0), +PKIX_ERRORENTRY(CERTSELECTORCREATEFAILED,PKIX_CertSelector_Create failed,0), +PKIX_ERRORENTRY(CERTSELECTORFAILED,certSelector failed,0), +PKIX_ERRORENTRY(CERTSELECTORGETCOMCERTSELPARAMSFAILED,PKIX_CertSelector_GetComCertSelParams failed,0), +PKIX_ERRORENTRY(CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED,PKIX_CertSelector_GetCommonCertSelectorParam failed,0), +PKIX_ERRORENTRY(CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED,PKIX_CertSelector_GetCommonCertSelectorParams failed,0), +PKIX_ERRORENTRY(CERTSELECTORGETMATCHCALLBACKFAILED,PKIX_CertSelector_GetMatchCallback failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHAUTHKEYIDFAILED,pkix_CertSelector_Match_AuthKeyId failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHBASICCONSTRAINTFAILED,pkix_CertSelector_Match_BasicConstraint failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCALLBACKFAILED,PKIX_CertSelector_MatchCallback failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTIFICATEVALIDFAILED,pkix_CertSelector_Match_CertificateValid failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTISSUERFAILED,cert does not match issuer name,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTOBJECTFAILED,cert does not match cert object,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTSERIALNUMFAILED,cert does not match serial number,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTSUBJECTFAILED,cert does not match subject name,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHCERTVERSIONFAILED,cert does not match cert version,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED,pkix_CertSelector_Match_ExtendedKeyUsage failed,SEC_ERROR_INADEQUATE_CERT_TYPE), +PKIX_ERRORENTRY(CERTSELECTORMATCHFAILED,certSelectorMatch failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHKEYUSAGEFAILED,pkix_CertSelector_Match_KeyUsage failed,SEC_ERROR_INADEQUATE_KEY_USAGE), +PKIX_ERRORENTRY(CERTSELECTORMATCHNAMECONSTRAINTSFAILED,pkix_CertSelector_Match_NameConstraints failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHPATHTONAMESFAILED,pkix_CertSelector_Match_PathToNames failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHPOLICIESFAILED,pkix_CertSelector_Match_Policies failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJALTNAMESFAILED,pkix_CertSelector_Match_SubjAltNames failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJKEYIDFAILED,pkix_CertSelector_Match_SubjKeyId failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJPKALGIDFAILED,pkix_CertSelector_Match_SubjPKAlgId failed,0), +PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJPUBKEYFAILED,pkix_CertSelector_Match_SubjPubKey failed,0), +PKIX_ERRORENTRY(CERTSELECTORSELECTFAILED,pkix_CertSelector_Select failed,0), +PKIX_ERRORENTRY(CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED,PKIX_CertSelector_SetCommonCertSelectorParams failed,0), +PKIX_ERRORENTRY(CERTSETASTRUSTANCHORFAILED, PKIX_PL_Cert_SetAsTrustAnchor failed, 0), +PKIX_ERRORENTRY(CERTSETCACHEFLAGFAILED,PKIX_PL_Cert_SetCacheFlag failed,0), +PKIX_ERRORENTRY(CERTSETTRUSTCERTSTOREFAILED,PKIX_PL_Cert_SetTrustCertStore failed,0), +PKIX_ERRORENTRY(CERTSTORECERTCONTINUEFAILED,PKIX_CertStore_CertContinue failed,0), +PKIX_ERRORENTRY(CERTSTORECERTCONTINUEFUNCTIONFAILED,PKIX_CertStore_CertContinueFunction failed,0), +PKIX_ERRORENTRY(CERTSTORECREATEFAILED,PKIX_CertStore_Create failed,0), +PKIX_ERRORENTRY(CERTSTORECRLCONTINUEFAILED,PKIX_CertStore_CrlContinue failed,0), +PKIX_ERRORENTRY(CERTSTOREEQUALSFAILED,pkix_CertStore_Equals failed,0), +PKIX_ERRORENTRY(CERTSTORECRLCHECKFAILED,Fail to check cert crl revocation,0), +PKIX_ERRORENTRY(CERTSTOREGETCHECKREVBYCRLFAILED,Can not get revocation check function,0), +PKIX_ERRORENTRY(CERTSTOREFAILTOIMPORTCRLLIST,Fail to import crls,0), +PKIX_ERRORENTRY(CERTSTOREGETCERTCALLBACKFAILED,PKIX_CertStore_GetCertCallback failed,0), +PKIX_ERRORENTRY(CERTSTOREGETCERTSTORECACHEFLAGFAILED,PKIX_CertStore_GetCertStoreCacheFlag failed,0), +PKIX_ERRORENTRY(CERTSTOREGETCERTSTORECONTEXTFAILED,PKIX_CertStore_GetCertStoreContext failed,0), +PKIX_ERRORENTRY(CERTSTOREGETCRLCALLBACKFAILED,PKIX_CertStore_GetCRLCallback failed,0), +PKIX_ERRORENTRY(CERTSTOREGETLOCALFLAGFAILED,PKIX_CertStore_GetLocalFlag failed,0), +PKIX_ERRORENTRY(CERTSTOREGETTRUSTCALLBACKFAILED,PKIX_CertStore_GetTrustCallback failed,0), +PKIX_ERRORENTRY(CERTSTOREHASHCODEFAILED,pkix_CertStore_Hashcode failed,0), +PKIX_ERRORENTRY(CERTTOSTRINGFAILED,PKIX_PL_Cert_ToString failed,0), +PKIX_ERRORENTRY(CERTTOSTRINGHELPERFAILED,pkix_pl_Cert_ToString_Helper failed,0), +PKIX_ERRORENTRY(CERTVERIFYCERTTYPEFAILED,PKIX_PL_Cert_VerifyCertAndKeyType failed,0), +PKIX_ERRORENTRY(CERTVERIFYKEYUSAGEFAILED,PKIX_PL_Cert_VerifyKeyUsage failed,0), +PKIX_ERRORENTRY(CERTVERIFYSIGNATUREFAILED,PKIX_PL_Cert_VerifySignature failed,0), +PKIX_ERRORENTRY(CHAINVERIFYCALLBACKFAILED,Chain rejected by Application Callback,SEC_ERROR_APPLICATION_CALLBACK_ERROR), +PKIX_ERRORENTRY(CHECKCERTAGAINSTANCHORFAILED,pkix_CheckCertAgainstAnchor failed,0), +PKIX_ERRORENTRY(CHECKCERTFAILED,pkix_CheckCert failed,0), +PKIX_ERRORENTRY(CHECKCHAINFAILED,pkix_CheckChain failed,0), +PKIX_ERRORENTRY(CHECKTRUSTCALLBACKFAILED,CheckTrustCallback failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTOREPOPULATECERTFAILED,pkix_pl_CollectionCertStoreContext_PopulateCert failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTOREPOPULATECRLFAILED,pkix_pl_CollectionCertStoreContext_PopulateCrl failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTCREATECERTFAILED,pkix_pl_CollectionCertStoreContext_CreateCert failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTCREATECRLFAILED,pkix_pl_CollectionCertStoreContext_CreateCRL failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTGETSELECTCERTFAILED,pkix_pl_CollectionCertStoreContext_GetSelectCert failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED,pkix_pl_CollectionCertStoreContext_GetSelectCRL failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTPOPULATECERTFAILED,pkix_pl_CollectionCertStoreContext_PopulateCert failed,0), +PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTPOPULATECRLFAILED,pkix_pl_CollectionCertStoreContext_PopulateCRL failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSCREATEFAILED,PKIX_ComCertSelParams_Create failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_GetAuthorityKeyIdentifier failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED,PKIX_ComCertSelParams_GetBasicConstraints failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETCERTIFICATEFAILED,PKIX_ComCertSelParams_GetCertificate failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED,PKIX_ComCertSelParams_GetCertificateValid failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED,PKIX_ComCertSelParams_GetExtendedKeyUsage failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETISSUERFAILED,PKIX_ComCertSelParams_GetIssuer failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETKEYUSAGEFAILED,PKIX_ComCertSelParams_GetKeyUsage failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETLEAFCERTFLAGFAILED,PKIX_ComCertSelParams_GetLeafCertFlag failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED,PKIX_ComCertSelParams_GetMatchAllSubjAltNames failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED,PKIX_ComCertSelParams_GetNameConstraints failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETPATHTONAMESFAILED,PKIX_ComCertSelParams_GetPathToNames failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETPOLICYFAILED,PKIX_ComCertSelParams_GetPolicy failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSERIALNUMBERFAILED,PKIX_ComCertSelParams_GetSerialNumber failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJALTNAMESFAILED,PKIX_ComCertSelParams_GetSubjAltNames failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJECTFAILED,PKIX_ComCertSelParams_GetSubject failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_GetSubjKeyIdentifier failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJPKALGIDFAILED,PKIX_ComCertSelParams_GetSubjPKAlgId failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJPUBKEYFAILED,PKIX_ComCertSelParams_GetSubjPubKey failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSGETVERSIONFAILED,PKIX_ComCertSelParams_GetVersion failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED,PKIX_ComCertSelParams_SetBasicConstraints failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETCERTIFICATEFAILED,PKIX_ComCertSelParams_SetCertificate failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED,PKIX_ComCertSelParams_SetCertificateValid failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETEXTKEYUSAGEFAILED,PKIX_ComCertSelParams_SetExtendedKeyUsage failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETKEYUSAGEFAILED,PKIX_ComCertSelParams_SetKeyUsage failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETLEAFCERTFLAGFAILED,PKIX_ComCertSelParams_SetLeafCertFlag failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETNISTPOLICYENABLEDFAILED,PKIX_ComCertSelParams_SetNISTPolicyEnabled failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETPATHTONAMESFAILED,PKIX_ComCertSelParams_SetPathToNames failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETSUBJECTFAILED,PKIX_ComCertSelParams_SetSubject failed,0), +PKIX_ERRORENTRY(COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_SetSubjKeyIdentifier failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSADDISSUERNAMEFAILED,PKIX_ComCRLSelParams_AddIssuerName failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSCREATEFAILED,PKIX_ComCRLSelParams_Create failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSEQUALSFAILED,pkix_ComCRLSelParams_Equals failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSGETDATEANDTIMEFAILED,PKIX_ComCRLSelParams_GetDateAndTime failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSGETISSUERNAMESFAILED,PKIX_ComCRLSelParams_GetIssuerNames failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSGETMAXCRLNUMBERFAILED,PKIX_ComCRLSelParams_GetMaxCRLNumber failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSGETMINCRLNUMBERFAILED,PKIX_ComCRLSelParams_GetMinCRLNumber failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSGETNISTPOLICYENABLEDFAILED,PKIX_ComCRLSelParams_GetNISTPolicyEnabled failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSSETCERTFAILED,PKIX_ComCRLSelParams_SetCertificateChecking failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSSETDATEANDTIMEFAILED,PKIX_ComCRLSelParams_SetDateAndTime failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSTOSTRINGFAILED,pkix_ComCRLSelParams_ToString failed,0), +PKIX_ERRORENTRY(COMCRLSELPARAMSTOSTRINGHELPERFAILED,pkix_ComCRLSelParams_ToString_Helper failed,0), +PKIX_ERRORENTRY(COMPARATORCALLBACKFAILED,comparator callback failed,0), +PKIX_ERRORENTRY(CONTENTTYPENOTPKCS7MIME,Content type is not application/pkcs7-mime,0), +PKIX_ERRORENTRY(CONTENTTYPENOTPKIXCRL,Content type is not application/pkix-crl,SEC_ERROR_BAD_HTTP_RESPONSE), +PKIX_ERRORENTRY(COULDNOTALLOCATEMEMORY,Could not allocate memory,0), +PKIX_ERRORENTRY(COULDNOTALLOCATENEWSTRINGOBJECT,Could not allocate new string object,0), +PKIX_ERRORENTRY(COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST,Could not append child to parent PolicyNode list,0), +PKIX_ERRORENTRY(COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST,Could not append child to parent VerifyNode list,0), +PKIX_ERRORENTRY(COULDNOTCREATEAIAMGROBJECT,Could not create AiaMgr object,0), +PKIX_ERRORENTRY(COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT,Could not create basic constraints state object,0), +PKIX_ERRORENTRY(COULDNOTCREATEBUILDPARAMSOBJECT,Could not create build params object,0), +PKIX_ERRORENTRY(COULDNOTCREATEBUILDRESULTOBJECT,Could not create build result object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTBASICCONSTRAINTSOBJECT,Could not create a CertBasicConstraints object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTCHAINCHECKEROBJECT,Could not create cert chain checker object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTNAMECONSTRAINTSOBJECT,Could not create CertNameConstraints object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYINFOOBJECT,Could not create a CertPolicyInfo object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYMAPOBJECT,Could not create a CertPolicyMap object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYQUALIFIEROBJECT,Could not create a CertPolicyQualifier object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTSELECTOROBJECT,Could not create cert selector object,0), +PKIX_ERRORENTRY(COULDNOTCREATECERTSTOREOBJECT,Could not create CertStore object,0), +PKIX_ERRORENTRY(COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT,Could not create CollectionCertStoreContext object,0), +PKIX_ERRORENTRY(COULDNOTCREATECOMMONCERTSELPARAMSOBJECT,Could not create common certsel params object,0), +PKIX_ERRORENTRY(COULDNOTCREATECOMMONCRLSELECTORPARAMSOBJECT,Could not create common crl selector params object,0), +PKIX_ERRORENTRY(COULDNOTCREATECRLENTRYOBJECT,Could not create CRLENTRY object,0), +PKIX_ERRORENTRY(COULDNOTCREATECRLOBJECT,Could not create CRL object,0), +PKIX_ERRORENTRY(COULDNOTCREATECRLSELECTOROBJECT,Could not create CRLSelector object,0), +PKIX_ERRORENTRY(COULDNOTCREATECRLCHECKEROBJECT,Could not create CRLChecker object,0), +PKIX_ERRORENTRY(COULDNOTCREATEOCSPCHECKEROBJECT,Could not create OcspChecker object,0), +PKIX_ERRORENTRY(COULDNOTCREATEREVOCATIONMETHODOBJECT,Could not create RevocationMethod object,0), +PKIX_ERRORENTRY(COULDNOTCREATEDEFAULTREVOCATIONCHECKEROBJECT,Could not create DefaultRevocationChecker object,0), +PKIX_ERRORENTRY(COULDNOTCREATEEKUCHECKERSTATEOBJECT,Could not create EkuCheckerState object,0), +PKIX_ERRORENTRY(COULDNOTCREATEFORWARDBUILDERSTATEOBJECT,Could not create forwardBuilder state object,0), +PKIX_ERRORENTRY(COULDNOTCREATEHASHTABLEOBJECT,Could not create HashTable object,0), +PKIX_ERRORENTRY(COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT,Could not create HttpDefaultClient object,0), +PKIX_ERRORENTRY(COULDNOTCREATEINFOACCESSOBJECT,Could not create InfoAccess object,0), +PKIX_ERRORENTRY(COULDNOTCREATELDAPDEFAULTCLIENTOBJECT,Could not create LdapDefaultClient object,0), +PKIX_ERRORENTRY(COULDNOTCREATELOCKOBJECT,Could not create lock object,0), +PKIX_ERRORENTRY(COULDNOTCREATELOGGEROBJECT,Could not create Logger object,0), +PKIX_ERRORENTRY(COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT,Could not create NameConstraintsCheckerState object,0), +PKIX_ERRORENTRY(COULDNOTCREATENSSDN,Could not create NSS DN,0), +PKIX_ERRORENTRY(COULDNOTCREATEOBJECT,Could not create object,0), +PKIX_ERRORENTRY(COULDNOTCREATEOBJECTSTORAGE,Could not create object storage,0), +PKIX_ERRORENTRY(COULDNOTCREATEPOLICYCHECKERSTATEOBJECT,Could not create policyChecker state object,0), +PKIX_ERRORENTRY(COULDNOTCREATEPOLICYNODEOBJECT,Could not create a PolicyNode object,0), +PKIX_ERRORENTRY(COULDNOTCREATEPROCESSINGPARAMSOBJECT,Could not create processing params object,0), +PKIX_ERRORENTRY(COULDNOTCREATERESOURCELIMITOBJECT,Could not create ResourceLimit object,0), +PKIX_ERRORENTRY(COULDNOTCREATESIGNATURECHECKERSTATEOBJECT,Could not create SignatureCheckerState object,0), +PKIX_ERRORENTRY(COULDNOTCREATESOCKETOBJECT,Could not create Socket object,0), +PKIX_ERRORENTRY(COULDNOTCREATESTRING,Could not create string,0), +PKIX_ERRORENTRY(COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT,Could not create target cert checker state object,0), +PKIX_ERRORENTRY(COULDNOTCREATETRUSTANCHOROBJECT,Could not create trust anchor object,0), +PKIX_ERRORENTRY(COULDNOTCREATEVALIDATEPARAMSOBJECT,Could not create validate params object,0), +PKIX_ERRORENTRY(COULDNOTCREATEVALIDATERESULTOBJECT,Could not create validate result object,0), +PKIX_ERRORENTRY(COULDNOTCREATEVERIFYNODEOBJECT,Could not create a VerifyNode object,0), +PKIX_ERRORENTRY(COULDNOTCREATEX500NAMEOBJECT,Could not create X500Name object,0), +PKIX_ERRORENTRY(COULDNOTGETFIRSTOBJECTTYPE,Could not get first object type,0), +PKIX_ERRORENTRY(COULDNOTGETSECONDOBJECTTYPE,Could not get second object type,0), +PKIX_ERRORENTRY(COULDNOTGETTYPEOFSECONDARGUMENT,Could not get type of second argument,0), +PKIX_ERRORENTRY(COULDNOTLOOKUPINHASHTABLE,Could not lookup in hashtable,0), +PKIX_ERRORENTRY(COULDNOTMALLOCNEWKEY,Could not malloc new key,0), +PKIX_ERRORENTRY(COULDNOTTESTWHETHERKEYSEQUAL,Could not test whether keys are equal,0), +PKIX_ERRORENTRY(CREATECERTFAILED,CreateCert failed,0), +PKIX_ERRORENTRY(CREATECRLSELECTORDUPLICATEOBJECTFAILED,Create CRLSelector Duplicate Object failed,0), +PKIX_ERRORENTRY(CREATEPROCESSINGPARAMSFAILED,Failed to create processing parameters,0), +PKIX_ERRORENTRY(CRLCHECKERCREATEFAILED,pkix_CRLChecker_Create failed,0), +PKIX_ERRORENTRY(CRLCHECKERINITIALIZEFAILED,pkix_CRLChecker_Initialize failed,0), +PKIX_ERRORENTRY(CRLCHECKERNOLOCALCERTSTOREFOUND,No local cert store found, 0), +PKIX_ERRORENTRY(CRLCHECKERSETSELECTORFAILED,pkix_CRLChecker_SetSelector failed,0), +PKIX_ERRORENTRY(CRLCREATEFAILED,PKIX_PL_CRL_Create failed,0), +PKIX_ERRORENTRY(CRLCREATETOLISTFAILED,pkix_pl_CRL_CreateToList failed,0), +PKIX_ERRORENTRY(CRLCREATEWITHSIGNEDCRLFAILED,pkix_pl_CRL_CreateWithSignedCRL failed,0), +PKIX_ERRORENTRY(CRLCRITICALEXTENSIONOIDSNOTPROCESSED,CRL Critical Extension OIDs not processed,0), +PKIX_ERRORENTRY(CRLDPCREATEFAILED, Failed to create CRL DP,0), +PKIX_ERRORENTRY(CRLENTRYCREATEFAILED,pkix_pl_CRLEntry_Create failed,0), +PKIX_ERRORENTRY(CRLENTRYCRITICALEXTENSIONWASNOTPROCESSED,CRLEntry Critical Extension was not processed,0), +PKIX_ERRORENTRY(CRLENTRYEXTENSIONSEQUALSFAILED,PKIX_PL_CRLEntry_Extensions_Equals failed,0), +PKIX_ERRORENTRY(CRLENTRYEXTENSIONSHASHCODEFAILED,pkix_pl_CRLEntry_Extensions_Hashcode failed,0), +PKIX_ERRORENTRY(CRLENTRYGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_CRLEntry_GetCriticalExtensionOIDs failed,0), +PKIX_ERRORENTRY(CRLENTRYGETCRLENTRYREASONCODEFAILED,PKIX_PL_CRLEntry_GetCRLEntryReasonCode failed,0), +PKIX_ERRORENTRY(CRLENTRYTOSTRINGHELPERFAILED,pkix_pl_CRLEntry_ToString_Helper failed,0), +PKIX_ERRORENTRY(CRLGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_CRL_GetCriticalExtensionOIDs failed,0), +PKIX_ERRORENTRY(CRLGETCRLENTRIESFAILED,pkix_pl_CRL_GetCRLEntries failed,0), +PKIX_ERRORENTRY(CRLGETCRLENTRYFORSERIALNUMBERFAILED,PKIX_PL_CRL_GetCRLEntryForSerialNumber failed,0), +PKIX_ERRORENTRY(CRLGETCRLNUMBERFAILED,PKIX_PL_CRL_GetCRLNumber failed,0), +PKIX_ERRORENTRY(CRLGETISSUERFAILED,PKIX_PL_CRL_GetIssuer failed,0), +PKIX_ERRORENTRY(CRLGETPARTITIONEDFLAGFAILED,PKIX_PL_CRL_IsPartitioned failed,0), +PKIX_ERRORENTRY(CRLGETSIGNATUREALGIDFAILED,pkix_pl_CRL_GetSignatureAlgId failed,0), +PKIX_ERRORENTRY(CRLGETVERSIONFAILED,pkix_pl_CRL_GetVersion failed,0), +PKIX_ERRORENTRY(CRLISSUECERTEXPIRED,CRL issue cert has expired,0), +PKIX_ERRORENTRY(CRLMAXNUMBERRANGEMATCHFAILED,CRL MaxNumber Range Match Failed,0), +PKIX_ERRORENTRY(CRLSELECTORCREATEFAILED,PKIX_CRLSelector_Create failed,0), +PKIX_ERRORENTRY(CRLSELECTORFAILED,crlSelector failed,0), +PKIX_ERRORENTRY(CRLSELECTORGETCOMCERTSELPARAMSFAILED,PKIX_CRLSelector_GetComCertSelParams failed,0), +PKIX_ERRORENTRY(CRLSELECTORGETMATCHCALLBACKFAILED,PKIX_CRLSelector_GetMatchCallback failed,0), +PKIX_ERRORENTRY(CRLSELECTORMATCHCALLBACKFAILED,PKIX_CRLSelector_MatchCallback failed,0), +PKIX_ERRORENTRY(CRLSELECTORMATCHFAILED,crlSelectorMatch failed,0), +PKIX_ERRORENTRY(CRLSELECTORSELECTFAILED,pkix_CRLSelector_Select failed,0), +PKIX_ERRORENTRY(CRLSELECTORSETCOMMONCRLSELECTORPARAMSFAILED,PKIX_CRLSelector_SetCommonCRLSelectorParams failed,0), +PKIX_ERRORENTRY(CRLSELECTORTOSTRINGHELPERFAILED,pkix_CRLSelector_ToString_Helper failed,0), +PKIX_ERRORENTRY(CRLTOSTRINGHELPERFAILED,pkix_pl_CRL_ToString_Helper failed,0), +PKIX_ERRORENTRY(CRLVERIFYUPDATETIMEFAILED,pkix_pl_CRL_VerifyUpdateTime failed,0), +PKIX_ERRORENTRY(DATECREATECURRENTOFFBYSECONDSFAILED,PKIX_PL_Date_Create_CurrentOffBySeconds failed,0), +PKIX_ERRORENTRY(DATECREATEFROMPRTIMEFAILED,pkix_pl_Date_CreateFromPRTime failed,0), +PKIX_ERRORENTRY(DATECREATEUTCTIMEFAILED,PKIX_PL_Date_Create_UTCTime failed,0), +PKIX_ERRORENTRY(DATEDERTIMETOPRTIMEFAILED,Fail to convert encoded time to PRTime,0), +PKIX_ERRORENTRY(DATEEQUALSFAILED,PKIX_PL_Date_Equals failed,0), +PKIX_ERRORENTRY(DATEGETPRTIMEFAILED,pkix_pl_Date_GetPRTime failed,0), +PKIX_ERRORENTRY(DATEHASHCODEFAILED,PKIX_PL_Date_Hashcode failed,0), +PKIX_ERRORENTRY(DATETOSTRINGFAILED,PKIX_Date_ToString failed,0), +PKIX_ERRORENTRY(DATETOSTRINGHELPERFAILED,pkix_pl_Date_ToString_Helper failed,0), +PKIX_ERRORENTRY(DECIPHERONLYKEYUSAGENOTSUPPORTED,decipherOnly key usage not supported,0), +PKIX_ERRORENTRY(DECODINGCERTNAMECONSTRAINTSFAILED,Decoding Cert NameConstraints failed,0), +PKIX_ERRORENTRY(DEFAULTREVCHECKERCREATEFAILED,pkix_DefaultRevChecker_Create failed,0), +PKIX_ERRORENTRY(DEFAULTREVCHECKERINITIALIZEFAILED,pkix_DefaultRevChecker_Initialize failed,0), +PKIX_ERRORENTRY(DEPTHWOULDEXCEEDRESOURCELIMITS,Depth would exceed Resource Limits,SEC_ERROR_OUT_OF_SEARCH_LIMITS), +PKIX_ERRORENTRY(DERASCIITOTIMEFAILED,DER_AsciiToTime failed,0), +PKIX_ERRORENTRY(DERDECODETIMECHOICEFAILED,DER_DecodeTimeChoice failed,0), +PKIX_ERRORENTRY(DERDECODETIMECHOICEFORLASTUPDATEFAILED,DER_DecodeTimeChoice for lastUpdate failed,0), +PKIX_ERRORENTRY(DERDECODETIMECHOICEFORNEXTUPDATEFAILED,DER_DecodeTimeChoice for nextUpdate failed,0), +PKIX_ERRORENTRY(DERENCODETIMECHOICEFAILED,DER_EncodeTimeChoice failed,0), +PKIX_ERRORENTRY(DERGENERALIZEDDAYTOASCIIFAILED,DER_GeneralizedDayToAscii failed,0), +PKIX_ERRORENTRY(DERTIMETOUTCTIMEFAILED,DER_TimeToUTCTime failed,0), +PKIX_ERRORENTRY(DERUTCTIMETOASCIIFAILED,DER_UTCTimeToAscii failed,0), +PKIX_ERRORENTRY(DESTROYSPKIFAILED,pkix_pl_DestroySPKI failed,0), +PKIX_ERRORENTRY(DIRECTORYNAMECREATEFAILED,pkix_pl_DirectoryName_Create failed,0), +PKIX_ERRORENTRY(DUPLICATEIMMUTABLEFAILED,pkix_duplicateImmutable failed,0), +PKIX_ERRORENTRY(CANNOTSORTIMMUTABLELIST,pkix_List_BubbleSort can not sort immutable list,0), +PKIX_ERRORENTRY(EKUCHECKERGETREQUIREDEKUFAILED,pkix_pl_EkuChecker_GetRequiredEku failed,0), +PKIX_ERRORENTRY(EKUCHECKERINITIALIZEFAILED,PKIX_PL_EkuChecker_Initialize failed,0), +PKIX_ERRORENTRY(EKUCHECKERSTATECREATEFAILED,pkix_pl_EkuCheckerState_Create failed,0), +PKIX_ERRORENTRY(ENABLEREVOCATIONWITHOUTCERTSTORE,Enable Revocation without CertStore,0), +PKIX_ERRORENTRY(ERRORALLOCATINGMONITORLOCK,Error Allocating MonitorLock,0), +PKIX_ERRORENTRY(ERRORALLOCATINGRWLOCK,Error Allocating RWLock,0), +PKIX_ERRORENTRY(ERRORCREATINGCHILDSTRING,Error creating child string,0), +PKIX_ERRORENTRY(ERRORCREATINGFORMATSTRING,Error creating format string,0), +PKIX_ERRORENTRY(ERRORCREATINGINDENTSTRING,Error creating indent string,0), +PKIX_ERRORENTRY(ERRORCREATINGITEMSTRING,Error creating item string,0), +PKIX_ERRORENTRY(ERRORCREATINGLISTITEM,Error Creating List Item,0), +PKIX_ERRORENTRY(ERRORCREATINGSUBTREESTRING,Error creating subtree string,0), +PKIX_ERRORENTRY(ERRORCREATINGTABLELOCK,Error creating table lock,0), +PKIX_ERRORENTRY(ERRORFINDINGORPROCESSINGURI,Error finding or processing URI,0), +PKIX_ERRORENTRY(ERRORGETTINGCAUSESTRING,Error getting cause string,0), +PKIX_ERRORENTRY(ERRORGETTINGCLASSTABLEENTRY,Error getting class table entry,0), +PKIX_ERRORENTRY(ERRORGETTINGHASHCODE,Error getting hashcode,0), +PKIX_ERRORENTRY(ERRORGETTINGSECONDOBJECTTYPE,Error getting second object type,0), +PKIX_ERRORENTRY(ERRORINBYTEARRAYHASHCODE,Error in PKIX_PL_ByteArray_Hashcode,0), +PKIX_ERRORENTRY(ERRORINGETTINGDESTRUCTOR,Error in getting destructor,0), +PKIX_ERRORENTRY(ERRORINHASH,Error in pkix_hash,0), +PKIX_ERRORENTRY(ERRORINLISTHASHCODE,Error in PKIX_List_Hashcode,0), +PKIX_ERRORENTRY(ERRORINOBJECTDEFINEDESTROY,Error in object-defined destroy callback,0), +PKIX_ERRORENTRY(ERRORINOIDHASHCODE,Error in PKIX_PL_OID_Hashcode,0), +PKIX_ERRORENTRY(ERRORINRECURSIVEEQUALSCALL,Error in recursive equals call,0), +PKIX_ERRORENTRY(ERRORINSINGLEPOLICYNODETOSTRING,Error in pkix_SinglePolicyNode_ToString,0), +PKIX_ERRORENTRY(ERRORINSINGLEVERIFYNODETOSTRING,Error in pkix_SingleVerifyNode_ToString,0), +PKIX_ERRORENTRY(ERRORINSPRINTF,Error in PKIX_PL_Sprintf,0), +PKIX_ERRORENTRY(ERRORINSTRINGCREATE,Error in PKIX_PL_String_Create,0), +PKIX_ERRORENTRY(ERRORLOCKINGOBJECT,Error locking object,0), +PKIX_ERRORENTRY(ERRORTOSTRINGFAILED,PKIX_Error_ToString failed,0), +PKIX_ERRORENTRY(ERRORTRAVERSINGBUCKET,Error traversing bucket,0), +PKIX_ERRORENTRY(ERRORUNLOCKINGMUTEX,Error unlocking mutex,0), +PKIX_ERRORENTRY(ERRORUNLOCKINGOBJECT,Error unlocking object,0), +PKIX_ERRORENTRY(ESCASCIITOUTF16FAILED,pkix_EscASCII_to_UTF16 failed,0), +PKIX_ERRORENTRY(EXPIRATIONCHECKERINITIALIZEFAILED,pkix_ExpirationChecker_Initialize failed,0), +PKIX_ERRORENTRY(EXTENDEDKEYUSAGECHECKINGFAILED,Extended Key Usage Checking failed,SEC_ERROR_INADEQUATE_CERT_TYPE), +PKIX_ERRORENTRY(EXTENDEDKEYUSAGEUSEROBJECT,Extended Key Usage User Object,0), +PKIX_ERRORENTRY(EXTRACTPARAMETERSFAILED,pkix_ExtractParameters failed,0), +PKIX_ERRORENTRY(FAILEDINENCODINGSEARCHREQUEST,failed in encoding searchRequest,SEC_ERROR_FAILED_TO_ENCODE_DATA), +PKIX_ERRORENTRY(FAILEDTODECODECRL, failed to decode CRL,SEC_ERROR_BAD_DER), +PKIX_ERRORENTRY(FAILEDTOGETNSSTRUSTANCHORS,Failed to get nss trusted roots,0), +PKIX_ERRORENTRY(FAILEDTOGETTRUST, failed to get trust from the cert,0), +PKIX_ERRORENTRY(FAILTOREMOVEDPFROMLIST, failed to remove dp from the list,0), +PKIX_ERRORENTRY(FAILTOSELECTCERTSFROMANCHORS,failed to select certs from anchors,0), +PKIX_ERRORENTRY(FAILUREHASHINGCERT,Failure hashing Cert,0), +PKIX_ERRORENTRY(FAILUREHASHINGERROR,Failure hashing Error,0), +PKIX_ERRORENTRY(FAILUREHASHINGLISTEXPECTEDPOLICYSET,Failure hashing PKIX_List expectedPolicySet,0), +PKIX_ERRORENTRY(FAILUREHASHINGLISTQUALIFIERSET,Failure hashing PKIX_List qualifierSet,0), +PKIX_ERRORENTRY(FAILUREHASHINGOIDVALIDPOLICY,Failure hashing PKIX_PL_OID validPolicy,0), +PKIX_ERRORENTRY(FANOUTEXCEEDSRESOURCELIMITS,Fanout exceeds Resource Limits,0), +PKIX_ERRORENTRY(FETCHINGCACHEDCRLFAILED,Fetching Cached CRLfailed,0), +PKIX_ERRORENTRY(FILLINPROCESSINGPARAMSFAILED,Fail to fill in parameters,0), +PKIX_ERRORENTRY(FILLINRETURNRESULTSFAILED,Fail to fill in return results,0), +PKIX_ERRORENTRY(FIRSTARGUMENTNOTBYTEARRAY,FirstObject is not a ByteArray,0), +PKIX_ERRORENTRY(FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT,First argument is not a CertBasicConstraints Object,0), +PKIX_ERRORENTRY(FIRSTDOUBLEHEXMUSTNOTBE00,First DoubleHex MUST NOT be 00,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(FIRSTFIELDMUSTBEBETWEEN02,First field must be between 0-2,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTANOCSPRESPONSE,FirstObject is not an OcspResponse,0), +PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTLDAPREQUEST,FirstObject is not a LdapRequest,0), +PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTLDAPRESPONSE,FirstObject is not a LdapResponse,0), +PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTOCSPREQUEST,FirstObject is not a OcspRequest,0), +PKIX_ERRORENTRY(FIRSTOBJECTARGUMENTNOTANX500NAME,FirstObject is not an X500Name,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTANERROROBJECT,FirstObject is not an Error object,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTBIGINT,FirstObject not a BigInt,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTBUILDPARAMS,FirstObject is not a BuildParams,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTBUILDRESULT,FirstObject is not a BuildResult,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERT,FirstObject is not a Cert,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTBASICCONSTRAINTS,FirstObject is not a CertBasicConstraints,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTNAMECONSTRAINTS,FirstObject is not a CertNameConstraints,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYINFO,FirstObject is not a CertPolicyInfo,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYMAP,FirstObject is not a CertPolicyMap,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYQUALIFIER,FirstObject is not a CertPolicyQualifier,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCOMCRLSELPARAMS,FirstObject is not a ComCRLSelParams,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCRL,FirstObject is not a CRL,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCRLENTRY,FirstObject is not a CRLEntry,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTCRLSELECTOR,FirstObject is not a CRLSelector,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTDATE,FirstObject is not a Date,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTERROR,FirstObject is not an Error,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTGENERALNAME,FirstObject is not a GeneralName,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTINFOACCESS,FirstObject is not a InfoAccess,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTLIST,FirstObject is not a List,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTLOGGER,FirstObject is not a Logger,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTPOLICYNODE,FirstObject is not a PolicyNode,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTPROCESSINGPARAMS,FirstObject is not a ProcessingParams,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTPUBLICKEY,FirstObject is not a PublicKey,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTRESOURCELIMITS,FirstObject is not a ResourceLimits,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTSTRING,FirstObject is not a String,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTTRUSTANCHOR,FirstObject is not a TrustAnchor,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTVALIDATEPARAMS,FirstObject is not a ValidateParams,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTVALIDATERESULT,FirstObject is not a ValidateResult,0), +PKIX_ERRORENTRY(FIRSTOBJECTNOTVERIFYNODE,FirstObject is not a VerifyNode,0), +PKIX_ERRORENTRY(FIRSTPUBKEYTYPENULLKEY,firstPubKeyType is nullKey,0), +PKIX_ERRORENTRY(FUNCTIONMUSTNOTBEUSED,Function MUST not be used,SEC_ERROR_LIBPKIX_INTERNAL), +PKIX_ERRORENTRY(FORWARDBUILDERSTATEDUMPSTATEFAILED,pkix_ForwardBuilderState_DumpState failed,0), +PKIX_ERRORENTRY(FORWARDBUILDERSTATEISIOPENDINGFAILED,pkix_ForwardBuilderState_IsIOPending failed,0), +PKIX_ERRORENTRY(FORWARDBUILDSTATECREATEFAILED,pkix_ForwardBuildState_Create failed,0), +PKIX_ERRORENTRY(FREEFAILED,PKIX_PL_Free failed,0), +PKIX_ERRORENTRY(GENERALNAMECREATEFAILED,pkix_pl_GeneralName_Create failed,0), +PKIX_ERRORENTRY(GENERALNAMEGETNSSGENERALNAMEFAILED,pkix_pl_GeneralName_GetNssGeneralName failed,0), +PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGDOUBLESLASH,GeneralName string missing double slash,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGLOCATIONTYPE,GeneralName string missing location type,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGSERVERSITE,GeneralName string missing server-site,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(GENERALNAMETOSTRINGFAILED,pkix_pl_GeneralName_ToString failed,0), +PKIX_ERRORENTRY(GENERALNAMETOSTRINGHELPERFAILED,pkix_pl_GeneralName_ToString_Helper failed,0), +PKIX_ERRORENTRY(GENERICCLIENTNOTANLDAPDEFAULTCLIENT,genericClient is not an LdapDefaultClient,0), +PKIX_ERRORENTRY(GETATTRIBUTESCALLEDFORNONENTRYMESSAGE,GetAttributes called for non-Entry message,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(GETCERTSFAILED,getCerts failed,0), +PKIX_ERRORENTRY(GETCRITICALEXTENSIONOIDSFAILED,pkix_GetCriticalExtensionOIDs failed,0), +PKIX_ERRORENTRY(GETCRLSFAILED,getCrls failed,0), +PKIX_ERRORENTRY(GETOIDTOKENFAILED,pkix_pl_getOIDToken failed,0), +PKIX_ERRORENTRY(GETPKIXERRORCODEFAILED,Get PKIX error code failed,0), +PKIX_ERRORENTRY(GETREQCERTIFICATEUSAGESFAILED,Fail to get required certificate usages,0), +PKIX_ERRORENTRY(GETRESULTCODECALLEDFORNONRESULTMESSAGE,GetResultCode called for non-Result message,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(GETRETCERTIFICATEUSAGESFAILED,Fail to get returned certificate usages,0), +PKIX_ERRORENTRY(GETTRUSTEDCERTLISTFAILED,Fail to get trusted cert list,0), +PKIX_ERRORENTRY(HASHFAILED,pkix_hash failed,0), +PKIX_ERRORENTRY(HASHTABLEADDFAILED,PKIX_PL_HashTable_Add failed,0), +PKIX_ERRORENTRY(HASHTABLECREATEFAILED,PKIX_PL_HashTable_Create failed,0), +PKIX_ERRORENTRY(HASHTABLELOOKUPFAILED,PKIX_PL_HashTable_Lookup failed,0), +PKIX_ERRORENTRY(HASHTABLEREMOVEFAILED,PKIX_PL_HashTable_Remove failed,0), +PKIX_ERRORENTRY(HELPERBYTES2ASCIIFAILED,pkix_pl_helperBytes2Ascii failed,0), +PKIX_ERRORENTRY(HELPERBYTES2ASCIINUMTOKENSZERO,pkix_pl_helperBytes2Ascii: numTokens is zero,0), +PKIX_ERRORENTRY(HTTPCERTSTORECREATEREQUESTSESSIONFAILED,pkix_pl_HttpCertStore_CreateRequestSession failed,0), +PKIX_ERRORENTRY(HTTPCERTSTORECREATEWITHASCIINAMEFAILED,PKIX_PL_HttpCertStore_CreateWithAsciiName failed,0), +PKIX_ERRORENTRY(HTTPCERTSTOREDECODECERTPACKAGEFAILED,pkix_pl_HttpCertStore_DecodeCertPackage failed,0), +PKIX_ERRORENTRY(HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED,pkix_HttpCertStore_FindSocketConnection failed,0), +PKIX_ERRORENTRY(HTTPCERTSTOREPROCESSCERTRESPONSEFAILED,pkix_pl_HttpCertStore_ProcessCertResponse failed,0), +PKIX_ERRORENTRY(HTTPCERTSTOREPROCESSCRLRESPONSEFAILED,pkix_pl_HttpCertStore_ProcessCrlResponse failed,0), +PKIX_ERRORENTRY(HTTPCLIENTCREATESESSIONFAILED,HttpClient->CreateSession failed,0), +PKIX_ERRORENTRY(HTTPCLIENTININVALIDSTATE,HttpClient in invalid state,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED,pkix_pl_HttpDefaultClient_ConnectContinue failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTCREATEFAILED,pkix_pl_HttpDefaultClient_Create failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTDISPATCHFAILED,pkix_pl_HttpDefaultClient_Dispatch failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED,pkix_pl_HttpDefaultClient_HdrCheckComplete failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTINILLEGALSTATE,HttpDefaultClient in illegal state,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVBODYCONTINUEFAILED,pkix_pl_HttpDefaultClient_RecvBodyContinue failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVBODYFAILED,pkix_pl_HttpDefaultClient_RecvBody failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED,pkix_pl_HttpDefaultClient_RecvHdrContinue failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVHDRFAILED,pkix_pl_HttpDefaultClient_RecvHdr failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTSENDCONTINUEFAILED,pkix_pl_HttpDefaultClient_SendContinue failed,0), +PKIX_ERRORENTRY(HTTPDEFAULTCLIENTSENDFAILED,pkix_pl_HttpDefaultClient_Send failed,0), +PKIX_ERRORENTRY(HTTPSERVERERROR,HTTP Server Error,0), +PKIX_ERRORENTRY(ILLEGALCHARACTERINESCAPEDASCII,Illegal character in Escaped ASCII String,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(ILLEGALCHARACTERINOID,Illegal character in OID,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(ILLEGALDOTINOID,Illegal period in OID,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(ILLEGALSURROGATEPAIR,Illegal surrogate pair in EscapedASCII,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(ILLEGALUNICODECHARACTER,Illegal Unicode character in EscapedASCII,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(ILLEGALUSEOFAMP,Illegal use of ampersand character,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(IMPOSSIBLECRITERIONFORCRLQUERY,Impossible criterion for Crl Query,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(INDEXOUTOFBOUNDS,Index out of bounds,SEC_ERROR_LIBPKIX_INTERNAL), +PKIX_ERRORENTRY(INESCAPEDASCII,in EscapedASCII,0), +PKIX_ERRORENTRY(INFOACCESSCREATEFAILED,pkix_pl_InfoAccess_Create failed,0), +PKIX_ERRORENTRY(INFOACCESSCREATELISTFAILED,pkix_pl_InfoAccess_CreateList failed,0), +PKIX_ERRORENTRY(INFOACCESSGETLOCATIONFAILED,PKIX_PL_InfoAccess_GetLocation failed,0), +PKIX_ERRORENTRY(INFOACCESSGETLOCATIONTYPEFAILED,PKIX_PL_InfoAccess_GetLocationType failed,0), +PKIX_ERRORENTRY(INFOACCESSGETMETHODFAILED,PKIX_PL_InfoAccess_GetMethod failed,0), +#ifndef NSS_PKIX_NO_LDAP +PKIX_ERRORENTRY(INFOACCESSPARSELOCATIONFAILED,pkix_pl_InfoAccess_ParseLocation failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +#endif +PKIX_ERRORENTRY(INFOACCESSPARSETOKENSFAILED,pkix_pl_InfoAccess_ParseTokens failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(INITIALIZECHECKERSFAILED,pkix_InitializeCheckers failed,0), +PKIX_ERRORENTRY(INITIALIZEFAILED,PKIX_PL_Initialize failed,0), +PKIX_ERRORENTRY(INPUTLISTMUSTBEHEADER,Input List must be header,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(INPUTLISTSMUSTBELISTHEADERS,Input Lists must be list headers,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(INSUFFICIENTCRITERIAFORCERTQUERY,Insufficient criteria for Cert query,0), +PKIX_ERRORENTRY(INSUFFICIENTCRITERIAFORCRLQUERY,Insufficient criteria for Crl Query,0), +PKIX_ERRORENTRY(INTRUSTEDCERT,in Trusted Cert,0), +PKIX_ERRORENTRY(INVALIDCHARACTERINBIGINT,Invalid character in BigInt,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(INVALIDDERENCODINGFOROID,Invalid DER-encoding for OID,0), +PKIX_ERRORENTRY(INVALIDENCODINGOIDTOKENVALUETOOBIG,Invalid encoding: OID token value too big,0), +PKIX_ERRORENTRY(INVALIDPOLICYMAPPINGINCLUDESANYPOLICY,Invalid policyMapping includes anyPolicy,SEC_ERROR_INVALID_POLICY_MAPPING), +PKIX_ERRORENTRY(INVALIDREVOCATIONMETHOD,Invalid revocation method,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(INVALIDSIGNINGCERTINOCSPRESPONSE,Invalid signing Cert in OCSP response,SEC_ERROR_OCSP_INVALID_SIGNING_CERT), +PKIX_ERRORENTRY(INVALIDSTATUS,INVALID STATUS,0), +PKIX_ERRORENTRY(INVALIDSTORETYPEFORSETTINGCONFIGDIR,Invalid Store type for Setting ConfigDir,0), +PKIX_ERRORENTRY(IPADDRBYTES2ASCIIDATALENGTHZERO,pkix_pl_ipAddrBytes2Ascii: data length is zero,0), +PKIX_ERRORENTRY(IPADDRBYTES2ASCIIFAILED,pkix_pl_ipAddrBytes2Ascii failed,0), +PKIX_ERRORENTRY(ISCERTSELFISSUEDFAILED,pkix_IsCertSelfIssued failed,0), +PKIX_ERRORENTRY(ISCERTSELFISSUEFAILED,pkix_IsCertSelfIssue failed,0), +PKIX_ERRORENTRY(KEYUSAGEKEYCERTSIGNBITNOTON,Validation failed: KeyUsage KeyCertSign bit is not on,SEC_ERROR_CA_CERT_INVALID), +PKIX_ERRORENTRY(KEYUSAGEKEYCRLSIGNBITNOTON,Validation failed: KeyUsage CRLSign bit is not on,0), +PKIX_ERRORENTRY(LDAPCERTSTOREBUILDCERTLISTFAILED,pkix_pl_LdapCertStore_BuildCertList failed,0), +PKIX_ERRORENTRY(LDAPCERTSTOREBUILDCRLLISTFAILED,pkix_pl_LdapCertStore_BuildCrlList failed,0), +PKIX_ERRORENTRY(LDAPCERTSTOREDECODECROSSCERTPAIRFAILED,pkix_pl_LdapCertStore_DecodeCrossCertPair failed,0), +PKIX_ERRORENTRY(LDAPCERTSTOREDESTROYAVALISTFAILED,pkix_pl_LdapCertStore_DestroyAVAList failed,0), +PKIX_ERRORENTRY(LDAPCERTSTOREINILLEGALSTATE,LDAP CertStore in illegal state,0), +PKIX_ERRORENTRY(LDAPCERTSTOREMAKENAMEAVALISTFAILED,pkix_pl_LdapCertStore_MakeNameAVAList failed,0), +PKIX_ERRORENTRY(LDAPCLIENTINITIATEREQUESTFAILED,PKIX_PL_LdapClient_InitiateRequest failed,0), +PKIX_ERRORENTRY(LDAPCLIENTRESUMEREQUESTFAILED,PKIX_PL_LdapClient_ResumeRequest failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTABANDONCONTINUEFAILED,pkix_pl_LdapDefaultClient_AbandonContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDCONTINUEFAILED,pkix_pl_LdapDefaultClient_BindContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDFAILED,pkix_pl_LdapDefaultClient_Bind failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED,pkix_pl_LdapDefaultClient_BindResponseContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_BindResponse failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED,pkix_pl_LdapDefaultClient_ConnectContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCREATEBYNAMEFAILED,PKIX_PL_LdapDefaultClient_CreateByName failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCREATEHELPERFAILED,pkix_pl_LdapDefaultClient_CreateHelper failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_DecodeBindResponse failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTDISPATCHFAILED,pkix_pl_LdapDefaultClient_Dispatch failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTINILLEGALSTATE,LDAP DefaultClient in illegal state,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEABANDONFAILED,pkix_pl_LdapDefaultClient_MakeAbandon failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEANDFILTERFAILED,pkix_pl_LdapDefaultClient_MakeAndFilter failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEBINDFAILED,pkix_pl_LdapDefaultClient_MakeBind failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEUNBINDFAILED,pkix_pl_LdapDefaultClient_MakeUnbind failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED,pkix_pl_LdapDefaultClient_RecvCheckComplete failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVCONTINUEFAILED,pkix_pl_LdapDefaultClient_RecvContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVFAILED,pkix_pl_LdapDefaultClient_Recv failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVINITIALFAILED,pkix_pl_LdapDefaultClient_RecvInitial failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVNONINITIALFAILED,pkix_pl_LdapDefaultClient_RecvNonInitial failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTSENDCONTINUEFAILED,pkix_pl_LdapDefaultClient_SendContinue failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTSENDFAILED,pkix_pl_LdapDefaultClient_Send failed,0), +PKIX_ERRORENTRY(LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_VerifyBindResponse failed,0), +PKIX_ERRORENTRY(LDAPREQUESTATTRSTRINGTOBITFAILED,pkix_pl_LdapRequest_AttrStringToBit failed,0), +PKIX_ERRORENTRY(LDAPREQUESTATTRTYPETOBITFAILED,pkix_pl_LdapRequest_AttrTypeToBit failed,0), +PKIX_ERRORENTRY(LDAPREQUESTCREATEFAILED,pkix_pl_LdapRequest_Create failed,0), +PKIX_ERRORENTRY(LDAPREQUESTENCODEATTRSFAILED,pkix_pl_LdapRequest_EncodeAttrs failed,0), +PKIX_ERRORENTRY(LDAPREQUESTGETENCODEDFAILED,pkix_pl_LdapRequest_GetEncoded failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEAPPENDFAILED,pkix_pl_LdapResponse_Append failed,0), +PKIX_ERRORENTRY(LDAPRESPONSECREATEFAILED,pkix_pl_LdapResponseCreate failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEDECODEFAILED,pkix_pl_LDAPResponse_Decode failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEGETCAPACITYFAILED,pkix_pl_LdapResponse_GetCapacity failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEGETMESSAGEFAILED,pkix_pl_LdapResponse_GetMessage failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEGETMESSAGETYPEFAILED,pkix_pl_LdapResponse_GetMessageType failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEGETRESULTCODEFAILED,pkix_pl_LdapResponse_GetResultCode failed,0), +PKIX_ERRORENTRY(LDAPRESPONSEISCOMPLETEFAILED,pkix_pl_LdapResponse_IsComplete failed,0), +PKIX_ERRORENTRY(LISTAPPENDFAILED,PKIX_List_Append failed,0), +PKIX_ERRORENTRY(LISTAPPENDITEMFAILED,PKIX_List_AppendItem failed,0), +PKIX_ERRORENTRY(LISTAPPENDLISTFAILED,pkix_List_AppendList failed,0), +PKIX_ERRORENTRY(LISTAPPENDUNIQUEFAILED,pkix_List_AppendUnique failed,0), +PKIX_ERRORENTRY(LISTBUBBLESORTFAILED,pkix_List_BubbleSort failed,0), +PKIX_ERRORENTRY(LISTCONTAINSFAILED,pkix_List_Contains failed,0), +PKIX_ERRORENTRY(LISTCREATEFAILED,PKIX_List_Create failed,0), +PKIX_ERRORENTRY(LISTCREATEINTERNALFAILED,pkix_List_Create_Internal failed,0), +PKIX_ERRORENTRY(LISTDELETEITEMFAILED,PKIX_List_DeleteItem failed,0), +PKIX_ERRORENTRY(LISTDUPLICATEFAILED,pkix_List_Duplicate failed,0), +PKIX_ERRORENTRY(LISTEQUALSFAILED,PKIX_List_Equals failed,0), +PKIX_ERRORENTRY(LISTGETELEMENTFAILED,pkix_List_GetElement failed,0), +PKIX_ERRORENTRY(LISTGETITEMFAILED,PKIX_List_GetItem failed,0), +PKIX_ERRORENTRY(LISTGETLENGTHFAILED,PKIX_List_GetLength failed,0), +PKIX_ERRORENTRY(LISTHASHCODEFAILED,pkix_List_Hashcode failed,0), +PKIX_ERRORENTRY(LISTINSERTITEMFAILED,PKIX_List_InsertItem failed,0), +PKIX_ERRORENTRY(LISTISEMPTYFAILED,PKIX_List_IsEmpty failed,0), +PKIX_ERRORENTRY(LISTMERGEFAILED,pkix_List_MergeList failed,0), +PKIX_ERRORENTRY(LISTQUICKSORTFAILED,pkix_List_QuickSort failed,0), +PKIX_ERRORENTRY(LISTREMOVEFAILED,pkix_List_Remove failed,0), +PKIX_ERRORENTRY(LISTREMOVEITEMSFAILED,pkix_List_RemoveItems failed,0), +PKIX_ERRORENTRY(LISTREVERSELISTFAILED,PKIX_List_ReverseList failed,0), +PKIX_ERRORENTRY(LISTSETIMMUTABLEFAILED,PKIX_List_SetImmutable failed,0), +PKIX_ERRORENTRY(LISTSETITEMFAILED,PKIX_List_SetItem failed,0), +PKIX_ERRORENTRY(LISTTOSTRINGFAILED,pkix_List_ToString failed,0), +PKIX_ERRORENTRY(LISTTOSTRINGHELPERFAILED,pkix_List_ToString Helper failed,0), +PKIX_ERRORENTRY(LOCATIONSTRINGNOTPROPERLYTERMINATED,Location string not properly terminated,0), +PKIX_ERRORENTRY(LOCKHASNONZEROREADCOUNT,Lock has non-zero read count,0), +PKIX_ERRORENTRY(LOCKOBJECTFAILED,pkix_LockObject failed,0), +PKIX_ERRORENTRY(LOGGERDUPLICATEFAILED,pkix_Logger_Duplicate failed,0), +PKIX_ERRORENTRY(LOGGINGLEVELEXCEEDSMAXIMUM,Logging Level exceeds Maximum,0), +PKIX_ERRORENTRY(LOOPDISCOVEREDDUPCERTSNOTALLOWED,Loop discovered: duplicate certificates not allowed,SEC_ERROR_UNTRUSTED_ISSUER), +PKIX_ERRORENTRY(LOOPOFERRORCAUSEDETECTED,Loop of error causes detected,0), +PKIX_ERRORENTRY(MAJORVERSIONSDONTMATCH,Major versions do not match,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(MALLOCFAILED,PKIX_PL_Malloc failed,0), +PKIX_ERRORENTRY(MEMLEAKGENERATEDERROR,Error generated for memory leak testing,SEC_ERROR_NO_MEMORY), +PKIX_ERRORENTRY(MINORVERSIONNOTBETWEENDESIREDMINANDMAX,Minor version does not fall between desired minimum and maximum,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(MISSINGDSAPARAMETERS,Missing DSA parameters in Trusted Cert,SEC_ERROR_INVALID_KEY), +PKIX_ERRORENTRY(MONITORLOCKCREATEFAILED,PKIX_PL_MonitorLock_Create failed,0), +PKIX_ERRORENTRY(MONITORLOCKENTERFAILED,PKIX_PL_MonitorLock_Enter failed,0), +PKIX_ERRORENTRY(MONITORLOCKEXITFAILED,PKIX_PL_MonitorLock_Exit failed,0), +PKIX_ERRORENTRY(MUTEXLOCKFAILED,PKIX_PL_Mutex_Lock failed,0), +PKIX_ERRORENTRY(NAMECHAININGCHECKERINITIALIZEFAILED,pkix_NameChainingChecker_Initialize failed,0), +PKIX_ERRORENTRY(NAMECHAININGCHECKFAILED,Name Chaining Check failed,SEC_ERROR_UNKNOWN_ISSUER), +PKIX_ERRORENTRY(NAMECOMPONENTWITHNOEQ,Name Component with no equal sign,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(NAMECONSTRAINTSCHECKERINITIALIZEFAILED,pkix_NameConstraintsChecker_Initialize failed,0), +PKIX_ERRORENTRY(NAMECONSTRAINTSCHECKERSTATECREATEFAILED,pkix_NameConstraintsCheckerState_Create failed,0), +PKIX_ERRORENTRY(NAMETYPENOTSUPPORTED,name type not supported,0), +PKIX_ERRORENTRY(NOCONTENTTYPEINHTTPRESPONSE,No content type in Http Response,SEC_ERROR_BAD_HTTP_RESPONSE), +PKIX_ERRORENTRY(NODESMISSINGFROMCHAIN,Nodes missing from chain,0), +PKIX_ERRORENTRY(NOREGISTEREDHTTPCLIENT,No registered Http Client,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(NORESPONSEDATAINHTTPRESPONSE,No responseData in Http Response,SEC_ERROR_BAD_HTTP_RESPONSE), +PKIX_ERRORENTRY(NOTARGETCERTSUPPLIED,No target cert supplied,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(NOTCONFORMINGCRLDP,Cert CRL DP does not conform to the rfc, 0), +PKIX_ERRORENTRY(NOTDERPACKAGE,Not a DER package,0), +PKIX_ERRORENTRY(NOTENOUGHNAMECOMPONENTSINGENERALNAME,Not enough name components in GeneralName,SEC_ERROR_BAD_INFO_ACCESS_LOCATION), +PKIX_ERRORENTRY(NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED,Failed to convert nss certificate usage to pkix ku and eku data structures,0), +PKIX_ERRORENTRY(NSSCONTEXTCREATEFAILED,PKIX_PL_NssContext_Create failed,0), +PKIX_ERRORENTRY(NSSCONTEXTDESTROYFAILED,PKIX_PL_NssContext_Destroy failed,0), +PKIX_ERRORENTRY(NSSCONTEXTGETCHECKALLUSAGESFAILED, pkix_pl_NssContext_GetCheckAllUsages failed,0), +PKIX_ERRORENTRY(NSSCONTEXTGETRETURNUSAGESFAILED, pkix_pl_NssContext_GetReturnUsages failed,0), +PKIX_ERRORENTRY(NSSCONTEXTGETWINCXFAILED,pkix_pl_NssContext_GetWincx failed,0), +PKIX_ERRORENTRY(NSSCONTEXTSETCERTSIGNCHECKFAILED, pkix_pl_NssContext_SetCertSignatureCheck,0), +PKIX_ERRORENTRY(NSSCONTEXTSETCERTUSAGEFAILED, pkix_pl_NssContext_SetCertUsage failed,0), +PKIX_ERRORENTRY(NSSCONTEXTSETCHECKALLUSAGESFAILED, pkix_pl_NssContext_SetCheckAllUsages failed,0), +PKIX_ERRORENTRY(NSSCONTEXTSETRETURNEDCERTUSAGEFAILED, pkix_pl_NssContext_SetReturnedCertUsage,0), +PKIX_ERRORENTRY(NSSCONTEXTSETRETURNUSAGESFAILED, pkix_pl_NssContext_SetReturnUsages failed,0), +PKIX_ERRORENTRY(NSSCONTEXTVALIDATINGRESPONDERCERTFAILED,pkix_pl_NssContext_ValidatingResponderCert failed,0), +PKIX_ERRORENTRY(NSSTRUSTEDLISTISEMPTY,nss trusted roots list is empty,0), +PKIX_ERRORENTRY(NULLARGUMENT,Null argument,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(NUMBUCKETSEQUALSZERO,NumBuckets equals zero,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(OBJECTALLOCFAILED,PKIX_PL_Object_Alloc failed,0), +PKIX_ERRORENTRY(OBJECTARGUMENTNOTPOLICYMAP,object argument is not a PolicyMap,0), +PKIX_ERRORENTRY(OBJECTCOMPARATORFAILED,PKIX_PL_Object_Comparator failed,0), +PKIX_ERRORENTRY(OBJECTDEFINED,object-defined ,0), +PKIX_ERRORENTRY(OBJECTDUPLICATECERTFAILED,PKIX_PL_Object_Duplicate Cert failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATECONTEXTFAILED,PKIX_PL_Object_Duplicate Context failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEDATEFAILED,PKIX_PL_Object_Duplicate Date failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEFAILED,PKIX_PL_Object_Duplicate failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEISSUERNAMESFAILED,PKIX_PL_Object_Duplicate IssuerNames failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATELISTFAILED,PKIX_PL_Object_Duplicate List failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEMAXCRLNUMBERFAILED,PKIX_PL_Object_Duplicate maxCRLNumber failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEMINCRLNUMBERFAILED,PKIX_PL_Object_Duplicate minCRLNumber failed,0), +PKIX_ERRORENTRY(OBJECTDUPLICATEPARAMSFAILED,PKIX_PL_Object_Duplicate Params failed,0), +PKIX_ERRORENTRY(OBJECTEQUALSFAILED,PKIX_PL_Object_Equals failed,0), +PKIX_ERRORENTRY(OBJECTEQUALSFAILEDONCHILDREN,PKIX_PL_Object_Equals failed on children,0), +PKIX_ERRORENTRY(OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS,PKIX_PL_Object_Equals failed on expectedPolicySets,0), +PKIX_ERRORENTRY(OBJECTGETTYPEFAILED,PKIX_PL_Object_GetType failed,0), +PKIX_ERRORENTRY(OBJECTHASHCODEFAILED,PKIX_PL_Object_Hashcode failed,0), +PKIX_ERRORENTRY(OBJECTINVALIDATECACHEFAILED,PKIX_PL_Object_InvalidateCache failed,0), +PKIX_ERRORENTRY(OBJECTISTYPEREGISTEREDFAILED,PKIX_PL_Object_IsTypeRegistered failed,0), +PKIX_ERRORENTRY(OBJECTLOCKFAILED,PKIX_PL_Object_Lock failed,0), +PKIX_ERRORENTRY(OBJECTNOTAIAMGR,Object is not a AIAMgr,0), +PKIX_ERRORENTRY(OBJECTNOTANEKUCHECKERSTATE,Object is not an EKU Checker State,0), +PKIX_ERRORENTRY(OBJECTNOTANERROR,Object is not an Error,0), +PKIX_ERRORENTRY(OBJECTNOTANHTTPCERTSTORECONTEXT,Object is not an HttpCertStoreContext,0), +PKIX_ERRORENTRY(OBJECTNOTANHTTPDEFAULTCLIENT,Object is not an HttpDefaultClient,0), +PKIX_ERRORENTRY(OBJECTNOTANINFOACCESS,Object is not an InfoAccess,0), +PKIX_ERRORENTRY(OBJECTNOTANLDAPDEFAULTCLIENT,Object is not an LdapDefaultClient,0), +PKIX_ERRORENTRY(OBJECTNOTANOCSPRESPONSE,Object is not an OcspResponse,0), +PKIX_ERRORENTRY(OBJECTNOTANOID,Object is not an OID,0), +PKIX_ERRORENTRY(OBJECTNOTANSOCKET,Object is not an Socket,0), +PKIX_ERRORENTRY(OBJECTNOTANX500NAME,Object is not an X500Name,0), +PKIX_ERRORENTRY(OBJECTNOTBASICCONSTRAINTSCHECKERSTATE,Object is not a basic constraints checker state,0), +PKIX_ERRORENTRY(OBJECTNOTBIGINT,Object is not a BigInt,0), +PKIX_ERRORENTRY(OBJECTNOTBUILDPARAMS,Object is not a BuildParams,0), +PKIX_ERRORENTRY(OBJECTNOTBUILDRESULT,Object is not a BuildResult,0), +PKIX_ERRORENTRY(OBJECTNOTBYTEARRAY,Object is not a bytearray,0), +PKIX_ERRORENTRY(OBJECTNOTCERT,Object is not a Cert,0), +PKIX_ERRORENTRY(OBJECTNOTCERTBASICCONSTRAINTS,Object is not a CertBasicConstraints,0), +PKIX_ERRORENTRY(OBJECTNOTCERTCHAINCHECKER,Object is not a cert chain checker,0), +PKIX_ERRORENTRY(OBJECTNOTCERTNAMECONSTRAINTS,Object is not a CertNameConstraints,0), +PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYINFO,Object is not a CertPolicyInfo,0), +PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYMAP,Object is not a CertPolicyMap,0), +PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYQUALIFIER,Object is not a CertPolicyQualifier,0), +PKIX_ERRORENTRY(OBJECTNOTCERTSELECTOR,Object is not a cert selector,0), +PKIX_ERRORENTRY(OBJECTNOTCERTSTORE,Object is not a CertStore,0), +PKIX_ERRORENTRY(OBJECTNOTCOLLECTIONCERTSTORECONTEXT,Object is not a CollectionCertStoreContext,0), +PKIX_ERRORENTRY(OBJECTNOTCOMCERTSELPARAMS,Object is not a comCertSelParams,0), +PKIX_ERRORENTRY(OBJECTNOTCOMCRLSELPARAMS,Object is not a ComCRLSelParams,0), +PKIX_ERRORENTRY(OBJECTNOTCRL,Object is not a CRL,0), +PKIX_ERRORENTRY(OBJECTNOTCRLENTRY,Object is not a CRLEntry,0), +PKIX_ERRORENTRY(OBJECTNOTCRLSELECTOR,Object is not a CRLSelector,0), +PKIX_ERRORENTRY(OBJECTNOTDATE,Object is not a Date,0), +PKIX_ERRORENTRY(OBJECTNOTCRLCHECKER,Object is not a CRLChecker,0), +PKIX_ERRORENTRY(OBJECTNOTDEFAULTREVOCATIONCHECKER,Object is not a DefaultRevocationChecker,0), +PKIX_ERRORENTRY(OBJECTNOTFORWARDBUILDERSTATE,Object is not a PKIX_ForwardBuilderState,0), +PKIX_ERRORENTRY(OBJECTNOTGENERALNAME,Object is not a GeneralName,0), +PKIX_ERRORENTRY(OBJECTNOTHASHTABLE,Object is not a hashtable,0), +PKIX_ERRORENTRY(OBJECTNOTINFOACCESS,Object is not a InfoAccess,0), +PKIX_ERRORENTRY(OBJECTNOTLDAPREQUEST,Object is not a LdapRequest,0), +PKIX_ERRORENTRY(OBJECTNOTLDAPRESPONSE,Object is not a LdapResponse,0), +PKIX_ERRORENTRY(OBJECTNOTLIST,Object is not a list,0), +PKIX_ERRORENTRY(OBJECTNOTLOGGER,Object is not a Logger,0), +PKIX_ERRORENTRY(OBJECTNOTMONITORLOCK,Object is not a MonitorLock,0), +PKIX_ERRORENTRY(OBJECTNOTMUTEX,Object is not a Mutex,0), +PKIX_ERRORENTRY(OBJECTNOTNAMECONSTRAINTSCHECKERSTATE,Object is not a name constraints checker state,0), +PKIX_ERRORENTRY(OBJECTNOTOCSPCERTID,Object is not an OcspCertID,0), +PKIX_ERRORENTRY(OBJECTNOTOCSPCHECKER,Object is not an OCSPChecker,0), +PKIX_ERRORENTRY(OBJECTNOTOCSPREQUEST,Object is not an OcspRequest,0), +PKIX_ERRORENTRY(OBJECTNOTPOLICYCHECKERSTATE,Object is not a PKIX_PolicyCheckerState,0), +PKIX_ERRORENTRY(OBJECTNOTPOLICYNODE,Object is not a PolicyNode,0), +PKIX_ERRORENTRY(OBJECTNOTPROCESSINGPARAMS,Object is not a ProcessingParams,0), +PKIX_ERRORENTRY(OBJECTNOTPUBLICKEY,Object is not a PublicKey,0), +PKIX_ERRORENTRY(OBJECTNOTRESOURCELIMITS,Object is not a ResourceLimits,0), +PKIX_ERRORENTRY(OBJECTNOTREVOCATIONCHECKER,Object is not a revocation checker,0), +PKIX_ERRORENTRY(OBJECTNOTRWLOCK,Object is not a RWLock,0), +PKIX_ERRORENTRY(OBJECTNOTSIGNATURECHECKERSTATE,Object is not a signature checker state,0), +PKIX_ERRORENTRY(OBJECTNOTSOCKET,Object is not a Socket,0), +PKIX_ERRORENTRY(OBJECTNOTSTRING,Object is not a string,0), +PKIX_ERRORENTRY(OBJECTNOTTARGETCERTCHECKERSTATE,Object is not a target cert checker state,0), +PKIX_ERRORENTRY(OBJECTNOTTRUSTANCHOR,Object is not a trustAnchor,0), +PKIX_ERRORENTRY(OBJECTNOTVALIDATEPARAMS,Object is not a ValidateParams,0), +PKIX_ERRORENTRY(OBJECTNOTVALIDATERESULT,Object is not a ValidateResult,0), +PKIX_ERRORENTRY(OBJECTNOTVERIFYNODE,Object is not a VerifyNode,0), +PKIX_ERRORENTRY(OBJECTREGISTERTYPEFAILED,PKIX_PL_Object_RegisterType failed,0), +PKIX_ERRORENTRY(OBJECTRETRIEVEEQUALSCALLBACKFAILED,pkix_pl_Object_RetrieveEqualsCallback failed,0), +PKIX_ERRORENTRY(OBJECTSPECIFICFUNCTIONFAILED,object-specific function failed,0), +PKIX_ERRORENTRY(OBJECTSTILLREFERENCED,Object is still referenced,0), +PKIX_ERRORENTRY(OBJECTTOSTRINGFAILED,PKIX_PL_Object_ToString failed,0), +PKIX_ERRORENTRY(OBJECTTYPESDONOTMATCH,Object types do not match,0), +PKIX_ERRORENTRY(OBJECTWITHNONPOSITIVEREFERENCES,Object with non-positive references,0), +PKIX_ERRORENTRY(OCSPCERTIDCREATEFAILED,PKIX_PL_OcspCertID_Create failed,0), +PKIX_ERRORENTRY(OCSPCERTIDGETFRESHCACHESTATUSFAILED,PKIX_PL_OcspCertID_GetFreshCacheStatus returned an error,0), +PKIX_ERRORENTRY(OCSPCERTIDREMEMBEROCSPFAILUREDFAILED,PKIX_PL_OcspCertID_RememberOCSPProcessingFailure,0), +PKIX_ERRORENTRY(OCSPCHECKERCREATEFAILED,PKIX_OcspChecker_Create failed,0), +PKIX_ERRORENTRY(OCSPBADHTTPRESPONSE,Bad Http Response,SEC_ERROR_OCSP_BAD_HTTP_RESPONSE), +PKIX_ERRORENTRY(OCSPREQUESTCREATEFAILED,PKIX_PL_OcspRequest_Create failed,0), +PKIX_ERRORENTRY(OCSPREQUESTGETCERTIDFAILED,pkix_pl_OcspRequest_GetCertID failed,0), +PKIX_ERRORENTRY(OCSPREQUESTGETENCODEDFAILED,pkix_pl_OcspRequest_GetEncoded failed,0), +PKIX_ERRORENTRY(OCSPREQUESTGETLOCATIONFAILED,pkix_pl_OcspRequest_GetLocation failed,0), +PKIX_ERRORENTRY(OCSPRESPONSECREATEFAILED,pkix_pl_OcspResponse_Create failed,0), +PKIX_ERRORENTRY(OCSPRESPONSEDECODEFAILED,pkix_pl_OcspResponse_Decode failed,0), +PKIX_ERRORENTRY(OCSPRESPONSEGETSTATUSFORCERTFAILED,pkix_pl_OcspResponse_GetStatusForCert failed,0), +PKIX_ERRORENTRY(OCSPRESPONSEGETSTATUSRETURNEDANERROR,pkix_pl_OcspResponse_GetStatus returned an error,0), +PKIX_ERRORENTRY(OCSPRESPONSESAYSCERTREVOKED,OCSP response says Cert revoked,SEC_ERROR_REVOKED_CERTIFICATE_OCSP), +PKIX_ERRORENTRY(OCSPRESPONSEVERIFYSIGNATUREFAILED,pkix_pl_OcspResponse_VerifySignature failed,0), +PKIX_ERRORENTRY(OCSPSERVERERROR,OCSP Server Error,SEC_ERROR_OCSP_SERVER_ERROR), +PKIX_ERRORENTRY(OIDBYTES2ASCIIDATALENGTHZERO,pkix_pl_oidBytes2Ascii: data length is zero,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(OIDBYTES2ASCIIFAILED,pkix_pl_oidBytes2Ascii failed,0), +PKIX_ERRORENTRY(OIDBYTESLENGTH0,Oid bytes length is 0,0), +PKIX_ERRORENTRY(OIDCOMPARATORFAILED,pkix_pl_OID_Comparator failed,0), +PKIX_ERRORENTRY(OIDCOMPONENTTOOBIG,Overflow error: OID component > 2^32,0), +PKIX_ERRORENTRY(OIDCREATEFAILED,PKIX_PL_OID_Create failed,0), +PKIX_ERRORENTRY(OIDEQUALFAILED,PKIX_PL_OID_Equal failed,0), +PKIX_ERRORENTRY(OIDEQUALSFAILED,PKIX_PL_OID_Equals failed,0), +PKIX_ERRORENTRY(OIDGETNEXTTOKENFAILED,pkix_pl_OID_GetNextToken failed,0), +PKIX_ERRORENTRY(OIDHASHCODEFAILED,PKIX_PL_OID_Hashcode failed,0), +PKIX_ERRORENTRY(OIDLENGTHTOOSHORT,OID length too short,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(OIDNEEDS2ORMOREFIELDS,OID needs 2 or more fields,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(OIDTOSTRINGFAILED,PKIX_PL_OID_ToString failed,0), +PKIX_ERRORENTRY(OPERATIONNOTPERMITTEDONIMMUTABLELIST,Operation not permitted on Immutable List,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(OTHERNAMECREATEFAILED,pkix_pl_OtherName_Create failed,0), +PKIX_ERRORENTRY(OUTOFMEMORY,Out of Memory,0), +PKIX_ERRORENTRY(PATHLENCONSTRAINTINVALID,Certificate path length constraint is invalid,SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID), +PKIX_ERRORENTRY(PK11CERTSTORECERTQUERYFAILED,pkix_pl_Pk11CertStore_CertQuery failed,0), +PKIX_ERRORENTRY(PK11CERTSTORECREATEFAILED,PKIX_PL_Pk11CertStore_Create failed,0), +PKIX_ERRORENTRY(PK11CERTSTORECRLQUERYFAILED,pkix_pl_Pk11CertStore_CrlQuery failed,0), +PKIX_ERRORENTRY(PKIXUNKNOWNERROR,PKIX uninitialized error code,0), +PKIX_ERRORENTRY(POLICYCHECKERCALCULATEINTERSECTIONFAILED,pkix_PolicyChecker_CalculateIntersection failed,0), +PKIX_ERRORENTRY(POLICYCHECKERCHECKANYFAILED,pkix_PolicyChecker_CheckAny failed,0), +PKIX_ERRORENTRY(POLICYCHECKERCHECKPOLICYRECURSIVEFAILED,pkix_PolicyChecker_CheckPolicyRecursive failed,0), +PKIX_ERRORENTRY(POLICYCHECKERERROR,PolicyChecker Error,0), +PKIX_ERRORENTRY(POLICYCHECKERINITIALIZEFAILED,pkix_PolicyChecker_Initialize failed,0), +PKIX_ERRORENTRY(POLICYCHECKERMAKEMUTABLECOPYFAILED,pkix_PolicyChecker_MakeMutableCopy failed,0), +PKIX_ERRORENTRY(POLICYCHECKERMAKESINGLETONFAILED,pkix_PolicyChecker_MakeSingleton failed,0), +PKIX_ERRORENTRY(POLICYCHECKERMAPCONTAINSFAILED,pkix_PolicyChecker_MapContains failed,0), +PKIX_ERRORENTRY(POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED,pkix_PolicyChecker_MapGetMappedPolicies failed,0), +PKIX_ERRORENTRY(POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED,pkix_PolicyChecker_MapGetSubjectDomainPolicies failed,0), +PKIX_ERRORENTRY(POLICYCHECKERSPAWNFAILED,pkix_PolicyChecker_Spawn failed,0), +PKIX_ERRORENTRY(POLICYCHECKERSTATECREATEFAILED,PKIX_PolicyCheckerState_Create failed,0), +PKIX_ERRORENTRY(POLICYNODEADDTOPARENTFAILED,pkix_PolicyNode_AddToParent failed,0), +PKIX_ERRORENTRY(POLICYNODECREATEFAILED,pkix_PolicyNode_Create failed,0), +PKIX_ERRORENTRY(POLICYNODEDUPLICATEHELPERFAILED,pkix_PolicyNode_DuplicateHelper failed,0), +PKIX_ERRORENTRY(POLICYNODEGETCHILDRENMUTABLEFAILED,pkix_PolicyNode_GetChildrenMutable failed,0), +PKIX_ERRORENTRY(POLICYNODEGETDEPTHFAILED,PKIX_PolicyNode_GetDepth failed,0), +PKIX_ERRORENTRY(POLICYNODEGETEXPECTEDPOLICIESFAILED,PKIX_PolicyNode_GetExpectedPolicies failed,0), +PKIX_ERRORENTRY(POLICYNODEGETPARENTFAILED,PKIX_PolicyNode_GetParent failed,0), +PKIX_ERRORENTRY(POLICYNODEGETPOLICYQUALIFIERSFAILED,PKIX_PolicyNode_GetPolicyQualifiers failed,0), +PKIX_ERRORENTRY(POLICYNODEGETVALIDPOLICYFAILED,PKIX_PolicyNode_GetValidPolicy failed,0), +PKIX_ERRORENTRY(POLICYNODEISCRITICALFAILED,PKIX_PolicyNode_IsCritical failed,0), +PKIX_ERRORENTRY(POLICYNODEPRUNEFAILED,pkix_PolicyNode_Prune failed,0), +PKIX_ERRORENTRY(POLICYTREETOOIDSFAILED,Failed to convert policy tree to oid,0), +PKIX_ERRORENTRY(PORTARENAALLOCFAILED,PORT Arena Allocation failed, 0), +PKIX_ERRORENTRY(PORTUCS2UTF8CONVERSIONFAILED,PORT_UCS2_UTF8Conversion failed.,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(PRACCEPTFAILED,PR_Accept failed,0), +PKIX_ERRORENTRY(PRBINDFAILED,PR_Bind failed,0), +PKIX_ERRORENTRY(PRCONNECTCONTINUEFAILED,PR_ConnectContinue failed,0), +PKIX_ERRORENTRY(PRCONNECTFAILED,PR_Connect failed,0), +PKIX_ERRORENTRY(PRECONDITIONFAILED,Function precondition failed,SEC_ERROR_LIBPKIX_INTERNAL), +PKIX_ERRORENTRY(PRENUMERATEHOSTENTFAILED,PR_EnumerateHostEnt failed.,0), +PKIX_ERRORENTRY(PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT,PR_GetHostByName rejects hostname argument.,0), +PKIX_ERRORENTRY(PRIMHASHTABLEADDFAILED,pkix_pl_PrimHashTable_Add failed,0), +PKIX_ERRORENTRY(PRIMHASHTABLECREATEFAILED,pkix_pl_PrimHashTable_Create failed,0), +PKIX_ERRORENTRY(PRIMHASHTABLEDESTROYFAILED,pkix_pl_PrimHashTable_Destroy failed,0), +PKIX_ERRORENTRY(PRIMHASHTABLEGETBUCKETSIZEFAILED,pkix_pl_PrimHashTable_GetBucketSize failed,0), +PKIX_ERRORENTRY(PRIMHASHTABLELOOKUPFAILED,pkix_pl_PrimHashTable_Lookup failed,0), +PKIX_ERRORENTRY(PRIMHASHTABLEREMOVEFAILED,pkix_pl_PrimHashTable_Remove failed,0), +PKIX_ERRORENTRY(PRLISTENFAILED,PR_Listen failed,0), +PKIX_ERRORENTRY(PRNEWTCPSOCKETFAILED,PR_NewTCPSocket failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSADDCERTCHAINCHECKERFAILED,PKIX_ProcessingParams_AddCertChainChecker failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSADDCERTSTOREFAILED,PKIX_ProcessingParams_AddCertStore failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSADDREVMETHODFAILED,PKIX_ProcessingParams_AddRevocationMethod failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSCREATEFAILED,PKIX_ProcessingParams_Create failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED,PKIX_ProcessingParams_GetCertChainCheckers failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETCERTSTORESFAILED,PKIX_ProcessingParams_GetCertStores failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETDATEFAILED,PKIX_ProcessingParams_GetDate failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETHINTCERTSFAILED,PKIX_ProcessingParams_GetHintCerts failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETINITIALPOLICIESFAILED,PKIX_ProcessingParams_GetInitialPolicies failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETNISTREVPOLICYENABLEDFAILED,pkix_ProcessingParams_GetNISTRevocationPolicyEnabled failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED,PKIX_ProcessingParams_GetPolicyQualifiersRejected failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETRESOURCELIMITSFAILED,PKIX_ProcessingParams_GetResourceLimits failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED,PKIX_ProcessingParams_GetRevocationChecker failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETREVOCATIONENABLEDFAILED,PKIX_ProcessingParams_GetRevocationEnabled failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED,PKIX_ProcessingParams_GetTargetCertConstraints failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSGETTRUSTANCHORSFAILED,PKIX_ProcessingParams_GetTrustAnchors failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED,PKIX_ProcessingParams_IsAnyPolicyInhibited failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED,PKIX_ProcessingParams_IsExplicitPolicyRequired failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED,PKIX_ProcessingParams_IsPolicyMappingInhibited failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETANYPOLICYINHIBITED,PKIX_ProcessingParams_SetAnyPolicyInhibited failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETCERTSTORESFAILED,PKIX_ProcessingParams_SetCertStores failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETDATEFAILED,PKIX_ProcessingParams_SetDate failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED,PKIX_ProcessingParams_SetExplicitPolicyRequired failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETHINTCERTSFAILED,PKIX_ProcessingParams_SetHintCerts failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETINITIALPOLICIESFAILED,PKIX_ProcessingParams_SetInitialPolicies failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETNISTREVOCATIONENABLEDFAILED,PKIX_ProcessingParams_SetNISTRevocationEnabled failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED,PKIX_ProcessingParams_SetPolicyMappingInhibited failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED,PKIX_ProcessingParams_SetRevocationChecker failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED,PKIX_ProcessingParams_SetTargetCertConstraints failed,0), +PKIX_ERRORENTRY(PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED,ProcessingParams_SetQualifyTargetCertFlag failed,0), +PKIX_ERRORENTRY(PRPOLLFAILED,PR_Poll failed,0), +PKIX_ERRORENTRY(PRPOLLRETBADFILENUM,PR_Poll failed,0), +PKIX_ERRORENTRY(PRRECVFAILED,PR_Recv failed,0), +PKIX_ERRORENTRY(PRRECVREPORTSNETWORKCONNECTIONCLOSED,PR_Recv reports network connection is closed,0), +PKIX_ERRORENTRY(PRSENDFAILED,PR_Send failed,0), +PKIX_ERRORENTRY(PRSHUTDOWNFAILED,PR_Shutdown failed,0), +PKIX_ERRORENTRY(PRSMPRINTFFAILED,PR_smprintf failed,0), +PKIX_ERRORENTRY(PRSNPRINTFFAILED,PR_snprintf failed,0), +PKIX_ERRORENTRY(PUBKEYTYPENULLKEY,pubKeyType is nullKey,0), +PKIX_ERRORENTRY(PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED,PKIX_PL_PublicKey_MakeInheritedDSAPublicKey failed,0), +PKIX_ERRORENTRY(PUBLICKEYNEEDSDSAPARAMETERSFAILED,PKIX_PL_PublicKey_NeedsDSAParameters failed,0), +PKIX_ERRORENTRY(PUBLICKEYTOSTRINGFAILED,PKIX_PL_PublicKey_ToString failed,0), +PKIX_ERRORENTRY(PUBLICKEYTOSTRINGHELPERFAILED,pkix_pl_PublicKey_ToString_Helper failed,0), +PKIX_ERRORENTRY(QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION,Qualifiers in critical Certificate Policy extension,0), +PKIX_ERRORENTRY(REALLOCFAILED,PKIX_PL_Realloc failed,0), +PKIX_ERRORENTRY(RECEIVEDCORRUPTEDOBJECTARGUMENT,Received corrupted object argument,0), +PKIX_ERRORENTRY(REGISTERCERTSTOREFAILED,RegisterCertStores failed,0), +PKIX_ERRORENTRY(REMOVEDUPUNTRUSTEDCERTSFAILED, pkix_Build_RemoveDupUntrustedCerts failed,0), +PKIX_ERRORENTRY(REQUESTNOTANHTTPDEFAULTCLIENT,request is not an HttpDefaultClient,0), +PKIX_ERRORENTRY(RESOURCELIMITSGETMAXDEPTHFAILED,PKIX_ResourceLimits_GetMaxDepth failed,0), +PKIX_ERRORENTRY(RESOURCELIMITSGETMAXFANOUTFAILED,PKIX_ResourceLimits_GetMaxFanout failed,0), +PKIX_ERRORENTRY(RESOURCELIMITSGETMAXTIMEFAILED,PKIX_ResourceLimits_GetMaxTime failed,0), +PKIX_ERRORENTRY(RETRIEVEOUTPUTSFAILED,pkix_RetrieveOutputs failed,0), +PKIX_ERRORENTRY(REVCHECKCERTFAILED,pkix_RevCheckCert failed,0), +PKIX_ERRORENTRY(REVCHECKERCHECKFAILED,revCheckerCheck failed,0), +PKIX_ERRORENTRY(REVOCATIONCHECKERADDMETHODFAILED,Can not add revocation method,0), +PKIX_ERRORENTRY(REVOCATIONCHECKERCREATEFAILED,PKIX_RevocationChecker_Create failed,0), +PKIX_ERRORENTRY(REVOCATIONCHECKERGETREVCALLBACKFAILED,PKIX_RevocationChecker_GetRevCallback failed,0), +PKIX_ERRORENTRY(REVOCATIONCHECKERGETREVCHECKERCONTEXTFAILED,PKIX_RevocationChecker_GetRevCheckerContext failed,0), +PKIX_ERRORENTRY(REVOCATIONCHECKERWASNOTSET,Revocation chekcer was not set,0), +PKIX_ERRORENTRY(REVOKEDBYUNKNOWNCRLREASONCODE,Revoked by Unknown CRL ReasonCode,0), +PKIX_ERRORENTRY(SEARCHRESPONSEPACKETOFUNKNOWNTYPE,SearchResponse packet of unknown type,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(SECASN1ENCODEITEMFAILED,SEC_ASN1EncodeItem failed,SEC_ERROR_FAILED_TO_ENCODE_DATA), +PKIX_ERRORENTRY(SECERRORUNKNOWNISSUER,Nss legacy err code: build failed. Issuer is unknown.,SEC_ERROR_UNKNOWN_ISSUER), +PKIX_ERRORENTRY(SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED,SECKEY_CopySubjectPublicKeyInfo failed,0), +PKIX_ERRORENTRY(SECKEYEXTRACTPUBLICKEYFAILED,SECKEY_ExtractPublicKey failed,0), +PKIX_ERRORENTRY(SECOIDCOPYALGORITHMIDFAILED,SECOID_CopyAlgorithmID failed,0), +PKIX_ERRORENTRY(SECOIDFINDOIDTAGDESCRIPTIONFAILED,SECOID_FindOIDTag Description failed,0), +PKIX_ERRORENTRY(SECONDFIELDMUSTBEBETWEEN039,Second field must be between 0-39,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(SECONDKEYDSAPUBLICKEY,Second key is a DSA public key but has null parameters,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(SECONDKEYNOTDSAPUBLICKEY,Second key is not a DSA public key,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(SECONDPUBKEYTYPENULLKEY,secondPubKeyType is nullKey,0), +PKIX_ERRORENTRY(SECQUICKDERDECODERFAILED,SEC_QuickDERDecodeItem failed,0), +PKIX_ERRORENTRY(SECREADPKCS7CERTSFAILED,SEC_ReadPKCS7Certs failed,0), +PKIX_ERRORENTRY(SELECTORMATCHFAILED,selectorMatch failed,0), +PKIX_ERRORENTRY(SESSIONNOTANHTTPDEFAULTCLIENT,session is not an HttpDefaultClient,0), +PKIX_ERRORENTRY(SETPOLICIESFAILED,Fail to set cert validation policies,0), +PKIX_ERRORENTRY(SHUTDOWNFAILED,PKIX_PL_Shutdown failed,0), +PKIX_ERRORENTRY(SIGNATURECHECKERINITIALIZEFAILED,pkix_SignatureChecker_Initialize failed,0), +PKIX_ERRORENTRY(SIGNATURECHECKERSTATECREATEFAILED,pkix_SignatureCheckerState_Create failed,0), +PKIX_ERRORENTRY(SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY,Signature did not verify with the public key,0), +PKIX_ERRORENTRY(SINGLEPOLICYNODEEQUALSFAILED,PKIX_PL_SinglePolicyNode_Equals failed,0), +PKIX_ERRORENTRY(SINGLEPOLICYNODEHASHCODEFAILED,pkix_SinglePolicyNode_Hashcode failed,0), +PKIX_ERRORENTRY(SINGLEPOLICYNODETOSTRINGFAILED,pkix_SinglePolicyNode_ToString failed,0), +PKIX_ERRORENTRY(SINGLEVERIFYNODEEQUALSFAILED,PKIX_PL_SingleVerifyNode_Equals failed,0), +PKIX_ERRORENTRY(SINGLEVERIFYNODEHASHCODEFAILED,pkix_SingleVerifyNode_Hashcode failed,0), +PKIX_ERRORENTRY(SOCKETCONNECTCONTINUEFAILED,pkix_pl_Socket_ConnectContinue failed,0), +PKIX_ERRORENTRY(SOCKETCONNECTFAILED,pkix_pl_Socket_Connect failed,0), +PKIX_ERRORENTRY(SOCKETCREATEBYHOSTANDPORTFAILED,pkix_pl_Socket_CreateByHostAndPort failed,0), +PKIX_ERRORENTRY(SOCKETCREATEBYNAMEFAILED,pkix_pl_Socket_CreateByName failed,0), +PKIX_ERRORENTRY(SOCKETCREATECLIENTFAILED,pkix_pl_Socket_CreateClient failed,0), +PKIX_ERRORENTRY(SOCKETCREATEFAILED,pkix_pl_Socket_Create failed,0), +PKIX_ERRORENTRY(SOCKETCREATESERVERFAILED,pkix_pl_Socket_CreateServer failed,0), +PKIX_ERRORENTRY(SOCKETEQUALSFAILED,PKIX_PL_Socket_Equals failed,0), +PKIX_ERRORENTRY(SOCKETGETCALLBACKLISTFAILED,pkix_pl_Socket_GetCallbackList failed,0), +PKIX_ERRORENTRY(SOCKETGETPRFILEDESCFAILED,pkix_pl_Socket_GetPRFileDesc failed,0), +PKIX_ERRORENTRY(SOCKETHASHCODEFAILED,PKIX_PL_Socket_Hashcode failed,0), +PKIX_ERRORENTRY(SOCKETPOLLFAILED,pkix_pl_Socket_Poll failed,0), +PKIX_ERRORENTRY(SOCKETRECVFAILED,pkix_pl_Socket_Recv failed,0), +PKIX_ERRORENTRY(SOCKETSENDFAILED,pkix_pl_Socket_Send failed,0), +PKIX_ERRORENTRY(SOCKETSETNONBLOCKINGFAILED,pkix_pl_Socket_SetNonBlocking failed,0), +PKIX_ERRORENTRY(SOURCESTRINGHASINVALIDLENGTH,Source string has invalid length,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(SPRINTFFAILED,PKIX_PL_Sprintf failed,0), +PKIX_ERRORENTRY(STRINGCOMPARATORFAILED,pkix_pl_String_Comparator failed,0), +PKIX_ERRORENTRY(STRINGCREATEFAILED,PKIX_PL_String_Create failed,0), +PKIX_ERRORENTRY(STRINGEQUALSFAILED,pkix_pl_String_Equals failed,0), +PKIX_ERRORENTRY(STRINGGETENCODEDFAILED,PKIX_PL_String_GetEncoded failed,0), +PKIX_ERRORENTRY(STRINGHASHCODEFAILED,pkix_pl_String_Hashcode failed,0), +PKIX_ERRORENTRY(SUBJALTNAMECHECKFAILED,Validation failed: SubjAltNamecheck failed,0), +PKIX_ERRORENTRY(TARGETCERTCHECKERINITIALIZEFAILED,pkix_TargetCertChecker_Initialize failed,0), +PKIX_ERRORENTRY(TARGETCERTCHECKERSTATECREATEFAILED,pkix_TargetCertCheckerState_Create failed,0), +PKIX_ERRORENTRY(TESTANOTHERERRORMESSAGE, Another Error Message,0), +PKIX_ERRORENTRY(TESTERRORMESSAGE, Error Message,0), +PKIX_ERRORENTRY(TESTNOMATCHINGPOLICY, No Matching Policy,0), +PKIX_ERRORENTRY(TESTNOTANERRORCRLSELECTMISMATCH, Not an error CRL Select mismatch,0), +PKIX_ERRORENTRY(TESTPOLICYEXTWITHNOPOLICYQUALIFIERS, Policies extension but no Policy Qualifiers,0), +PKIX_ERRORENTRY(TIMECONSUMEDEXCEEDSRESOURCELIMITS,Time consumed exceeds Resource Limits,SEC_ERROR_OUT_OF_SEARCH_LIMITS), +PKIX_ERRORENTRY(TOOLITTLEDATAINDERSEQUENCE,Too little data in DER Sequence,0), +PKIX_ERRORENTRY(TOOMUCHDATAINDERSEQUENCE,Too much data in DER Sequence,0), +PKIX_ERRORENTRY(TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED,ToString for this GeneralName type not supported,0), +PKIX_ERRORENTRY(TRUNCATEDUNICODEINESCAPEDASCII,Truncated Unicode in EscapedASCII,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(TRUSTANCHORCREATEWITHCERTFAILED,PKIX_TrustAnchor_CreateWithCert failed,0), +PKIX_ERRORENTRY(TRUSTANCHORGETCANAMEFAILED,PKIX_TrustAnchor_GetCAName failed,0), +PKIX_ERRORENTRY(TRUSTANCHORGETCAPUBLICKEYFAILED,PKIX_TrustAnchor_GetCAPublicKey failed,0), +PKIX_ERRORENTRY(TRUSTANCHORGETNAMECONSTRAINTSFAILED,PKIX_TrustAnchor_GetNameConstraints failed,0), +PKIX_ERRORENTRY(TRUSTANCHORGETTRUSTEDCERTFAILED,PKIX_TrustAnchor_GetTrustedCert failed,0), +PKIX_ERRORENTRY(TRUSTANCHORTOCERTFAILED,Fail to convert trust anchor to cert,0), +PKIX_ERRORENTRY(TYPEALREADYREGISTERED,Type is already registered,0), +PKIX_ERRORENTRY(UNABLETOADDACCEPTABLERESPONSESTOREQUEST,Unable to add acceptableResponses to request,0), +PKIX_ERRORENTRY(UNABLETOADDCERTTOCERTLIST,Unable to add Cert to CertList,0), +PKIX_ERRORENTRY(UNABLETOBUILDCHAIN,Unable to build chain,0), +PKIX_ERRORENTRY(UNABLETOCREATECERTOCSPREQUEST,Unable to create a CertOCSPRequest,0), +PKIX_ERRORENTRY(UNABLETOCREATECRLSTRING,Unable to create crlString,0), +PKIX_ERRORENTRY(UNABLETOCREATEGENERALNAMEOFTHISTYPE,Unable to create GeneralName of this type,0), +PKIX_ERRORENTRY(UNABLETOCREATEISSUER,Unable to create Issuer,0), +PKIX_ERRORENTRY(UNABLETOCREATELIST,Unable to create list,0), +PKIX_ERRORENTRY(UNABLETOCREATENEWCERTLIST,Unable to create a new CertList,0), +PKIX_ERRORENTRY(UNABLETOCREATEPSTRING,Unable to create pString,0), +PKIX_ERRORENTRY(UNABLETOFINDSTATUSINOCSPRESPONSE,Unable to find status in OCSP response,SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS), +PKIX_ERRORENTRY(UNABLETOMAKELISTIMMUTABLE,Unable to make list immutable,0), +PKIX_ERRORENTRY(UNABLETOOPENCERTFILE,Unable to open cert file,0), +PKIX_ERRORENTRY(UNABLETOOPENCRLFILE,Unable to open crl file,0), +PKIX_ERRORENTRY(UNABLETOPARSEOCSPRESPONSE,Unable to parse OCSP response,SEC_ERROR_OCSP_MALFORMED_RESPONSE), +PKIX_ERRORENTRY(UNABLETOREADDERFROMCERTFILE,Unable to read DER from cert file,0), +PKIX_ERRORENTRY(UNABLETOREADDERFROMCRLFILE,Unable to read DER from crl file,0), +PKIX_ERRORENTRY(UNABLETOSETSOCKETTONONBLOCKING,Unable to set socket to non-blocking I/O,0), +PKIX_ERRORENTRY(UNDEFINEDCALLBACK,Undefined callback,0), +PKIX_ERRORENTRY(UNDEFINEDCLASSTABLEENTRY,Undefined class table entry,0), +PKIX_ERRORENTRY(UNDEFINEDCOMPARATOR,Undefined Comparator,0), +PKIX_ERRORENTRY(UNDEFINEDDUPLICATEFUNCTION,Undefined Duplicate function,0), +PKIX_ERRORENTRY(UNDEFINEDEQUALSCALLBACK,Undefined equals callback,0), +PKIX_ERRORENTRY(UNEXPECTEDERRORINESTABLISHINGCONNECTION,Unexpected error in establishing connection,0), +PKIX_ERRORENTRY(UNEXPECTEDRESULTCODEINRESPONSE,Unexpected result code in Response,SEC_ERROR_BAD_LDAP_RESPONSE), +PKIX_ERRORENTRY(UNKNOWNFORMAT,Unknown format,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(UNKNOWNINFOACCESSMETHOD,Unknown InfoAccess method,SEC_ERROR_BAD_INFO_ACCESS_METHOD), +PKIX_ERRORENTRY(UNKNOWNOBJECTOID,Unknown object OID,0), +PKIX_ERRORENTRY(UNKNOWNOBJECTTYPE,Unknown object type,0), +PKIX_ERRORENTRY(UNKNOWNTYPEARGUMENT,Unknown type argument,0), +PKIX_ERRORENTRY(UNLOCKOBJECTFAILED,pkix_UnlockObject failed,0), +PKIX_ERRORENTRY(UNRECOGNIZEDCRITICALEXTENSION,Unrecognized Critical Extension,SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION), +PKIX_ERRORENTRY(UNRECOGNIZEDCRLENTRYCRITICALEXTENSION,Unrecognized CRLEntry Critical Extension,SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION), +PKIX_ERRORENTRY(UNRECOGNIZEDPROTOCOLREQUESTED,Unrecognized protocol requested,0), +PKIX_ERRORENTRY(UNRECOGNIZEDREQUESTMETHOD,Unrecognized request method,0), +PKIX_ERRORENTRY(UNRECOGNIZEDTIMETYPE,Unrecognized time type,0), +PKIX_ERRORENTRY(UNSUPPORTEDCRLDPTYPE,CrlDp type is not supported,0), +PKIX_ERRORENTRY(UNSUPPORTEDVERSIONOFHTTPCLIENT,Unsupported version of Http Client,0), +PKIX_ERRORENTRY(UNSUPPORTEDCERTUSAGE,Specified certificate usage is unsupported,SEC_ERROR_CERT_USAGES_INVALID), +PKIX_ERRORENTRY(URLPARSINGFAILED,URL Parsing failed,0), +PKIX_ERRORENTRY(USERCHECKERCHECKFAILED,userCheckerCheck failed,0), +PKIX_ERRORENTRY(UTF16ALIGNMENTERROR,UTF16 Alignment Error,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(UTF16HIGHZONEALIGNMENTERROR,UTF16 High Zone Alignment Error,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(UTF16LOWZONEERROR,UTF16 Low Zone Error,SEC_ERROR_INVALID_ARGS), +PKIX_ERRORENTRY(UTF16TOESCASCIIFAILED,pkix_UTF16_to_EscASCII failed,0), +PKIX_ERRORENTRY(UTF16TOUTF8FAILED,pkix_UTF16_to_UTF8 failed,0), +PKIX_ERRORENTRY(UTF8TOUTF16FAILED,pkix_UTF8_to_UTF16 failed,0), +PKIX_ERRORENTRY(VALIDATEBUILDUSEROIDSFAILED,pkix_Validate_BuildUserOIDs failed,0), +PKIX_ERRORENTRY(VALIDATECERTCHAINFAILED,Failed to validate cert chain,0), +PKIX_ERRORENTRY(VALIDATECHAINFAILED,PKIX_ValidateChain failed,0), +PKIX_ERRORENTRY(VALIDATEPARAMSGETCERTCHAINFAILED,PKIX_ValidateParams_GetCertChain failed,0), +PKIX_ERRORENTRY(VALIDATEPARAMSGETPROCESSINGPARAMSFAILED,PKIX_ValidateParams_GetProcessingParams failed,0), +PKIX_ERRORENTRY(VALIDATERESULTCREATEFAILED,pkix_ValidateResult_Create failed,0), +PKIX_ERRORENTRY(VALIDATERESULTGETPOLICYTREEFAILED,PKIX_ValidateResult_GetPolicyTree failed,0), +PKIX_ERRORENTRY(VALIDATERESULTGETTRUSTANCHORFAILED,PKIX_ValidateResult_GetTrustAnchor failed,0), +PKIX_ERRORENTRY(VALIDATIONFAILEDCERTSIGNATURECHECKING,Validation failed: Cert Signature checking,0), +PKIX_ERRORENTRY(VALIDATIONFAILEDNULLCERTPOINTER,Validation failed: NULL Cert pointer,0), +PKIX_ERRORENTRY(VALIDATIONFAILEDPATHTONAMECHECKFAILED,Validation failed: PathToName check failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE), +PKIX_ERRORENTRY(VALUEINESCAPEDASCII,value in EscapedASCII,0), +PKIX_ERRORENTRY(VERIFYNODEADDTOCHAINFAILED,pkix_VerifyNode_AddToChain failed,0), +PKIX_ERRORENTRY(VERIFYNODEADDTOTREEFAILED,pkix_VerifyNode_AddToTree failed,0), +PKIX_ERRORENTRY(VERIFYNODECREATEFAILED,pkix_VerifyNode_Create failed,0), +PKIX_ERRORENTRY(VERIFYNODEDUPLICATEHELPERFAILED,pkix_VerifyNode_DuplicateHelper failed,0), +PKIX_ERRORENTRY(VERIFYNODEFINDERRORFAILED,pkix_VerifyNode_FindError failed,0), +PKIX_ERRORENTRY(VERIFYNODESETDEPTHFAILED,pkix_VerifyNode_SetDepth failed,0), +PKIX_ERRORENTRY(VERIFYNODESETERRORFAILED,pkix_VerifyNode_SetError failed,0), +PKIX_ERRORENTRY(VERSIONVALUEMUSTBEV1ORV2,Version value must be V1(0) or V2(1),SEC_ERROR_CRL_INVALID), +PKIX_ERRORENTRY(VERSIONVALUEMUSTBEV1V2ORV3,Version value must be v1(0) v2(1) or v3(2),SEC_ERROR_CERT_VALID), +PKIX_ERRORENTRY(X500NAMECOMPAREDERBYTESFAILED,pkix_pl_X500Name_CompareDERBytes failed,0), +PKIX_ERRORENTRY(X500NAMECREATEFAILED,PKIX_PL_X500Name_Create failed,0), +PKIX_ERRORENTRY(X500NAMECREATEFROMCERTNAMEFAILED,pkix_pl_X500Name_CreateFromCERTName failed,0), +PKIX_ERRORENTRY(X500NAMECREATEFROMUTF8FAILED,pkix_pl_X500Name_CreateFromUtf8 failed,0), +PKIX_ERRORENTRY(X500NAMEEQUALSFAILED,PKIX_PL_X500Name_Equals failed,0), +PKIX_ERRORENTRY(X500NAMEGETCOMMONNAMEFAILED,pkix_pl_X500Name_GetCommonName failed,0), +PKIX_ERRORENTRY(X500NAMEGETCOUNTRYNAMEFAILED,pkix_pl_X500Name_GetCountryName failed,0), +PKIX_ERRORENTRY(X500NAMEGETORGNAMEFAILED,pkix_pl_X500Name_GetOrgName failed,0), +PKIX_ERRORENTRY(X500NAMEGETSECNAMEFAILED,pkix_pl_X500Name_GetSECName failed,0), +PKIX_ERRORENTRY(X500NAMEHASHCODEFAILED,PKIX_PL_X500Name_Hashcode failed,0), +PKIX_ERRORENTRY(X500NAMEMATCHFAILED,PKIX_PL_X500Name_Match failed,0), +PKIX_ERRORENTRY(X500NAMETOSTRINGFAILED,PKIX_PL_X500Name_ToString failed,0), +PKIX_ERRORENTRY(ZEROLENGTHBYTEARRAYFORCRLENCODING,Zero-length ByteArray for CRL encoding,0), +PKIX_ERRORENTRY(INVALIDOCSPHTTPMETHOD,Unsupported HTTP Method for OCSP retrieval,0), +PKIX_ERRORENTRY(OCSPGETREQUESTTOOBIG,OCSP request too big for HTTP GET method,0), +PKIX_ERRORENTRY(CERTISBLOCKLISTEDATISSUANCETIME,Issuer Certificate is distrusted at the time the subordinate certifiate was issued,SEC_ERROR_UNTRUSTED_ISSUER) diff --git a/security/nss/lib/libpkix/include/pkix_params.h b/security/nss/lib/libpkix/include/pkix_params.h new file mode 100644 index 0000000000..a4d8e485cb --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_params.h @@ -0,0 +1,1793 @@ +/* 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/. */ +/* + * This file defines functions associated with the various parameters used + * by the top-level functions. + * + */ + +#ifndef _PKIX_PARAMS_H +#define _PKIX_PARAMS_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_ProcessingParams + * + * PKIX_ProcessingParams are parameters used when validating or building a + * chain of certificates. Using the parameters, the caller can specify several + * things, including the various inputs to the PKIX chain validation + * algorithm (such as trust anchors, initial policies, etc), any customized + * functionality (such as CertChainCheckers, RevocationCheckers, CertStores), + * and whether revocation checking should be disabled. + * + * Once the caller has created the ProcessingParams object, the caller then + * passes it to PKIX_ValidateChain or PKIX_BuildChain, which uses it to call + * the user's callback functions as needed during the validation or building + * process. + * + * If a parameter is not set (or is set to NULL), it will be set to the + * default value for that parameter. The default value for the Date parameter + * is NULL, which indicates the current time when the path is validated. The + * default for the remaining parameters is the least constrained. + */ + +/* + * FUNCTION: PKIX_ProcessingParams_Create + * DESCRIPTION: + * + * Creates a new ProcessingParams object. Trust anchor list is set to + * newly created empty list of trust. In this case trust anchors will + * be taken from provided cert store. Pointed to the created + * ProcessingParams object is stored in "pParams". + * + * PARAMETERS: + * "anchors" + * Address of List of (non-empty) TrustAnchors to be used. + * Must be non-NULL. + * "pParams" + * 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 Params 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_ProcessingParams_Create( + PKIX_ProcessingParams **pParams, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetCertChainCheckers + * DESCRIPTION: + * + * Retrieves a pointer to the List of CertChainCheckers (if any) that are set + * in the ProcessingParams pointed to by "params" and stores it at + * "pCheckers". Each CertChainChecker represents a custom certificate + * validation check used by PKIX_ValidateChain or PKIX_BuildChain as needed + * during the validation or building process. If "params" does not have any + * CertChainCheckers, this function stores an empty List at "pCheckers". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of CertChainCheckers (if any) + * are to be stored. Must be non-NULL. + * "pCheckers" + * 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 Params 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_ProcessingParams_GetCertChainCheckers( + PKIX_ProcessingParams *params, + PKIX_List **pCheckers, /* list of PKIX_CertChainChecker */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetCertChainCheckers + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a List of + * CertChainCheckers pointed to by "checkers". Each CertChainChecker + * represents a custom certificate validation check used by + * PKIX_ValidateChain or PKIX_BuildChain as needed during the validation or + * building process. If "checkers" is NULL, no CertChainCheckers will be used. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of CertChainCheckers is to be + * set. Must be non-NULL. + * "checkers" + * Address of List of CertChainCheckers to be set. If NULL, no + * CertChainCheckers will be used. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" and "checkers" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetCertChainCheckers( + PKIX_ProcessingParams *params, + PKIX_List *checkers, /* list of PKIX_CertChainChecker */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_AddCertChainChecker + * DESCRIPTION: + * + * Adds the CertChainChecker pointed to by "checker" to the ProcessingParams + * pointed to by "params". The CertChainChecker represents a custom + * certificate validation check used by PKIX_ValidateChain or PKIX_BuildChain + * as needed during the validation or building process. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be added to. Must be non-NULL. + * "checker" + * Address of CertChainChecker to be added. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_AddCertChainChecker( + PKIX_ProcessingParams *params, + PKIX_CertChainChecker *checker, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetRevocationChecker + * DESCRIPTION: + * + * Retrieves a pointer to the RevocationChecker that are set + * in the ProcessingParams pointed to by "params" and stores it at + * "pRevChecker". Each RevocationChecker represents a revocation + * check used by PKIX_ValidateChain or PKIX_BuildChain as needed during the + * validation or building process. If "params" does not have any + * RevocationCheckers, this function stores an empty List at "pRevChecker". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of RevocationCheckers + * is to be stored. Must be non-NULL. + * "pRevChecker" + * 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 Params 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_ProcessingParams_GetRevocationChecker( + PKIX_ProcessingParams *params, + PKIX_RevocationChecker **pChecker, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetRevocationChecker + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a + * RevocationChecker pointed to by "revChecker". Revocation + * checker object should be created and assigned to processing + * parameters before chain build or validation can begin. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of RevocationCheckers is to be + * set. Must be non-NULL. + * "revChecker" + * Address of RevocationChecker to be set. Must be set before chain + * building or validation. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetRevocationChecker( + PKIX_ProcessingParams *params, + PKIX_RevocationChecker *revChecker, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetCertStores + * DESCRIPTION: + * + * Retrieves a pointer to the List of CertStores (if any) that are set in the + * ProcessingParams pointed to by "params" and stores it at "pStores". Each + * CertStore represents a particular repository from which certificates and + * CRLs can be retrieved by PKIX_ValidateChain or PKIX_BuildChain as needed + * during the validation or building process. If "params" does not have any + * CertStores, this function stores an empty List at "pStores". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of CertStores (if any) are to + * be stored. Must be non-NULL. + * "pStores" + * 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 Params 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_ProcessingParams_GetCertStores( + PKIX_ProcessingParams *params, + PKIX_List **pStores, /* list of PKIX_CertStore */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetCertStores + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a List of CertStores + * pointed to by "stores". Each CertStore represents a particular repository + * from which certificates and CRLs can be retrieved by PKIX_ValidateChain or + * PKIX_BuildChain as needed during the validation or building process. If + * "stores" is NULL, no CertStores will be used. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of CertStores is to be set. + * Must be non-NULL. + * "stores" + * Address of List of CertStores to be set. If NULL, no CertStores will + * be used. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetCertStores( + PKIX_ProcessingParams *params, + PKIX_List *stores, /* list of PKIX_CertStore */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_AddCertStore + * DESCRIPTION: + * + * Adds the CertStore pointed to by "store" to the ProcessingParams pointed + * to by "params". The CertStore represents a particular repository from + * which certificates and CRLs can be retrieved by PKIX_ValidateChain or + * PKIX_BuildChain as needed during the validation or building process. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be added to. Must be non-NULL. + * "store" + * Address of CertStore to be added. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_AddCertStore( + PKIX_ProcessingParams *params, + PKIX_CertStore *store, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetDate + * DESCRIPTION: + * + * Retrieves a pointer to the Date (if any) that is set in the + * ProcessingParams pointed to by "params" and stores it at "pDate". The + * Date represents the time for which the validation of the certificate chain + * should be determined. If "params" does not have any Date set, this function + * stores NULL at "pDate". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose Date (if any) is to be stored. + * Must be non-NULL. + * "pDate" + * 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 Params 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_ProcessingParams_GetDate( + PKIX_ProcessingParams *params, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetDate + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a Date pointed to by + * "date". The Date represents the time for which the validation of the + * certificate chain should be determined. If "date" is NULL, the current + * time is used during validation. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose Date is to be set. Must be non-NULL. + * "date" + * Address of Date to be set. If NULL, current time is used. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetDate( + PKIX_ProcessingParams *params, + PKIX_PL_Date *date, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetInitialPolicies + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (if any) that are set in the + * ProcessingParams pointed to by "params" and stores it at "pInitPolicies". + * Each OID represents an initial policy identifier, indicating that any + * one of these policies would be acceptable to the certificate user for + * the purposes of certification path processing. If "params" does not have + * any initial policies, this function stores an empty List at + * "pInitPolicies". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of OIDs (if any) are to be + * stored. Must be non-NULL. + * "pInitPolicies" + * 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 Params 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_ProcessingParams_GetInitialPolicies( + PKIX_ProcessingParams *params, + PKIX_List **pInitPolicies, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetInitialPolicies + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a List of OIDs + * pointed to by "initPolicies". + * + * Each OID represents an initial policy identifier, indicating that any + * one of these policies would be acceptable to the certificate user for + * the purposes of certification path processing. By default, any policy + * is acceptable (i.e. all policies), so a user that wants to allow any + * policy as acceptable does not need to call this method. Similarly, if + * initPolicies is NULL or points to an empty List, all policies are + * acceptable. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of OIDs is to be set. + * Must be non-NULL. + * "initPolicies" + * Address of List of OIDs to be set. If NULL or if pointing to an empty + * List, all policies are acceptable. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetInitialPolicies( + PKIX_ProcessingParams *params, + PKIX_List *initPolicies, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetPolicyQualifiersRejected + * DESCRIPTION: + * + * Checks whether the ProcessingParams pointed to by "params" indicate that + * policy qualifiers should be rejected and stores the Boolean result at + * "pRejected". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams used to determine whether or not policy + * qualifiers should be rejected. Must be non-NULL. + * "pRejected" + * 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 the function succeeds. + * Returns a Params 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_ProcessingParams_GetPolicyQualifiersRejected( + PKIX_ProcessingParams *params, + PKIX_Boolean *pRejected, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetPolicyQualifiersRejected + * DESCRIPTION: + * + * Specifies in the ProcessingParams pointed to by "params" whether policy + * qualifiers are rejected using the Boolean value of "rejected". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be set. Must be non-NULL. + * "rejected" + * Boolean value indicating whether policy qualifiers are to be rejected. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetPolicyQualifiersRejected( + PKIX_ProcessingParams *params, + PKIX_Boolean rejected, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetTargetCertConstraints + * DESCRIPTION: + * + * Retrieves a pointer to the CertSelector (if any) that is set in the + * ProcessingParams pointed to by "params" and stores it at "pConstraints". + * The CertSelector represents the constraints to be placed on the target + * certificate. If "params" does not have any CertSelector set, this function + * stores NULL at "pConstraints". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose CertSelector (if any) is to be + * stored. Must be non-NULL. + * "pConstraints" + * 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 Params 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_ProcessingParams_GetTargetCertConstraints( + PKIX_ProcessingParams *params, + PKIX_CertSelector **pConstraints, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetTargetCertConstraints + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a CertSelector + * pointed to by "constraints". The CertSelector represents the constraints + * to be placed on the target certificate. If "constraints" is NULL, no + * constraints are defined. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose CertSelector is to be set. + * Must be non-NULL. + * "constraints" + * Address of CertSelector to be set. If NULL, no constraints are defined. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetTargetCertConstraints( + PKIX_ProcessingParams *params, + PKIX_CertSelector *constraints, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetTrustAnchors + * DESCRIPTION: + * + * Retrieves a pointer to the List of TrustAnchors that are set in + * the ProcessingParams pointed to by "params" and stores it at "pAnchors". + * If the function succeeds, the pointer to the List is guaranteed to be + * non-NULL and the List is guaranteed to be non-empty. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of TrustAnchors are to + * be stored. Must be non-NULL. + * "pAnchors" + * 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 Params 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_ProcessingParams_GetTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_List **pAnchors, /* list of TrustAnchor */ + void *plContext); +/* + * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors + * DESCRIPTION: + * + * Sets user defined set of trust anchors. The handling of the trust anchors + * may be furthered alter via PKIX_ProcessingParams_SetUseOnlyTrustAnchors. + * By default, a certificate will be considered invalid if it does not chain + * to a trusted anchor from this list. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of TrustAnchors are to + * be stored. Must be non-NULL. + * "anchors" + * Address of the trust anchors list object. 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 Params 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_ProcessingParams_SetTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_List *pAnchors, /* list of TrustAnchor */ + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetUseOnlyTrustAnchors + * DESCRIPTION: + * + * Retrieves a pointer to the Boolean. The boolean value represents + * the switch value that is used to identify whether trust anchors, if + * specified, should be the exclusive source of trust information. + * If the function succeeds, the pointer to the Boolean is guaranteed to be + * non-NULL. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams. Must be non-NULL. + * "pUseOnlyTrustAnchors" + * 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 Params 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_ProcessingParams_GetUseOnlyTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_Boolean *pUseOnlyTrustAnchors, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors + * DESCRIPTION: + * + * Configures whether trust anchors are used as the exclusive source of trust. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams. Must be non-NULL. + * "useOnlyTrustAnchors" + * If true, indicates that trust anchors should be used exclusively when + * they have been specified via PKIX_ProcessingParams_SetTrustAnchors. A + * certificate will be considered invalid if it does not chain to a + * trusted anchor from that list. + * If false, indicates that the trust anchors are additive to whatever + * existing trust stores are configured. A certificate is considered + * valid if it chains to EITHER a trusted anchor from that list OR a + * certificate marked trusted in a trust store. + * "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 Params 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_ProcessingParams_SetUseOnlyTrustAnchors( + PKIX_ProcessingParams *params, + PKIX_Boolean useOnlyTrustAnchors, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetUseAIAForCertFetching + * DESCRIPTION: + * + * Retrieves a pointer to the Boolean. The boolean value represents + * the switch value that is used to identify if url in cert AIA extension + * may be used for cert fetching. + * If the function succeeds, the pointer to the Boolean is guaranteed to be + * non-NULL. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams. Must be non-NULL. + * "pUseAIA" + * 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 Params 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_ProcessingParams_GetUseAIAForCertFetching( + PKIX_ProcessingParams *params, + PKIX_Boolean *pUseAIA, /* list of TrustAnchor */ + void *plContext); +/* + * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors + * DESCRIPTION: + * + * Sets switch value that defines if url in cert AIA extension + * may be used for cert fetching. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams. + * "useAIA" + * Address of the trust anchors list object. 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 Params 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_ProcessingParams_SetUseAIAForCertFetching( + PKIX_ProcessingParams *params, + PKIX_Boolean useAIA, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetQualifyTargetCert + * DESCRIPTION: + * + * Sets a boolean value that tells if libpkix needs to check that + * the target certificate satisfies the conditions set in processing + * parameters. Includes but not limited to date, ku and eku checks. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of TrustAnchors are to + * be stored. Must be non-NULL. + * "qualifyTargetCert" + * boolean value if set to true will trigger qualification of the + * target certificate. + * "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 Params 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_ProcessingParams_SetQualifyTargetCert( + PKIX_ProcessingParams *params, + PKIX_Boolean qualifyTargetCert, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetHintCerts + * DESCRIPTION: + * + * Retrieves a pointer to a List of Certs supplied by the user as a suggested + * partial CertChain (subject to verification), that are set in the + * ProcessingParams pointed to by "params", and stores it at "pHintCerts". + * The List returned may be empty or NULL. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of TrustAnchors are to + * be stored. Must be non-NULL. + * "pHintCerts" + * 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 Params 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_ProcessingParams_GetHintCerts( + PKIX_ProcessingParams *params, + PKIX_List **pHintCerts, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetHintCerts + * DESCRIPTION: + * + * Stores a pointer to a List of Certs supplied by the user as a suggested + * partial CertChain (subject to verification), as an element in the + * ProcessingParams pointed to by "params". The List may be empty or NULL. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose List of HintCerts is to be stored. + * Must be non-NULL. + * "hintCerts" + * 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 Params 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_ProcessingParams_SetHintCerts( + PKIX_ProcessingParams *params, + PKIX_List *hintCerts, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_GetResourceLimits + * DESCRIPTION: + * + * Retrieves a pointer to the ResourceLimits (if any) that is set in the + * ProcessingParams pointed to by "params" and stores it at "pResourceLimits". + * The ResourceLimits represent the maximum resource usage that the caller + * desires (such as MaxTime). The ValidateChain or BuildChain call will not + * exceed these maximum limits. If "params" does not have any ResourceLimits + * set, this function stores NULL at "pResourceLimits". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose ResourceLimits (if any) are to be + * stored. Must be non-NULL. + * "pResourceLimits" + * 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 Params 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_ProcessingParams_GetResourceLimits( + PKIX_ProcessingParams *params, + PKIX_ResourceLimits **pResourceLimits, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetResourceLimits + * DESCRIPTION: + * + * Sets the ProcessingParams pointed to by "params" with a ResourceLimits + * object pointed to by "resourceLimits". The ResourceLimits represent the + * maximum resource usage that the caller desires (such as MaxTime). The + * ValidateChain or BuildChain call will not exceed these maximum limits. + * If "resourceLimits" is NULL, no ResourceLimits are defined. + * + * PARAMETERS: + * "params" + * Address of ProcessingParams whose ResourceLimits are to be set. + * Must be non-NULL. + * "resourceLimits" + * Address of ResourceLimits to be set. If NULL, no limits are defined. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetResourceLimits( + PKIX_ProcessingParams *params, + PKIX_ResourceLimits *resourceLimits, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_IsAnyPolicyInhibited + * DESCRIPTION: + * + * Checks whether the ProcessingParams pointed to by "params" indicate that + * anyPolicy is inhibited and stores the Boolean result at "pInhibited". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams used to determine whether or not anyPolicy + * inhibited. Must be non-NULL. + * "pInhibited" + * 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 the function succeeds. + * Returns a Params 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_ProcessingParams_IsAnyPolicyInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean *pInhibited, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetAnyPolicyInhibited + * DESCRIPTION: + * + * Specifies in the ProcessingParams pointed to by "params" whether anyPolicy + * is inhibited using the Boolean value of "inhibited". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be set. Must be non-NULL. + * "inhibited" + * Boolean value indicating whether anyPolicy is to be inhibited. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetAnyPolicyInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean inhibited, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_IsExplicitPolicyRequired + * DESCRIPTION: + * + * Checks whether the ProcessingParams pointed to by "params" indicate that + * explicit policies are required and stores the Boolean result at + * "pRequired". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams used to determine whether or not explicit + * policies are required. Must be non-NULL. + * "pRequired" + * 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 the function succeeds. + * Returns a Params 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_ProcessingParams_IsExplicitPolicyRequired( + PKIX_ProcessingParams *params, + PKIX_Boolean *pRequired, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetExplicitPolicyRequired + * DESCRIPTION: + * + * Specifies in the ProcessingParams pointed to by "params" whether explicit + * policies are required using the Boolean value of "required". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be set. Must be non-NULL. + * "required" + * Boolean value indicating whether explicit policies are to be required. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetExplicitPolicyRequired( + PKIX_ProcessingParams *params, + PKIX_Boolean required, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_IsPolicyMappingInhibited + * DESCRIPTION: + * + * Checks whether the ProcessingParams pointed to by "params" indicate that + * policyMapping is inhibited and stores the Boolean result at "pInhibited". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams used to determine whether or not policy + * mappings are inhibited. Must be non-NULL. + * "pInhibited" + * 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 the function succeeds. + * Returns a Params 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_ProcessingParams_IsPolicyMappingInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean *pInhibited, + void *plContext); + +/* + * FUNCTION: PKIX_ProcessingParams_SetPolicyMappingInhibited + * DESCRIPTION: + * + * Specifies in the ProcessingParams pointed to by "params" whether policy + * mapping is inhibited using the Boolean value of "inhibited". + * + * PARAMETERS: + * "params" + * Address of ProcessingParams to be set. Must be non-NULL. + * "inhibited" + * Boolean value indicating whether policy mapping is to be inhibited. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Params 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_ProcessingParams_SetPolicyMappingInhibited( + PKIX_ProcessingParams *params, + PKIX_Boolean inhibited, + void *plContext); + + +/* PKIX_ValidateParams + * + * PKIX_ValidateParams consists of a ProcessingParams object as well as the + * List of Certs (certChain) that the caller is trying to validate. + */ + +/* + * FUNCTION: PKIX_ValidateParams_Create + * DESCRIPTION: + * + * Creates a new ValidateParams object and stores it at "pParams". + * + * PARAMETERS: + * "procParams" + * Address of ProcessingParams to be used. Must be non-NULL. + * "chain" + * Address of List of Certs (certChain) to be validated. Must be non-NULL. + * "pParams" + * 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 Params 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_ValidateParams_Create( + PKIX_ProcessingParams *procParams, + PKIX_List *chain, + PKIX_ValidateParams **pParams, + void *plContext); + +/* + * FUNCTION: PKIX_ValidateParams_GetProcessingParams + * DESCRIPTION: + * + * Retrieves a pointer to the ProcessingParams that represent the basic + * certificate processing parameters used during chain validation and chain + * building from the ValidateParams pointed to by "valParams" and stores it + * at "pProcParams". If the function succeeds, the pointer to the + * ProcessingParams is guaranteed to be non-NULL. + * + * PARAMETERS: + * "valParams" + * Address of ValidateParams whose ProcessingParams are to be stored. + * Must be non-NULL. + * "pProcParams" + * 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 Params 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_ValidateParams_GetProcessingParams( + PKIX_ValidateParams *valParams, + PKIX_ProcessingParams **pProcParams, + void *plContext); + +/* + * FUNCTION: PKIX_ValidateParams_GetCertChain + * DESCRIPTION: + * + * Retrieves a pointer to the List of Certs (certChain) that is set in the + * ValidateParams pointed to by "valParams" and stores it at "pChain". If the + * function succeeds, the pointer to the CertChain is guaranteed to be + * non-NULL. + * + * PARAMETERS: + * "valParams" + * Address of ValidateParams whose CertChain is to be stored. + * Must be non-NULL. + * "pChain" + * 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 Params 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_ValidateParams_GetCertChain( + PKIX_ValidateParams *valParams, + PKIX_List **pChain, + void *plContext); + +/* PKIX_TrustAnchor + * + * A PKIX_TrustAnchor represents a trusted entity and can be specified using a + * self-signed certificate or using the trusted CA's name and public key. In + * order to limit the trust in the trusted entity, name constraints can also + * be imposed on the trust anchor. + */ + +/* + * FUNCTION: PKIX_TrustAnchor_CreateWithCert + * DESCRIPTION: + * + * Creates a new TrustAnchor object using the Cert pointed to by "cert" as + * the trusted certificate and stores it at "pAnchor". Once created, a + * TrustAnchor is immutable. + * + * PARAMETERS: + * "cert" + * Address of Cert to use as trusted certificate. Must be non-NULL. + * "pAnchor" + * 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 Params 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_TrustAnchor_CreateWithCert( + PKIX_PL_Cert *cert, + PKIX_TrustAnchor **pAnchor, + void *plContext); + +/* + * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair + * DESCRIPTION: + * + * Creates a new TrustAnchor object using the X500Name pointed to by "name", + * and the PublicKey pointed to by "pubKey" and stores it at "pAnchor". The + * CertNameConstraints pointed to by "nameConstraints" (if any) are used to + * limit the trust placed in this trust anchor. To indicate that name + * constraints don't apply, set "nameConstraints" to NULL. Once created, a + * TrustAnchor is immutable. + * + * PARAMETERS: + * "name" + * Address of X500Name to use as name of trusted CA. Must be non-NULL. + * "pubKey" + * Address of PublicKey to use as trusted public key. Must be non-NULL. + * "nameConstraints" + * Address of CertNameConstraints to use as initial name constraints. + * If NULL, no name constraints are applied. + * "pAnchor" + * 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 Params 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_TrustAnchor_CreateWithNameKeyPair( + PKIX_PL_X500Name *name, + PKIX_PL_PublicKey *pubKey, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_TrustAnchor **pAnchor, + void *plContext); + +/* + * FUNCTION: PKIX_TrustAnchor_GetTrustedCert + * DESCRIPTION: + * + * Retrieves a pointer to the Cert that is set in the TrustAnchor pointed to + * by "anchor" and stores it at "pCert". If "anchor" does not have a Cert + * set, this function stores NULL at "pCert". + * + * PARAMETERS: + * "anchor" + * Address of TrustAnchor whose Cert is to be stored. Must be non-NULL. + * "pChain" + * 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 Params 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_TrustAnchor_GetTrustedCert( + PKIX_TrustAnchor *anchor, + PKIX_PL_Cert **pCert, + void *plContext); + +/* + * FUNCTION: PKIX_TrustAnchor_GetCAName + * DESCRIPTION: + * + * Retrieves a pointer to the CA's X500Name (if any) that is set in the + * TrustAnchor pointed to by "anchor" and stores it at "pCAName". If "anchor" + * does not have an X500Name set, this function stores NULL at "pCAName". + * + * PARAMETERS: + * "anchor" + * Address of TrustAnchor whose CA Name is to be stored. Must be non-NULL. + * "pCAName" + * 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 Params 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_TrustAnchor_GetCAName( + PKIX_TrustAnchor *anchor, + PKIX_PL_X500Name **pCAName, + void *plContext); + +/* + * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey + * DESCRIPTION: + * + * Retrieves a pointer to the CA's PublicKey (if any) that is set in the + * TrustAnchor pointed to by "anchor" and stores it at "pPubKey". If "anchor" + * does not have a PublicKey set, this function stores NULL at "pPubKey". + * + * PARAMETERS: + * "anchor" + * Address of TrustAnchor whose CA PublicKey is to be stored. + * Must be non-NULL. + * "pPubKey" + * 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 Params 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_TrustAnchor_GetCAPublicKey( + PKIX_TrustAnchor *anchor, + PKIX_PL_PublicKey **pPubKey, + void *plContext); + +/* + * FUNCTION: PKIX_TrustAnchor_GetNameConstraints + * DESCRIPTION: + * + * Retrieves a pointer to the CertNameConstraints (if any) set in the + * TrustAnchor pointed to by "anchor" and stores it at "pConstraints". If + * "anchor" does not have any CertNameConstraints set, this function stores + * NULL at "pConstraints". + * + * PARAMETERS: + * "anchor" + * Address of TrustAnchor whose CertNameConstraints are to be stored. + * Must be non-NULL. + * "pConstraints" + * 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 Params 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_TrustAnchor_GetNameConstraints( + PKIX_TrustAnchor *anchor, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext); + +/* PKIX_ResourceLimits + * + * A PKIX_ResourceLimits object represents the maximum resource usage that + * the caller desires. The ValidateChain or BuildChain call + * will not exceed these maximum limits. For example, the caller may want + * a timeout value of 1 minute, meaning that if the ValidateChain or + * BuildChain function is unable to finish in 1 minute, it should abort + * with an Error. + */ + +/* + * FUNCTION: PKIX_ResourceLimits_Create + * DESCRIPTION: + * + * Creates a new ResourceLimits object and stores it at "pResourceLimits". + * + * PARAMETERS: + * "pResourceLimits" + * 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 ResourceLimits 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_ResourceLimits_Create( + PKIX_ResourceLimits **pResourceLimits, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxTime + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the maximum time that is + * set in the ResourceLimits object pointed to by "resourceLimits" and stores + * it at "pMaxTime". This maximum time (in seconds) should not be exceeded + * by the function whose ProcessingParams contain this ResourceLimits object + * (typically ValidateChain or BuildChain). It essentially functions as a + * time-out value and is only appropriate if blocking I/O is being used. + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum time (in seconds) is + * to be stored. Must be non-NULL. + * "pMaxTime" + * Address where PKIX_UInt32 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 ResourceLimits 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_ResourceLimits_GetMaxTime( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 *pMaxTime, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxTime + * DESCRIPTION: + * + * Sets the maximum time of the ResourceLimits object pointed to by + * "resourceLimits" using the PKIX_UInt32 value of "maxTime". This + * maximum time (in seconds) should not be exceeded by the function + * whose ProcessingParams contain this ResourceLimits object + * (typically ValidateChain or BuildChain). It essentially functions as a + * time-out value and is only appropriate if blocking I/O is being used. + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum time (in seconds) is + * to be set. Must be non-NULL. + * "maxTime" + * Value of PKIX_UInt32 representing the maximum time (in seconds) + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a ResourceLimits 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_ResourceLimits_SetMaxTime( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 maxTime, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxFanout + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the maximum fanout that is + * set in the ResourceLimits object pointed to by "resourceLimits" and stores + * it at "pMaxFanout". This maximum fanout (number of certs) should not be + * exceeded by the function whose ProcessingParams contain this ResourceLimits + * object (typically ValidateChain or BuildChain). If the builder encounters + * more than this maximum number of certificates when searching for the next + * candidate certificate, it should abort and return an error. This + * parameter is only relevant for ValidateChain if it needs to internally call + * BuildChain (e.g. in order to build the chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum fanout (number of certs) + * is to be stored. Must be non-NULL. + * "pMaxFanout" + * Address where PKIX_UInt32 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 ResourceLimits 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_ResourceLimits_GetMaxFanout( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 *pMaxFanout, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxFanout + * DESCRIPTION: + * + * Sets the maximum fanout of the ResourceLimits object pointed to by + * "resourceLimits" using the PKIX_UInt32 value of "maxFanout". This maximum + * fanout (number of certs) should not be exceeded by the function whose + * ProcessingParams contain this ResourceLimits object (typically ValidateChain + * or BuildChain). If the builder encounters more than this maximum number of + * certificates when searching for the next candidate certificate, it should + * abort and return an Error. This parameter is only relevant for ValidateChain + * if it needs to internally call BuildChain (e.g. in order to build the + * chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum fanout (number of certs) + * is to be set. Must be non-NULL. + * "maxFanout" + * Value of PKIX_UInt32 representing the maximum fanout (number of certs) + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a ResourceLimits 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_ResourceLimits_SetMaxFanout( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 maxFanout, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxDepth + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the maximum depth that is + * set in the ResourceLimits object pointed to by "resourceLimits" and stores + * it at "pMaxDepth". This maximum depth (number of certs) should not be + * exceeded by the function whose ProcessingParams contain this ResourceLimits + * object (typically ValidateChain or BuildChain). If the builder encounters + * more than this maximum number of certificates when searching for the next + * candidate certificate, it should abort and return an error. This + * parameter is only relevant for ValidateChain if it needs to internally call + * BuildChain (e.g. in order to build the chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum depth (number of certs) + * is to be stored. Must be non-NULL. + * "pMaxDepth" + * Address where PKIX_UInt32 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 ResourceLimits 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_ResourceLimits_GetMaxDepth( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 *pMaxDepth, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxDepth + * DESCRIPTION: + * + * Sets the maximum depth of the ResourceLimits object pointed to by + * "resourceLimits" using the PKIX_UInt32 value of "maxDepth". This maximum + * depth (number of certs) should not be exceeded by the function whose + * ProcessingParams contain this ResourceLimits object (typically ValidateChain + * or BuildChain). If the builder encounters more than this maximum number of + * certificates when searching for the next candidate certificate, it should + * abort and return an Error. This parameter is only relevant for ValidateChain + * if it needs to internally call BuildChain (e.g. in order to build the + * chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum depth (number of certs) + * is to be set. Must be non-NULL. + * "maxDepth" + * Value of PKIX_UInt32 representing the maximum depth (number of certs) + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a ResourceLimits 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_ResourceLimits_SetMaxDepth( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 maxDepth, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCerts + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the maximum number of traversed + * certs that is set in the ResourceLimits object pointed to by "resourceLimits" + * and stores it at "pMaxNumber". This maximum number of traversed certs should + * not be exceeded by the function whose ProcessingParams contain this ResourceLimits + * object (typically ValidateChain or BuildChain). If the builder traverses more + * than this number of certs during the build process, it should abort and + * return an Error. This parameter is only relevant for ValidateChain if it + * needs to internally call BuildChain (e.g. in order to build the chain to a + * CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum number of traversed certs + * is to be stored. Must be non-NULL. + * "pMaxNumber" + * Address where PKIX_UInt32 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 ResourceLimits 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_ResourceLimits_GetMaxNumberOfCerts( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 *pMaxNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCerts + * DESCRIPTION: + * + * Sets the maximum number of traversed certs of the ResourceLimits object + * pointed to by "resourceLimits" using the PKIX_UInt32 value of "maxNumber". + * This maximum number of traversed certs should not be exceeded by the function + * whose ProcessingParams contain this ResourceLimits object (typically ValidateChain + * or BuildChain). If the builder traverses more than this number of certs + * during the build process, it should abort and return an Error. This parameter + * is only relevant for ValidateChain if it needs to internally call BuildChain + * (e.g. in order to build the chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum number of traversed certs + * is to be set. Must be non-NULL. + * "maxNumber" + * Value of PKIX_UInt32 representing the maximum number of traversed certs + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a ResourceLimits 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_ResourceLimits_SetMaxNumberOfCerts( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 maxNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCRLs + * DESCRIPTION: + * + * Retrieves a PKIX_UInt32 (if any) representing the maximum number of traversed + * CRLs that is set in the ResourceLimits object pointed to by "resourceLimits" + * and stores it at "pMaxNumber". This maximum number of traversed CRLs should + * not be exceeded by the function whose ProcessingParams contain this ResourceLimits + * object (typically ValidateChain or BuildChain). If the builder traverses more + * than this number of CRLs during the build process, it should abort and + * return an Error. This parameter is only relevant for ValidateChain if it + * needs to internally call BuildChain (e.g. in order to build the chain to a + * CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum number of traversed CRLs + * is to be stored. Must be non-NULL. + * "pMaxNumber" + * Address where PKIX_UInt32 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 ResourceLimits 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_ResourceLimits_GetMaxNumberOfCRLs( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 *pMaxNumber, + void *plContext); + +/* + * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCRLs + * DESCRIPTION: + * + * Sets the maximum number of traversed CRLs of the ResourceLimits object + * pointed to by "resourceLimits" using the PKIX_UInt32 value of "maxNumber". + * This maximum number of traversed CRLs should not be exceeded by the function + * whose ProcessingParams contain this ResourceLimits object (typically ValidateChain + * or BuildChain). If the builder traverses more than this number of CRLs + * during the build process, it should abort and return an Error. This parameter + * is only relevant for ValidateChain if it needs to internally call BuildChain + * (e.g. in order to build the chain to a CRL's issuer). + * + * PARAMETERS: + * "resourceLimits" + * Address of ResourceLimits object whose maximum number of traversed CRLs + * is to be set. Must be non-NULL. + * "maxNumber" + * Value of PKIX_UInt32 representing the maximum number of traversed CRLs + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "params" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a ResourceLimits 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_ResourceLimits_SetMaxNumberOfCRLs( + PKIX_ResourceLimits *resourceLimits, + PKIX_UInt32 maxNumber, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PARAMS_H */ diff --git a/security/nss/lib/libpkix/include/pkix_pl_pki.h b/security/nss/lib/libpkix/include/pkix_pl_pki.h new file mode 100644 index 0000000000..0a449b94a7 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_pl_pki.h @@ -0,0 +1,2735 @@ +/* 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/. */ +/* + * This file defines several platform independent functions to + * manipulate certificates and CRLs in a portable manner. + * + */ + +#ifndef _PKIX_PL_PKI_H +#define _PKIX_PL_PKI_H + +#include "pkixt.h" +#include "seccomon.h" +#include "certt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* + * Cert + * + * A Cert represents an X.509 certificate. It can be created using the bytes + * of a valid ASN.1 DER encoding. Once created, a Cert is immutable. The + * following functions include accessors (gettors) for the various components + * of an X.509 certificate. Also included are functions to perform various + * checks on a certificate, including name constraints, key usage, validity + * (expiration), and signature verification. + */ + +/* + * FUNCTION: PKIX_PL_Cert_Create + * DESCRIPTION: + * + * Creates a new certificate using the bytes in the ByteArray pointed to by + * "byteArray" and stores it at "pCert". If the bytes are not a valid ASN.1 + * DER encoding of a certificate, a PKIX_Error pointer is returned. Once + * created, a Cert is immutable. + * + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * TBSCertificate ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * serialNumber CertificateSerialNumber, + * signature AlgorithmIdentifier, + * issuer Name, + * validity Validity, + * subject Name, + * subjectPublicKeyInfo SubjectPublicKeyInfo, + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version MUST be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version MUST be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version MUST be v3 + * } + * + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + * + * UniqueIdentifier ::= BIT STRING + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + * + * PARAMETERS: + * "byteArray" + * Address of ByteArray representing the CERT's DER encoding. + * Must be non-NULL. + * "pCert" + * 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 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_PL_Cert_Create( + PKIX_PL_ByteArray *byteArray, + PKIX_PL_Cert **pCert, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate + * DESCRIPTION: + * + * Creates a new certificate using passed in CERTCertificate object. + * + * PARAMETERS: + * "nssCert" + * The object that will be used to create new PKIX_PL_Cert. + * "pCert" + * 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 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_PL_Cert_CreateFromCERTCertificate( + const CERTCertificate *nssCert, + PKIX_PL_Cert **pCert, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetCERTCertificate + * DESCRIPTION: + * + * Returns underlying CERTCertificate structure. Return CERTCertificate + * object is duplicated and should be destroyed by caller. + * + * PARAMETERS: + * "cert" + * Address of PKIX_PL_Cert. Must be non-NULL. + * "pCert" + * 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 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_PL_Cert_GetCERTCertificate( + PKIX_PL_Cert *cert, + CERTCertificate **pnssCert, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetVersion + * DESCRIPTION: + * + * Retrieves the version of the Cert pointed to by "cert" and stores it at + * "pVersion". The version number will either be 0, 1, or 2 (corresponding to + * v1, v2, or v3, respectively). + * + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * PARAMETERS: + * "cert" + * Address of Cert whose version is to be stored. Must be non-NULL. + * "pVersion" + * Address where PKIX_UInt32 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_PL_Cert_GetVersion( + PKIX_PL_Cert *cert, + PKIX_UInt32 *pVersion, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSerialNumber + * DESCRIPTION: + * + * Retrieves a pointer to the BigInt that represents the serial number of the + * Cert pointed to by "cert" and stores it at "pSerialNumber". + * + * CertificateSerialNumber ::= INTEGER + * + * PARAMETERS: + * "cert" + * Address of Cert whose serial number is to be stored. Must be non-NULL. + * "pSerial" + * 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 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_PL_Cert_GetSerialNumber( + PKIX_PL_Cert *cert, + PKIX_PL_BigInt **pSerial, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetIssuer + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name that represents the issuer DN of the + * Cert pointed to by "cert" and stores it at "pIssuer". + * + * PARAMETERS: + * "cert" + * Address of Cert whose issuer is to be stored. Must be non-NULL. + * "pIssuer" + * 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 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_PL_Cert_GetIssuer( + PKIX_PL_Cert *cert, + PKIX_PL_X500Name **pIssuer, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSubject + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name that represents the subject DN of the + * Cert pointed to by "cert" and stores it at "pSubject". If the Cert does not + * have a subject DN, this function stores NULL at "pSubject". + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject is to be stored. Must be non-NULL. + * "pSubject" + * 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 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_PL_Cert_GetSubject( + PKIX_PL_Cert *cert, + PKIX_PL_X500Name **pSubject, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId + * DESCRIPTION: + * + * Retrieves a pointer to the OID that represents the subject public key + * algorithm of the Cert pointed to by "cert" and stores it at + * "pSubjKeyAlgId". + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject public key algorithm OID is to be stored. + * Must be non-NULL. + * "pSubjKeyAlgId" + * 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 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_PL_Cert_GetSubjectPublicKeyAlgId( + PKIX_PL_Cert *cert, + PKIX_PL_OID **pSubjKeyAlgId, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey + * DESCRIPTION: + * + * Retrieves a pointer to the PublicKey that represents the subject public key + * of the Cert pointed to by "cert" and stores it at "pPublicKey". + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject public key is to be stored. + * Must be non-NULL. + * "pPublicKey" + * 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 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_PL_Cert_GetSubjectPublicKey( + PKIX_PL_Cert *cert, + PKIX_PL_PublicKey **pPublicKey, + void *plContext); + +/* + * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters + * DESCRIPTION: + * + * Determines if the PublicKey pointed to by "pubKey" is a DSA Key with null + * parameters and stores the result at "pNeedsParams". + * + * PARAMETERS: + * "pubKey" + * Address of the Public Key of interest. Must be non-NULL. + * "pNeedsParams" + * 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 PublicKey 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_PL_PublicKey_NeedsDSAParameters( + PKIX_PL_PublicKey *pubKey, + PKIX_Boolean *pNeedsParams, + void *plContext); + +/* + * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey + * DESCRIPTION: + * + * This function is used for DSA key parameter inheritance, which allows a + * first DSA key with omitted parameters (pointed to by "firstKey") to inherit + * the PQG parameters of a second DSA key that does have parameters. (pointed + * to by "secondKey"). Once created, a PublicKey is immutable. + * + * Specifically, the algorithm used by the function is: + * + * If the first PublicKey is not a DSA public key with omitted parameters, + * the function stores NULL at "pResultKey". (No Error is returned) + * Else if the second PublicKey is not a DSA public key with non-NULL, + * parameters, the function returns an Error. + * Else + * the function creates a third PublicKey with a "Y" value from the + * first PublicKey and the DSA parameters from the second PublicKey, + * and stores it at "pResultKey". + * + * PARAMETERS: + * "firstKey" + * Address of a Public Key that needs to inherit DSA parameters. + * Must be non-NULL. + * "secondKey" + * Address of a Public Key that has DSA parameters that will be inherited + * by "firstKey". Must be non-NULL. + * "pResultKey" + * 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 PublicKey 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_PL_PublicKey_MakeInheritedDSAPublicKey( + PKIX_PL_PublicKey *firstKey, + PKIX_PL_PublicKey *secondKey, + PKIX_PL_PublicKey **pResultKey, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (each OID corresponding to a + * critical extension of the Cert pointed to by "cert") and stores it at + * "pExtensions". If "cert" does not have any critical extensions, this + * function stores an empty List at "pExtensions". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "cert" + * Address of Cert whose critical extension OIDs are to be stored. + * Must be non-NULL. + * "pExtensions" + * 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 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_PL_Cert_GetCriticalExtensionOIDs( + PKIX_PL_Cert *cert, + PKIX_List **pExtensions, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier + * DESCRIPTION: + * + * Retrieves a pointer to a ByteArray representing the authority key + * identifier extension of the Cert pointed to by "cert" and stores it at + * "pAuthKeyId". + * + * Note that this function only retrieves the keyIdentifier component + * (OCTET STRING) of the AuthorityKeyIdentifier extension, when present. + * + * If "cert" does not have an AuthorityKeyIdentifier extension or if the + * keyIdentifier component of the AuthorityKeyIdentifier extension is not + * present, this function stores NULL at "pAuthKeyId". + * + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + * + * PARAMETERS: + * "cert" + * Address of Cert whose authority key identifier is to be stored. + * Must be non-NULL. + * "pAuthKeyId" + * 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 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_PL_Cert_GetAuthorityKeyIdentifier( + PKIX_PL_Cert *cert, + PKIX_PL_ByteArray **pAuthKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier + * DESCRIPTION: + * + * Retrieves a pointer to a ByteArray representing the subject key identifier + * extension of the Cert pointed to by "cert" and stores it at "pSubjKeyId". + * If "cert" does not have a SubjectKeyIdentifier extension, this function + * stores NULL at "pSubjKeyId". + * + * SubjectKeyIdentifier ::= KeyIdentifier + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject key identifier is to be stored. + * Must be non-NULL. + * "pSubjKeyId" + * 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 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_PL_Cert_GetSubjectKeyIdentifier( + PKIX_PL_Cert *cert, + PKIX_PL_ByteArray **pSubjKeyId, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames + * DESCRIPTION: + * + * Retrieves a pointer to the List of GeneralNames (each GeneralName + * representing a subject alternative name found in the subject alternative + * names extension of the Cert pointed to by "cert") and stores it at + * "pSubjectAltNames". If "cert" does not have a SubjectAlternativeNames + * extension, this function stores NULL at "pSubjectAltNames". + * + * Note that the List returned by this function is immutable. + * + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * PARAMETERS: + * "cert" + * Address of Cert whose subjectAltNames are to be stored. + * Must be non-NULL. + * "pSubjectAltNames" + * 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 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_PL_Cert_GetSubjectAltNames( + PKIX_PL_Cert *cert, + PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames + * DESCRIPTION: + * + * Retrieves a pointer to the List of GeneralNames (each GeneralName + * representing a subject DN or a subject alternative name found in the + * subject alternative names extension of the Cert pointed to by "cert") and + * stores it at "pAllSubjectNames".If the Subject DN of "cert" is empty and + * it does not have a SubjectAlternativeNames extension, this function stores + * NULL at "pAllSubjectNames". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject DN and subjectAltNames are to be stored. + * Must be non-NULL. + * "pAllSubjectNames" + * 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 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_PL_Cert_GetAllSubjectNames( + PKIX_PL_Cert *cert, + PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage + * DESCRIPTION: + * + * Retrieves a pointer to a List of OIDs (each OID corresponding to an + * extended key usage of the Cert pointed to by "cert") and stores it at + * "pKeyUsage". If "cert" does not have an extended key usage extension, this + * function stores a NULL at "pKeyUsage". + * + * Note that the List returned by this function is immutable. + * + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + * + * PARAMETERS: + * "cert" + * Address of Cert whose extended key usage OIDs are to be stored. + * Must be non-NULL. + * "pKeyUsage" + * 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 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_PL_Cert_GetExtendedKeyUsage( + PKIX_PL_Cert *cert, + PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetNameConstraints + * DESCRIPTION: + * + * Retrieves a pointer to a CertNameConstraints object representing the name + * constraints extension of the Cert pointed to by "cert" and stores it at + * "pNameConstraints". + * + * If "cert" does not have a name constraints extension, this function stores + * NULL at "pNameConstraints". + * + * NameConstraints ::= SEQUENCE { + * permittedSubtrees [0] GeneralSubtrees OPTIONAL, + * excludedSubtrees [1] GeneralSubtrees OPTIONAL } + * + * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + * + * GeneralSubtree ::= SEQUENCE { + * base GeneralName, + * minimum [0] BaseDistance DEFAULT 0, + * maximum [1] BaseDistance OPTIONAL } + * + * BaseDistance ::= INTEGER (0..MAX) + * + * PARAMETERS: + * "cert" + * Address of Cert whose name constraints extension is to be stored. + * Must be non-NULL. + * "pNameConstraints" + * 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 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_PL_Cert_GetNameConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetBasicConstraints + * DESCRIPTION: + * + * Retrieves a pointer to a CertBasicConstraints object representing the basic + * constraints extension of the Cert pointed to by "cert" and stores it at + * "pBasicConstraints". + * + * If "cert" does not have a basic constraints extension, this function stores + * NULL at "pBasicConstraints". Once created, a CertBasicConstraints object + * is immutable. + * + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + * + * PARAMETERS: + * "cert" + * Address of Cert whose basic constraints extension is to be stored. + * Must be non-NULL. + * "pBasicConstraints" + * 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 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_PL_Cert_GetBasicConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertBasicConstraints **pBasicConstraints, + void *plContext); + +/* + * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag + * DESCRIPTION: + * + * Retrieves a pointer to a Boolean value representing the cA Flag component + * of the CertBasicConstraints object pointed to by "basicConstraints" and + * stores it at "pResult". + * + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + * + * PARAMETERS: + * "basicConstraints" + * Address of CertBasicConstraints whose cA Flag is to be stored. + * 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 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_PL_BasicConstraints_GetCAFlag( + PKIX_PL_CertBasicConstraints *basicConstraints, + PKIX_Boolean *pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint + * DESCRIPTION: + * + * Retrieves a pointer to an integer value representing the pathLenConstraint + * component of the CertBasicConstraints object pointed to by + * "basicConstraints" and stores it at "pPathLenConstraint". If the + * pathLenConstraint component is not present, this function stores -1 at + * "pPathLenConstraint". + * + * PARAMETERS: + * "basicConstraints" + * Address of CertBasicConstraints whose pathLen is to be stored. + * Must be non-NULL. + * "pPathLenConstraint" + * Address where PKIX_Int32 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_PL_BasicConstraints_GetPathLenConstraint( + PKIX_PL_CertBasicConstraints *basicConstraints, + PKIX_Int32 *pPathLenConstraint, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyInformation + * DESCRIPTION: + * + * Retrieves a pointer to a List of CertPolicyInfos found in the certificate + * policies extension of the Cert pointed to by "cert" and stores it at + * "pPolicyInfo". If "cert" does not have a certificate policies extension, + * this function stores NULL at "pPolicyInfo". Once created, a CertPolicyInfo + * object is immutable. + * + * Note that the List returned by this function is immutable. + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * PARAMETERS: + * "cert" + * Address of Cert whose CertPolicyInfos are to be stored. + * Must be non-NULL. + * "pPolicyInfo" + * 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 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_PL_Cert_GetPolicyInformation( + PKIX_PL_Cert *cert, + PKIX_List **pPolicyInfo, /* list of PKIX_PL_CertPolicyInfo */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolicyId + * DESCRIPTION: + * + * Retrieves a pointer to an OID representing the policyIdentifier of the + * CertPolicyInfo pointed to by "policyInfo" and stores it at "pCertPolicyId". + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PARAMETERS: + * "policyInfo" + * Address of CertPolicyInfo whose policy identifier is to be stored. + * Must be non-NULL. + * "pCertPolicyId" + * 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 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_PL_CertPolicyInfo_GetPolicyId( + PKIX_PL_CertPolicyInfo *policyInfo, + PKIX_PL_OID **pCertPolicyId, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolQualifiers + * DESCRIPTION: + * + * Retrieves a pointer to a List of the CertPolicyQualifiers representing + * the policyQualifiers of the CertPolicyInfo pointed to by "policyInfo" and + * stores it at "pPolicyQualifiers". If "policyInfo" does not have any + * policyQualifiers, this function stores NULL at "pPolicyQualifiers". Once + * created, a CertPolicyQualifier is immutable. + * + * Note that the List returned by this function is immutable. + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * PARAMETERS: + * "policyInfo" + * Address of CertPolicyInfo whose policy qualifiers List is to be stored. + * Must be non-NULL. + * "pPolicyQualifiers" + * 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 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_PL_CertPolicyInfo_GetPolQualifiers( + PKIX_PL_CertPolicyInfo *policyInfo, + PKIX_List **pPolicyQualifiers, /* list of PKIX_PL_CertPolicyQualifier */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_PolicyQualifier_GetPolicyQualifierId + * DESCRIPTION: + * + * Retrieves a pointer to an OID representing the policyQualifierId of the + * CertPolicyQualifier pointed to by "policyQualifier" and stores it at + * "pPolicyQualifierId". + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * PolicyQualifierId ::= + * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * PARAMETERS: + * "policyQualifier" + * Address of CertPolQualifier whose policyQualifierId is to be stored. + * Must be non-NULL. + * "pPolicyQualifierId" + * 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 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_PL_PolicyQualifier_GetPolicyQualifierId( + PKIX_PL_CertPolicyQualifier *policyQualifier, + PKIX_PL_OID **pPolicyQualifierId, + void *plContext); + +/* + * FUNCTION: PKIX_PL_PolicyQualifier_GetQualifier + * DESCRIPTION: + * + * Retrieves a pointer to a ByteArray representing the qualifier of the + * CertPolicyQualifier pointed to by "policyQualifier" and stores it at + * "pQualifier". + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * PARAMETERS: + * "policyQualifier" + * Address of CertPolicyQualifier whose qualifier is to be stored. + * Must be non-NULL. + * "pQualifier" + * 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 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_PL_PolicyQualifier_GetQualifier( + PKIX_PL_CertPolicyQualifier *policyQualifier, + PKIX_PL_ByteArray **pQualifier, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyMappings + * DESCRIPTION: + * + * Retrieves a pointer to a List of CertPolicyMaps found in the policy + * mappings extension of the Cert pointed to by "cert" and stores it at + * "pPolicyMappings". If "cert" does not have a policy mappings extension, + * this function stores NULL at "pPolicyMappings". Once created, a + * CertPolicyMap is immutable. + * + * Note that the List returned by this function is immutable. + * + * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + * issuerDomainPolicy CertPolicyId, + * subjectDomainPolicy CertPolicyId } + * + * PARAMETERS: + * "cert" + * Address of Cert whose CertPolicyMaps are to be stored. + * Must be non-NULL. + * "pPolicyMappings" + * 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 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_PL_Cert_GetPolicyMappings( + PKIX_PL_Cert *cert, + PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy + * DESCRIPTION: + * + * Retrieves a pointer to an OID representing the issuerDomainPolicy of the + * CertPolicyMap pointed to by "policyMapping" and stores it at + * "pIssuerDomainPolicy". + * + * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + * issuerDomainPolicy CertPolicyId, + * subjectDomainPolicy CertPolicyId } + * + * PARAMETERS: + * "policyMapping" + * Address of CertPolicyMap whose issuerDomainPolicy is to be stored. + * Must be non-NULL. + * "pIssuerDomainPolicy" + * 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 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_PL_CertPolicyMap_GetIssuerDomainPolicy( + PKIX_PL_CertPolicyMap *policyMapping, + PKIX_PL_OID **pIssuerDomainPolicy, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy + * DESCRIPTION: + * + * Retrieves a pointer to an OID representing the subjectDomainPolicy of the + * CertPolicyMap pointed to by "policyMapping" and stores it at + * "pSubjectDomainPolicy". + * + * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + * issuerDomainPolicy CertPolicyId, + * subjectDomainPolicy CertPolicyId } + * + * PARAMETERS: + * "policyMapping" + * Address of CertPolicyMap whose subjectDomainPolicy is to be stored. + * Must be non-NULL. + * "pSubjectDomainPolicy" + * 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 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_PL_CertPolicyMap_GetSubjectDomainPolicy( + PKIX_PL_CertPolicyMap *policyMapping, + PKIX_PL_OID **pSubjectDomainPolicy, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy + * DESCRIPTION: + * + * Retrieves the requireExplicitPolicy value of the policy constraints + * extension of the Cert pointed to by "cert" and stores it at "pSkipCerts". + * If "cert" does not have a policy constraints extension or the + * requireExplicitPolicy component is not populated, this function stores -1 + * at "pSkipCerts". + * + * PolicyConstraints ::= SEQUENCE { + * requireExplicitPolicy [0] SkipCerts OPTIONAL, + * inhibitPolicyMapping [1] SkipCerts OPTIONAL } + * + * SkipCerts ::= INTEGER (0..MAX) + * + * PARAMETERS: + * "cert" + * Address of Cert whose requireExplicitPolicy value is to be stored. + * Must be non-NULL. + * "pSkipCerts" + * Address where PKIX_Int32 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_PL_Cert_GetRequireExplicitPolicy( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited + * DESCRIPTION: + * + * Retrieves the inhibitPolicyMapping value of the policy constraints + * extension of the Cert pointed to by "cert" and stores it at "pSkipCerts". + * If "cert" does not have a policy constraints extension or the + * inhibitPolicyMapping component is not populated, this function stores -1 + * at "pSkipCerts". + * + * PolicyConstraints ::= SEQUENCE { + * requireExplicitPolicy [0] SkipCerts OPTIONAL, + * inhibitPolicyMapping [1] SkipCerts OPTIONAL } + * + * SkipCerts ::= INTEGER (0..MAX) + * + * PARAMETERS: + * "cert" + * Address of Cert whose requireExplicitPolicy value is to be stored. + * Must be non-NULL. + * "pSkipCerts" + * Address where PKIX_Int32 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_PL_Cert_GetPolicyMappingInhibited( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy + * DESCRIPTION: + * + * Retrieves the value of the inhibit any-policy extension of the Cert + * pointed to by "cert" and stores it at "pSkipCerts". If "cert" does not have + * an inhibit any-policy extension, this function stores -1 at "pSkipCerts". + * + * InhibitAnyPolicy ::= SkipCerts + * + * SkipCerts ::= INTEGER (0..MAX) + * + * PARAMETERS: + * "cert" + * Address of Cert whose inhibit any-policy extensions value is to be + * stored. Must be non-NULL. + * "pSkipCerts" + * Address where PKIX_Int32 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_PL_Cert_GetInhibitAnyPolicy( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext); + +/* policy processing functions */ + +/* + * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical + * DESCRIPTION: + * + * Checks whether the certificate policies extension of the Cert pointed to + * by "cert" is critical and stores the Boolean result at "pCritical". If + * "cert" does not have a certificate policies extension, this function + * stores NULL at "pCritical". + * + * XXX what distinguishes NULL from PKIX_FALSE? + * + * PARAMETERS: + * "cert" + * Address of Cert whose certificate policies extension's criticality is + * to be determined. Must be non-NULL. + * "pCritical" + * Address where PKIX_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_PL_Cert_AreCertPoliciesCritical( + PKIX_PL_Cert *cert, + PKIX_Boolean *pCritical, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_CheckNameConstraints + * DESCRIPTION: + * + * Checks whether the subject distinguished name and subject alternative names + * of the Cert pointed to by "cert" satisfy the CertNameConstraints pointed + * to by "nameConstraints". If the CertNameConstraints are not satisfied, a + * PKIX_Error pointer is returned. If "nameConstraints" is NULL, the function + * does nothing. + * + * PARAMETERS: + * "cert" + * Address of Cert whose subject names are to be checked. + * Must be non-NULL. + * "nameConstraints" + * Address of CertNameConstraints that need to be satisfied. + * "treatCommonNameAsDNSName" + * PKIX_TRUE if the subject common name should be considered a dNSName + * when evaluating name constraints. + * "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_PL_Cert_CheckNameConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean treatCommonNameAsDNSName, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_MergeNameConstraints + * DESCRIPTION: + * + * Merges the CertNameConstraints pointed to by "firstNC" and the + * CertNameConstraints pointed to by "secondNC" and stores the merged + * CertNameConstraints at "pResultNC". If "secondNC" is NULL, the + * CertNameConstraints pointed to by "firstNC" is stored at "pResultNC". + * + * Once created, a CertNameConstraints object is immutable. + * + * PARAMETERS: + * "firstNC" + * Address of first CertNameConstraints to be merged. Must be non-NULL. + * "secondNC" + * Address of second CertNameConstraints to be merged + * "pResultNC" + * 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 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_PL_Cert_MergeNameConstraints( + PKIX_PL_CertNameConstraints *firstNC, + PKIX_PL_CertNameConstraints *secondNC, + PKIX_PL_CertNameConstraints **pResultNC, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage + * DESCRIPTION: + * + * Verifies that the keyUsage bit(s) specified by "keyUsage" appear in the + * keyUsage extension of the Cert pointed to by "cert". The keyUsage bit + * values specified in pkixt.h are supported, and can be bitwise or'ed if + * multiple bit values are to be verified. If the keyUsages do not all appear + * in the keyUsage extension of "cert", a PKIX_Error pointer is returned. + * + * KeyUsage ::= BIT STRING { + * digitalSignature (0), + * nonRepudiation (1), + * keyEncipherment (2), + * dataEncipherment (3), + * keyAgreement (4), + * keyCertSign (5), + * cRLSign (6), + * encipherOnly (7), + * decipherOnly (8) } + * + * PARAMETERS: + * "cert" + * Address of Cert whose keyUsage bits are to be verified. + * Must be non-NULL. + * "keyUsage" + * Constant representing keyUsage bit(s) that all must appear in keyUsage + * extension of "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 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_PL_Cert_VerifyKeyUsage( + PKIX_PL_Cert *cert, + PKIX_UInt32 keyUsage, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType + * DESCRIPTION: + * + * Verifies cert and key types against certificate usage that is + * a part of plContext(pkix_pl_nsscontext) structure. Throws an error + * if cert or key types does not match. + * + * PARAMETERS: + * "cert" + * Address of Cert whose keyUsage bits are to be verified. + * Must be non-NULL. + * "isLeafCert" + * What type of a cert has been verified. + * "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_PL_Cert_VerifyCertAndKeyType( + PKIX_PL_Cert *cert, + PKIX_Boolean isChainCert, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_CheckValidity + * DESCRIPTION: + * + * Checks whether the Cert pointed to by "cert" would be valid at the time + * represented by the Date pointed to by "date". If "date" is NULL, then this + * function checks whether the Cert would be valid at the current time. If the + * Cert would not be valid at the specified Date, a PKIX_Error pointer is + * returned. + * + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + * + * PARAMETERS: + * "cert" + * Address of Cert whose validity is to be checked. Must be non-NULL. + * "date" + * Address of Date at which the Cert is being checked for validity. + * If NULL, the current time is used for the Date. + * "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_PL_Cert_CheckValidity( + PKIX_PL_Cert *cert, + PKIX_PL_Date *date, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter + * DESCRIPTION: + * + * Retrieves a pointer to the Date that represents the notAfter time of the + * Certificate pointed to by "cert" and stores it at "pDate". + * + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + * PARAMETERS: + * "cert" + * Address of Cert whose validity time is to be retrieved. Must be + * non-NULL. + * "date" + * Address of Date at which the Cert's notAfter time is being retrieved. + * 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_PL_Cert_GetValidityNotAfter( + PKIX_PL_Cert *cert, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_VerifySignature + * DESCRIPTION: + * + * Verifies the signature on the Cert pointed to by "cert" using the + * PublicKey pointed to by "pubKey". If the signature doesn't verify, an + * Error pointer is returned. + * + * PARAMETERS: + * "cert" + * Address of Cert whose signature is to be verified. Must be non-NULL. + * "pubKey" + * Address of a Public Key used to verify the signature. 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_PL_Cert_VerifySignature( + PKIX_PL_Cert *cert, + PKIX_PL_PublicKey *pubKey, + void *plContext); + +/* A set of flags to indicate how explicitly configured trust anchors should be + * handled by PKIX_PL_Cert_IsCertTrusted + */ +typedef enum PKIX_PL_TrustAnchorModeEnum { + /* Indicates trust anchors should be ignored; only the underlying + * platform's trust settings should be used. + */ + PKIX_PL_TrustAnchorMode_Ignore, + + /* Indicates that explicitly configured trust anchors may be considered + * trustworthy, if present. + * Note: If the underlying platform supports marking a certificate as + * explicitly untrustworthy, explicitly configured trust anchors + * MAY be ignored/rejected. + */ + PKIX_PL_TrustAnchorMode_Additive, + + /* Indicates that ONLY trust anchors should be considered as + * trustworthy. + * Note: If the underlying platform supports marking a certificate as + * explicitly untrustworthy, explicitly configured trust anchors + * MAY be ignored/rejected. + */ + PKIX_PL_TrustAnchorMode_Exclusive +} PKIX_PL_TrustAnchorMode; + +/* + * FUNCTION: PKIX_PL_Cert_IsCertTrusted + * DESCRIPTION: + * + * Checks the Cert specified by "cert" to determine, in a manner that depends + * on the underlying platform, whether it is trusted, and stores the result in + * "pTrusted". If a certificate is trusted it means that a chain built to that + * certificate, and satisfying all the usage, policy, validity, and other + * tests, is a valid chain and the End Entity certificate from which it was + * built can be trusted. + * + * If the Certificate is not intrinsically trustworthy, it still might end up a + * component in a successful chain. + * + * If the Certificate is intrinsically untrustworthy, this function will return + * an error. + * + * PARAMETERS + * "cert" + * Address of Cert whose trustworthiness is to be determined. Must be + * non-NULL. + * "trustAnchorMode" + * A PKIX_PL_TrustAnchorMode that indicates how explicitly defined user + * trust anchors should be handled. + * "pTrusted" + * Address where the Boolean value 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_PL_Cert_IsCertTrusted( + PKIX_PL_Cert *cert, + PKIX_PL_TrustAnchorMode trustAnchorMode, + PKIX_Boolean *pTrusted, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted + * DESCRIPTION: + * + * Checks the Leaf Cert specified by "cert" to determine, in a manner that + * depends on the underlying platform, whether it is trusted, and stores the + * result in "pTrusted". If a certificate is trusted it means that this + * End Entify certificate has been marked as trusted for the requested usage, + * policy, validity, and other tests. + * + * If the Certificate is not intrinsically trustworthy, we can still try to + * build a successful chain. + * + * If the Certificate is intrinsically untrustworthy, this function will return + * an error. + * + * PARAMETERS + * "cert" + * Address of Cert whose trustworthiness is to be determined. Must be + * non-NULL. + * "pTrusted" + * Address where the Boolean value 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_PL_Cert_IsLeafCertTrusted( + PKIX_PL_Cert *cert, + PKIX_Boolean *pTrusted, + void *plContext); + +/* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ +PKIX_Error* +PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetCacheFlag + * DESCRIPTION: + * + * Retrieves the value of the cache flag in "cert" and return it at address + * pointed by "pCacheFlag". The initila cache flag is determined by the + * CertStore this "cert" is fetched from. When CertStore is created, user + * need to specify if the data should be cached. + * + * PARAMETERS: + * "cert" + * Address of Cert whose cache flag is fetched. Must be non-NULL. + * "pCacheFlag" + * Address where PKIX_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_PL_Cert_GetCacheFlag( + PKIX_PL_Cert *cert, + PKIX_Boolean *pCacheFlag, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_SetCacheFlag + * DESCRIPTION: + * + * Set the value of the cache flag in "cert" base on the boolean value stored + * at "cacheFlag". This function is meant to be used by CertStore after a + * Cert is created. + * + * PARAMETERS: + * "cert" + * Address of Cert where "cacheFlag" is stored. Must be non-NULL. + * "cacheFlag" + * PKIX_Boolean flag for cache flag. + * "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_PL_Cert_SetCacheFlag( + PKIX_PL_Cert *cert, + PKIX_Boolean cacheFlag, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_GetTrustCertStore + * DESCRIPTION: + * + * Retrieves the value of the CertStore in "cert" and return it at address + * pointed by "pCertStore". + * + * PARAMETERS: + * "cert" + * Address of Cert whose CertStore is fetched. Must be non-NULL. + * "pTrustCertStore" + * Address where CertStore will be stored 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 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_PL_Cert_GetTrustCertStore( + PKIX_PL_Cert *cert, + PKIX_CertStore **pTrustCertStore, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Cert_SetTrustCertStore + * DESCRIPTION: + * + * Set the value of the CertStore "certStore" in "cert". + * + * PARAMETERS: + * "cert" + * Address of Cert where "certStore" will be stored. Must be non-NULL. + * "trustCertStore" + * Address where the CertStore is. 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_PL_Cert_SetTrustCertStore( + PKIX_PL_Cert *cert, + PKIX_CertStore *trustCertStore, + void *plContext); + + +/* + * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess + * DESCRIPTION: + * + * Retrieves the value(s) of the Authority Information Access in "cert" and + * returns it in a list at address pointed by "pAuthorityInfoAccess". + * + * SubjectInfoAccess ::= + * SEQUENCE SIZE (1..MAX) of AccessDescription + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName + * } + * + * PARAMETERS: + * "cert" + * Address of Cert whose Authority Information Access is fetched. + * Must be non-NULL. + * "pAuthorityInfoAccess" + * Address where Authority InfoAccess will be stored 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 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_PL_Cert_GetAuthorityInfoAccess( + PKIX_PL_Cert *cert, + PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ + void *plContext); + + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess + * DESCRIPTION: + * + * Retrieves the value(s) of the Subject Information Access in "cert" and + * returns it in a list at address pointed by "pSubjectInfoAccess". + * + * SubjectInfoAccess ::= + * SEQUENCE SIZE (1..MAX) of AccessDescription + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName + * } + * + * PARAMETERS: + * "cert" + * Address of Cert whose Subject Information Access is fetched. + * Must be non-NULL. + * "pSubjectInfoAccess" + * Address where Subject InfoAccess will be stored 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 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_PL_Cert_GetSubjectInfoAccess( + PKIX_PL_Cert *cert, + PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ + void *plContext); + + + +/* + * FUNCTION: PKIX_PL_Cert_GetCrlDp + * DESCRIPTION: + * + * Retrieves the value(s) of the CRL Distribution Point Extension and + * returns it in a list at address pointed by "pDpList". + * + * PARAMETERS: + * "cert" + * Address of Cert whose Subject Information Access is fetched. + * Must be non-NULL. + * "pDpList" + * Address where CRL DP will be stored 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 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_PL_Cert_GetCrlDp(PKIX_PL_Cert *cert, + PKIX_List **pDpList, + void *plContext); + + +/* + * InfoAccess + * + * To hold Authority Information Access or Subject Information Access + * retrieved from a Certificate. + */ + +#define PKIX_INFOACCESS_OCSP 1 +#define PKIX_INFOACCESS_CA_ISSUERS 2 +#define PKIX_INFOACCESS_TIMESTAMPING 3 +#define PKIX_INFOACCESS_CA_REPOSITORY 5 + +#define PKIX_INFOACCESS_LOCATION_UNKNOWN 0 +#define PKIX_INFOACCESS_LOCATION_HTTP 1 +#ifndef NSS_PKIX_NO_LDAP +#define PKIX_INFOACCESS_LOCATION_LDAP 2 +#endif + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetMethod + * DESCRIPTION: + * + * Stores the method of the Information Access from "infoAccess" and + * returns in "pMethod". + * + * SubjectInfoAccess ::= + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName + * } + * + * PARAMETERS: + * "infoAccess" + * Address of PKIX_PL_InfoAccess that has the access data. + * Must be non-NULL. + * "pMethod" + * Address where access method will be stored 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 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_PL_InfoAccess_GetMethod( + PKIX_PL_InfoAccess *infoAccess, + PKIX_UInt32 *pMethod, + void *plContext); + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetLocation + * DESCRIPTION: + * + * Stores the location of the Information Access from "infoAccess" and + * returns in "pLocation". + * + * SubjectInfoAccess ::= + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName + * } + * + * PARAMETERS: + * "infoAccess" + * Address of PKIX_PL_InfoAccess that has the access data. + * Must be non-NULL. + * "pLocation" + * Address where access location will be stored 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 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_PL_InfoAccess_GetLocation( + PKIX_PL_InfoAccess *infoAccess, + PKIX_PL_GeneralName **pLocation, + void *plContext); + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetLocationType + * DESCRIPTION: + * + * Stores the type of location of the Information Access from "infoAccess" and + * returns in "pType". + * + * SubjectInfoAccess ::= + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName + * } + * + * PARAMETERS: + * "infoAccess" + * Address of PKIX_PL_InfoAccess that has the access data. + * Must be non-NULL. + * "pType" + * Address where access location type will be stored 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 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_PL_InfoAccess_GetLocationType( + PKIX_PL_InfoAccess *infoAccess, + PKIX_UInt32 *pType, + void *plContext); + +PKIX_Error * +pkix_pl_InfoAccess_GetAIACerts( + PKIX_PL_InfoAccess *ia, + void **pNBIOContext, + void **pHandle, + PKIX_List **pCerts, + void *plContext); + +/* + * CRL + * + * A CRL represents an X.509 certificate revocation list. It can be created + * using the bytes of a valid ASN.1 DER encoding. Once created, a CRL is + * immutable. The following functions include accessors (gettors) for the + * various components of an X.509 CRL, as well as a function for signature + * verification. + */ + +/* + * FUNCTION: PKIX_PL_CRL_Create + * DESCRIPTION: + * + * Creates a new CRL using the bytes in the ByteArray pointed to by + * "byteArray" and stores it at "pCRL". If the bytes are not a valid ASN.1 + * DER encoding of a CRL, a PKIX_Error pointer is returned. Once created, a + * CRL is immutable. + * + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + * + * TBSCertList ::= SEQUENCE { + * version Version OPTIONAL, + * -- if present, MUST be v2 + * signature AlgorithmIdentifier, + * issuer Name, + * thisUpdate Time, + * nextUpdate Time OPTIONAL, + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL, + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + * } + * + * PARAMETERS: + * "byteArray" + * Address of ByteArray representing the CRL's DER encoding. + * Must be non-NULL. + * "pCRL" + * 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 CRL 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_PL_CRL_Create( + PKIX_PL_ByteArray *byteArray, + PKIX_PL_CRL **pCRL, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_GetIssuer + * DESCRIPTION: + * + * Retrieves a pointer to the X500Name that represents the issuer of the CRL + * pointed to by "crl" and stores it at "pCRLIssuer". + * + * PARAMETERS: + * "crl" + * Address of CRL whose issuer is to be stored. Must be non-NULL. + * "pCRLIssuer" + * 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 CRL 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_PL_CRL_GetIssuer( + PKIX_PL_CRL *crl, + PKIX_PL_X500Name **pCRLIssuer, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (each OID corresponding to a + * critical extension of the CRL pointed to by "crl") and stores it at + * "pExtensions". If "crl" does not have any critical extensions, this + * function stores an empty List at "pExtensions". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "crl" + * Address of CRL whose critical extension OIDs are to be stored. + * Must be non-NULL. + * "pExtensions" + * 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 CRL 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_PL_CRL_GetCriticalExtensionOIDs( + PKIX_PL_CRL *crl, + PKIX_List **pExtensions, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_GetCRLEntryForSerialNumber + * DESCRIPTION: + * + * Retrieves a pointer to the CRLEntry (found in the CRL pointed to by "crl") + * corresponding to the BigInt pointed to by "serialNumber" and stores it at + * "pCRLEntry". If there is no such CRLEntry, this functions stores NULL at + * "pCRLEntry". Once created, a CRLEntry is immutable. + * + * PARAMETERS: + * "crl" + * Address of CRL whose CRL Entries are to be searched. Must be non-NULL. + * "serialNumber" + * Address of BigInt representing serial number of certificate whose + * CRLEntry is to be found. Must be non-NULL. + * "pCRLEntry" + * 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 CRL 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_PL_CRL_GetCRLEntryForSerialNumber( + PKIX_PL_CRL *crl, + PKIX_PL_BigInt *serialNumber, + PKIX_PL_CRLEntry **pCRLEntry, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_GetCRLNumber + * DESCRIPTION: + * Retrieves the CRL Number from extension. This is non-critical extension. + * + * PARAMETERS: + * "crl" + * Address of CRL whose version is to be stored. Must be non-NULL. + * "pCrlNumber" + * Address where a CRL Number 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 CRL 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_PL_CRL_GetCRLNumber( + PKIX_PL_CRL *crl, + PKIX_PL_BigInt **pCrlNumber, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime + * DESCRIPTION: + * + * Checks whether the CRL pointed to by "crl" would be valid at the time + * represented by the Date pointed to by "date" and stores the Boolean result + * at "pResult". This check is done only when NIST policy is enforced. + * + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + * + * PARAMETERS: + * "crl" + * Address of CRL whose validity is to be checked. Must be non-NULL. + * "date" + * Address of Date at which the CRL is being checked for validity. + * Must be non-NULL. + * "pResult" + * Address of Boolean result. 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 CRL 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_PL_CRL_VerifyUpdateTime( + PKIX_PL_CRL *crl, + PKIX_PL_Date *date, + PKIX_Boolean *pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_VerifySignature + * DESCRIPTION: + * + * Verifies the signature on the CRL pointed to by "crl" using the PublicKey + * pointed to by "pubKey". If the signature doesn't verify, a PKIX_Error + * pointer is returned. + * + * PARAMETERS: + * "crl" + * Address of CRL whose signature is to be verified. Must be non-NULL. + * "pubKey" + * Address of a Public Key used to verify the signature. 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 CRL 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_PL_CRL_VerifySignature( + PKIX_PL_CRL *crl, + PKIX_PL_PublicKey *pubKey, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRL_ReleaseDerCrl + * DESCRIPTION: + * + * Relinguish the ownership for the crl der. The operation will succeed if + * a crl owns the der. If the crl was created from existing crl and does not + * own the der, then the function will return null. + * + * PARAMETERS: + * "crl" + * Address of CRL whose signature is to be verified. Must be non-NULL. + * "derCrl" + * Pointer to a SECItem that has der crl. + * "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 CRL 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_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl, + SECItem **derCrl, + void *plContext); +/* + * FUNCTION: PKIX_PL_CRL_AdoptDerCrl + * DESCRIPTION: + * + * Adopt memory of the der. The secItem that contains der will be + * freed with destruction of parent pkix crl structure. + * + * * PARAMETERS: + * "crl" + * Address of CRL whose signature is to be verified. Must be non-NULL. + * "derCrl" + * Pointer to a SECItem that has der crl. + * "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 CRL 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_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl, + SECItem *derCrl, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode + * DESCRIPTION: + * + * Retrieves the value of the reason code extension of the CRLEntry pointed + * to by "crlEntry" and stores it at "pReason". If the "crlEntry" has no + * reason code extension, this function stores -1 at "pReason". + * + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8), + * privilegeWithdrawn (9), + * aACompromise (10) } + * + * PARAMETERS: + * "crlEntry" + * Address of CRLEntry whose reason code bit values are to be returned + * at "pReason". Must be non-NULL. + * "pReason" + * Address of PKIX_Int32 where reason code 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 CRL 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_PL_CRLEntry_GetCRLEntryReasonCode( + PKIX_PL_CRLEntry *crlEntry, + PKIX_Int32 *pReason, + void *plContext); + +/* + * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs + * DESCRIPTION: + * + * Retrieves a pointer to the List of OIDs (each OID corresponding to a + * critical extension of the CRLEntry pointed to by "crlEntry") and stores it + * at "pExtensions". If "crlEntry" does not have any critical extensions, this + * function stores an empty List at "pExtensions". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "crlEntry" + * Address of CRLEntry whose critical extension OIDs are to be stored. + * Must be non-NULL. + * "pExtensions" + * 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 CRL 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_PL_CRLEntry_GetCriticalExtensionOIDs( + PKIX_PL_CRLEntry *crlEntry, + PKIX_List **pExtensions, /* list of PKIX_PL_OID */ + void *plContext); + +#ifdef BUILD_LIBPKIX_TESTS +/* + * FUNCTION: PKIX_PL_X500Name_Create + * DESCRIPTION: + * + * Creates a new X500Name using the UTF8 string representation pointed to by + * "stringRep" and stores it at "pName". Once created, an X500Name is + * immutable. + * + * Name ::= CHOICE { + * RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * DirectoryString ::= CHOICE { + * teletexString TeletexString (SIZE (1..MAX)), + * printableString PrintableString (SIZE (1..MAX)), + * universalString UniversalString (SIZE (1..MAX)), + * utf8String UTF8String (SIZE (1..MAX)), + * bmpString BMPString (SIZE (1..MAX)) } + * + * PARAMETERS: + * "stringRep" + * Address of UTF8 String representation of X500Name. Must be non-NULL. + * "pName" + * 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 X500Name 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_PL_X500Name_Create ( + PKIX_PL_String *stringRep, + PKIX_PL_X500Name **pName, + void *plContext); + +#endif /* BUILD_LIBPKIX_TESTS */ + +/* + * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName + * DESCRIPTION: + * + * The function creates x500Name using der encoded DN and/or pointer to + * CERTName. If arument "name" is NULL, but derName is supplied when + * the function generates nssDN(CERTName type) from der data. If derName + * is not supplied, CERTName *name will not be used to generate DN DER + * encoding. + * + * PARAMETERS: + * "derName" + * Address of DER representation of X500Name. Can be NULL + * "name" + * Address of CERTName representation of X500Name. Can be NULL + * "pName" + * 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 X500Name 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_PL_X500Name_CreateFromCERTName( + SECItem *derName, + CERTName *name, + PKIX_PL_X500Name **pName, + void *plContext); + + +/* + * TYPE: PKIX_PL_X500Name_Match + * DESCRIPTION: + * Checks whether the X500Name pointed to by "firstX500Name" MATCHES the + * X500Name pointed to by "secondX500Name" and stores the boolean result at + * "pResult". Two X500Names MATCH if they meet the conditions specified by + * RFC 3280 (section 4.1.2.4). Namely: + * + * "This specification requires only a subset of the name comparison + * functionality specified in the X.500 series of specifications. + * Conforming implementations are REQUIRED to implement the following + * name comparison rules: + * + * (a) attribute values encoded in different types (e.g., PrintableString + * and BMPString) MAY be assumed to represent different strings; + * + * (b) attribute values in types other than PrintableString are case + * sensitive (this permits matching of attribute values as binary objects) + * + * (c) attribute values in PrintableString are not case sensitive + * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and + * + * (d) attribute values in PrintableString are compared after removing + * leading and trailing white space and converting internal substrings of + * one or more consecutive white space characters to a single space." + * + * PARAMETERS: + * "firstX500Name" + * Address of first X500Name to compare. Must be non-NULL. + * "secondX500Name" + * Address of second X500Name to compare. Must be non-NULL. + * "pResult" + * Address of Boolean result. 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 X500Name 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_PL_X500Name_Match( + PKIX_PL_X500Name *firstX500Name, + PKIX_PL_X500Name *secondX500Name, + PKIX_Boolean *pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Date_Create_UTCTime + * DESCRIPTION: + * Creates a new Date of type UTCTime using the string representation pointed + * to by "stringRep" and stores it at "pDate". The UTCTime restriction means + * that the year can only be specified by the least significant two digits + * (YY). As such, Only the years 1950-2049 can be represented. If "stringRep" + * is NULL, this function creates a new Date representing the current time + * and stores it at "pDate". Once created, a Date is immutable. + * + * If YY is greater than or equal to 50, the year is interpreted as 19YY. + * If YY is less than 50, the year is interpreted as 20YY. + * + * The string representation of the date must be in the following form: + * "YYMMDDhhmmssZ" where: + * + * YY is the least significant two digits of the year + * MM is the month (01 to 12) + * DD is the day (01 to 31) + * hh is the hour (00 to 23) + * mm are the minutes (00 to 59) + * ss are the seconds (00 to 59) + * Z indicates that local time is GMT + * + * PARAMETERS: + * "stringRep" + * Address of String representation of Date. + * If NULL, current time is used. + * "pDate" + * 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 Date 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_PL_Date_Create_UTCTime ( + PKIX_PL_String *stringRep, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Date_Create_UTCTime + * DESCRIPTION: + * Creates a new Date from PRTime data. + * + * PARAMETERS: + * "time" + * Represented time in PRTime type. + * "pDate" + * 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 Date 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_PL_Date_CreateFromPRTime( + PRTime time, + PKIX_PL_Date **pDate, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds + * DESCRIPTION: + * Creates a new Date of type UTCTime for current time with seconds off by + * "secondsOffset" and returns it at "pDate". + * + * PARAMETERS: + * "secondsOffset" + * A PKIX_Int32 indicates the time offset from current. If "secondsOffset" + * is negative, the time is in past. + * "pDate" + * 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 Date 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_PL_Date_Create_CurrentOffBySeconds( + PKIX_Int32 secondsOffset, + PKIX_PL_Date **pDate, + void *plContext); + +#ifdef BUILD_LIBPKIX_TESTS +/* + * FUNCTION: PKIX_PL_GeneralName_Create + * DESCRIPTION: + * + * Creates a new GeneralName of type "nameType" using the string + * representation pointed to by "stringRep" and stores it at "pGName". + * All of the GeneralName type format values specified in pkixt.h are + * supported, with the exception of PKIX_OTHER_NAME, PKIX_EDIPARTY_NAME, + * PKIX_IP_NAME, and PKIX_X400_ADDRESS. A PKIX_ESCASCII string representation + * should be used for all supported nameTypes, with the exception of + * registeredID and directoryName. For registeredID, the string representation + * should be the same as that used by PKIX_PL_OID_Create. For directoryName, + * the string representation should be the same as that used by + * PKIX_PL_X500Name_Create. If an unsupported name type is used, an Error is + * returned. Once created, a GeneralName is immutable. + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * + * NOTE: This function is allowed to be called only by pkix tests programs. + * + * PARAMETERS: + * "nameType" + * Type of GeneralName to be created. This must be one of the GeneralName + * type format values specified in pkixt.h + * "stringRep" + * Address of String representation of GeneralName. Must be non-NULL. + * "pGName" + * 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 GeneralName 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_PL_GeneralName_Create ( + PKIX_UInt32 nameType, + PKIX_PL_String *stringRep, + PKIX_PL_GeneralName **pGName, + void *plContext); +#endif /* BUILD_LIBPKIX_TESTS */ + +/* + * FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace + * DESCRIPTION: + * + * This function checks whether names in "nameList" comply with + * "nameConstraints". It stores PKIX_TRUE at "pCheckPass" if the names meet the + * requirement of the NameConstraints, PKIX_FALSE otherwise. + * + * PARAMETERS + * "nameList" + * List of GeneralNames that are checked for compliance. May be empty + * or NULL. + * "nameConstraints" + * Address of CertNameConstraints that provides lists of permitted + * and excluded names. Must be non-NULL. + * "pCheckPass" + * Address where PKIX_TRUE is returned if the all names in "nameList" are + * valid. 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 NameConstraints 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_PL_CertNameConstraints_CheckNamesInNameSpace( + PKIX_List *nameList, /* List of PKIX_PL_GeneralName */ + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean *pCheckPass, + void *plContext); + +/* + * FUNCTION: PKIX_PL_AIAMgr_Create + * DESCRIPTION: + * + * This function creates an AIAMgr to handle retrieval of Certs and CRLs + * from servers given by AIA Certificate extensions. It manages connections + * and caches. The manager created is stored at "pAIAMgr". + * + * PARAMETERS: + * "pAIAMgr" + * The address at which the result is stored. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an AIAMgr 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_PL_AIAMgr_Create( + PKIX_PL_AIAMgr **pAIAMgr, + void *plContext); + +/* + * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts + * DESCRIPTION: + * + * This function uses the AIAMgr pointed to by "aiaMgr" to retrieve the Certs + * specified by an AIA certificate extension, if any, in the Cert pointed to by + * "prevCert", storing the results at "pCerts". If the certificate has no such + * extension, this function stores NULL at "pCerts". + * + * If the request is suspended for non-blocking I/O, a platform-dependent + * context is stored at "pNBIOContext" and NULL is stored at "pCerts". This + * return is referred to as the WOULDBLOCK state. Note that the caller must + * check for a non-NULL value at "pNBIOContext", to distinguish this state from + * the "no such extension" return described in the first paragraph. (The + * alternative would be to return an empty List, but it seemed wrong to incur + * the overhead of creating and destroying an empty List for the most common + * situation.) + * + * After a WOULDBLOCK return, the user may continue the operation by calling + * pkix_AIAMgr_GetAIACerts (possibly more than once, if the function again + * returns in the WOULDBLOCK state) with the previously-returned non-NULL + * value of "pNBIOContext". When results are complete, NULL is stored at + * "pNBIOContext", and the results (which may be NULL) are stored at "pCerts". + * + * PARAMETERS: + * "aiaMgr" + * The AIAMgr which controls the retrieval of certificates. Must be + * non-NULL. + * "prevCert" + * Address of PKIX_PL_Cert which may provide an AIA or SIA extension. Must + * be non-NULL. + * "pNBIOContext" + * Address at which platform-dependent information is returned if request + * is suspended for non-blocking I/O. Must be non-NULL. + * "pCerts" + * Address at which the returned 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 an AIAMgr 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_PL_AIAMgr_GetAIACerts( + PKIX_PL_AIAMgr *aiaMgr, + PKIX_PL_Cert *prevCert, + void **pNBIOContext, + PKIX_List **pCerts, + void *plContext); + +typedef PKIX_Error * +(*PKIX_PL_VerifyCallback)( + PKIX_PL_Object *signedObject, + PKIX_PL_Cert *signerCert, /* can be unknown */ + PKIX_PL_Date *producedAt, + PKIX_ProcessingParams *procParams, + void **pNBIOContext, + void **pState, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_PKI_H */ diff --git a/security/nss/lib/libpkix/include/pkix_pl_system.h b/security/nss/lib/libpkix/include/pkix_pl_system.h new file mode 100644 index 0000000000..57d5df7cc0 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_pl_system.h @@ -0,0 +1,1545 @@ +/* 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/. */ +/* + * This file defines several platform independent functions to make system + * calls in a portable manner. + * + */ + +#ifndef _PKIX_PL_SYSTEM_H +#define _PKIX_PL_SYSTEM_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* + * FUNCTION: PKIX_PL_Initialize + * DESCRIPTION: + * + * XXX If this function is really only meant to be used by PKIX_Initialize, + * why don't we just put it in a private header file rather than the public + * API. I think it may confuse users. + * + * This function should NOT be called by applications. It is only meant to + * be used internally. The application needs only to call PKIX_Initialize, + * which in turn will call this function. + * + * This function initializes data structures critical to the operation of + * libpkix. If initialization is not successful, an Error pointer is + * returned. This function should only be called once. If it is called more + * than once, the behavior is undefined. + * + * No PKIX_* types and functions should be used before this function is + * called and returns successfully. + * + * PARAMETERS: + * "platformInitNeeded" + * Boolean indicating whether platform initialization is to be called + * "useArenas" + * Boolean indicating whether allocation is to be done using arenas or + * individual allocation (malloc). + * "pPlContext" + * Address at which platform-specific context pointer is stored. Must be + * non-NULL. + * THREAD SAFETY: + * Not Thread Safe + * + * This function assumes that no other thread is calling this function while + * it is executing. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Initialize( + PKIX_Boolean platformInitNeeded, + PKIX_Boolean useArenas, + void **pPlContext); + +/* + * FUNCTION: PKIX_PL_Shutdown + * DESCRIPTION: + * + * XXX If this function is really only meant to be used by PKIX_Shutdown, + * why don't we just put it in a private header file rather than the public + * API. I think it may confuse users. + * + * This function should NOT be called by applications. It is only meant to + * be used internally. The application needs only to call PKIX_Shutdown, + * which in turn will call this function. + * + * This function deallocates any memory used by the Portability Layer (PL) + * component of the libpkix library and shuts down any ongoing operations. + * This function should only be called once. If it is called more than once, + * the behavior is undefined. + * + * No PKIX_* types and functions should be used after this function is called + * and returns successfully. + * + * PARAMETERS: + * "platformInitNeeded" + * Boolean value of whether PKIX initialized NSS: PKIX_TRUE if we + * called nssInit, PKIX_FALSE otherwise + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe + * + * This function makes use of global variables and should only be called once. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Shutdown(void *plContext); + +/* standard memory management operations (not reference-counted) */ + +/* + * FUNCTION: PKIX_PL_Malloc + * DESCRIPTION: + * + * Allocates a block of "size" bytes. The bytes are not initialized. A + * pointer to the newly allocated memory will be stored at "pMemory". The + * memory allocated by PKIX_PL_Malloc() may only be freed by PKIX_PL_Free(). + * If "size" equals zero, this function stores NULL at "pMemory". + * + * PARAMETERS: + * "size" + * Number of bytes to allocate. + * "pMemory" + * Address where newly allocated pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on underlying thread safety of platform used by PL. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Malloc( + PKIX_UInt32 size, + void **pMemory, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Calloc + * DESCRIPTION: + * + * Allocates memory for an array of "nElem" elements, with each element + * requiring "elSize" bytes, and with all the bits initialized to zero. A + * pointer to the newly allocated memory will be stored at "pMemory". The + * memory allocated by PKIX_PL_Calloc() may only be freed by PKIX_PL_Free(). + * If "nElem" equals zero or "elSize" equals zero, this function stores NULL + * at "pMemory". + * + * PARAMETERS: + * "nElem" + * Number of elements needed. + * "elSize" + * Number of bytes needed per element. + * "pMemory" + * Address where newly allocated pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on underlying thread safety of platform used by PL. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Calloc( + PKIX_UInt32 nElem, + PKIX_UInt32 elSize, + void **pMemory, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Realloc + * DESCRIPTION: + * + * Resizes an existing block of memory (pointed to by "ptr") to "size" bytes. + * Stores a pointer to the resized memory at "pNewPtr". The "ptr" must + * originate from either PKIX_PL_Malloc(), PKIX_PL_Realloc(), or + * PKIX_PL_Calloc(). If "ptr" is NULL, this function behaves as if + * PKIX_PL_Malloc were called. If "ptr" is not NULL and "size" equals zero, + * the memory pointed to by "ptr" is deallocated and this function stores + * NULL at "pPtr". + * + * PARAMETERS: + * "ptr" + * A pointer to an existing block of memory. + * "size" + * New size in bytes. + * "pPtr" + * Address where newly allocated pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on underlying thread safety of platform used by PL. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Realloc( + void *ptr, + PKIX_UInt32 size, + void **pNewPtr, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Free + * DESCRIPTION: + * + * Frees a block of memory pointed to by "ptr". This value must originate with + * either PKIX_PL_Malloc(), PKIX_PL_Calloc, or PKIX_PL_Realloc(). If "ptr" is + * NULL, the function has no effect. + * + * PARAMETERS: + * "ptr" + * A pointer to an existing block of memory. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on underlying thread safety of platform used by PL. + * RETURNS: + * Returns NULL always. + */ +PKIX_Error * +PKIX_PL_Free( + void *ptr, + void *plContext); + +/* Callback Types + * + * The next few typedefs define function pointer types for the standard + * functions associated with every object type. See the Implementation + * Guidelines or the comments below for more information. + */ + +/* + * TYPE: PKIX_PL_DestructorCallback + * DESCRIPTION: + * + * This callback function destroys (or DecRef's) any pointers contained in + * the user data for the Object pointed to by "object" before the Object is + * destroyed. + * + * PARAMETERS: + * "object" + * Address of Object to destroy. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts (as long as they're not operating on the same + * object and nobody else is performing an operation on the object at the + * same time). Both of these conditions should be guaranteed by the fact that + * the object's ref count was reduced to 0 in a lock that's still held when + * this callback is called. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_DestructorCallback)( + PKIX_PL_Object *object, + void *plContext); + +/* + * TYPE: PKIX_PL_EqualsCallback + * DESCRIPTION: + * + * This callback function compares the Object pointed to by "firstObject" with + * the Object pointed to by "secondObject" for equality and stores the result + * at "pResult" (PKIX_TRUE if equal; PKIX_FALSE if not). + * + * PARAMETERS: + * "firstObject" + * Address of first object to compare. Must be non-NULL. + * "secondObject" + * Address of second object to compare. Must be non-NULL. + * "pResult" + * Address where Boolean will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_EqualsCallback)( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext); + +/* + * TYPE: PKIX_PL_HashcodeCallback + * DESCRIPTION: + * + * This callback function computes the hashcode of the Object pointed to by + * "object" and stores the result at "pValue". + * + * PARAMETERS: + * "object" + * Address of Object whose hashcode is desired. Must be non-NULL. + * "pValue" + * Address where PKIX_UInt32 will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_HashcodeCallback)( + PKIX_PL_Object *object, + PKIX_UInt32 *pValue, + void *plContext); + +/* + * TYPE: PKIX_PL_ToStringCallback + * DESCRIPTION: + * + * This callback function converts the Object pointed to by "object" to a + * string representation and stores the result at "pString". + * + * PARAMETERS: + * "object" + * Object to get a string representation from. Must be non-NULL. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_ToStringCallback)( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext); + +/* + * TYPE: PKIX_PL_ComparatorCallback + * DESCRIPTION: + * + * This callback function determines how the Object pointed to by + * "firstObject" compares to the Object pointed to by "secondObject" and + * stores the result at "pResult". + * + * Result is less than 0 if firstObject < secondObject + * Result equals 0 if firstObject = secondObject + * Result is greater than 0 if firstObject > secondObject + * + * PARAMETERS: + * "firstObject" + * Address of the first Object to compare. Must be non-NULL. + * "secondObject" + * Address of the second Object to compare. Must be non-NULL. + * "pResult" + * Address where PKIX_Int32 will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_ComparatorCallback)( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext); + +/* + * TYPE: PKIX_PL_DuplicateCallback + * DESCRIPTION: + * + * This callback function creates a copy of the Object pointed to by "object" + * and stores it at "pNewObject". Changes to the copy will not affect the + * original and vice versa. + * + * Note that if "object" is immutable, the Duplicate callback function simply + * needs to increment the reference count on "object" and return a reference + * to "object". + * + * PARAMETERS: + * "object" + * Address of the object to be copied. Must be non-NULL. + * "pNewObject" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_PL_DuplicateCallback)( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext); + +/* reference-counted objects */ + +/* + * FUNCTION: PKIX_PL_Object_Alloc + * DESCRIPTION: + * + * Allocates a new Object of type "type" with "size" bytes and stores the + * resulting pointer at "pObject". The reference count of the newly + * allocated object will be initialized to 1. To improve performance, each + * object maintains a small cache for the results of Hashcode and ToString. + * Mutable objects should call InvalidateCache whenever changes are made to + * the object's state (after creation). If an error occurs during allocation, + * "pObject" will be set to NULL. If "size" equals zero, this function creates + * an Object with a reference count of 1, and places a pointer to unallocated + * memory at "pMemory". + * + * PARAMETERS: + * "type" + * The type code of this object. See pkixt.h for codes. The type code + * must be previously registered with PKIX_PL_Object_RegisterType(). + * "size" + * The number of bytes needed for this object. + * "pMemory" + * 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_PL_Object_Alloc( + PKIX_TYPENUM type, + PKIX_UInt32 size, + PKIX_PL_Object **pObject, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_IsTypeRegistered + * DESCRIPTION: + * + * Checks whether "type" has been registered by a previous call to + * PKIX_PL_Object_RegisterType() and stores the Boolean result at "pBool". + * This function will typically only be called by constructors for specific + * types. + * + * PARAMETERS: + * "type" + * The type code to check if valid. + * "pBool" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Object_IsTypeRegistered( + PKIX_UInt32 type, + PKIX_Boolean *pBool, + void *plContext); + +#ifdef PKIX_USER_OBJECT_TYPE +/* + * FUNCTION: PKIX_PL_Object_RegisterType + * DESCRIPTION: + * + * Registers a new Object with type value "type" and associates it with a set + * of functions ("destructor", "equalsFunction", "hashcodeFunction", + * "toStringFunction", "comparator", "duplicateFunction"). The new type value + * is also associated with a string pointed to by "description", which is used + * by the default ToStringCallback. This function may only be called with a + * particular "type" value once. If "destructor", "equalsFunction", + * "hashcodeFunction", or "toStringFunction" are NULL, default functions will + * be registered. However, if "comparator" and "duplicateFunction" are NULL, + * no functions will be registered and calls to PKIX_PL_Object_Compare and + * PKIX_PL_Object_Duplicate will result in an error. + * + * PARAMETERS: + * "type" + * The type code. + * "description" + * The string used by the default ToStringCallback. Default used if NULL. + * "destructor" + * The DestructorCallback function to be set. Default used if NULL. + * "equalsFunction" + * The EqualsCallback function to be set. Default used if NULL. + * "hashcodeFunction" + * The HashcodeCallback function to be set. Default used if NULL. + * "toStringFunction" + * The ToStringCallback function to be set. Default used if NULL. + * "comparator" + * The ComparatorCallback function to be set. None set if NULL. If no + * callback function is set in this field, calls to + * PKIX_PL_Object_Compare() will result in an error. + * "duplicateFunction" + * The DuplicateCallback function to be set. None set if NULL. If no + * callback function is set in this field, calls to + * PKIX_PL_Object_Duplicate() will result in an error. + * "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 Object Error if "type" is already registered. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Object_RegisterType( + PKIX_UInt32 type, + char *description, + PKIX_PL_DestructorCallback destructor, + PKIX_PL_EqualsCallback equalsFunction, + PKIX_PL_HashcodeCallback hashcodeFunction, + PKIX_PL_ToStringCallback toStringFunction, + PKIX_PL_ComparatorCallback comparator, + PKIX_PL_DuplicateCallback duplicateFunction, + void *plContext); + +#endif +/* + * FUNCTION: PKIX_PL_Object_InvalidateCache + * DESCRIPTION: + * + * Invalidates the cache of the Object pointed to by "object". The cache + * contains results of Hashcode and ToString. This function should be used by + * mutable objects whenever changes are made to the Object's state (after + * creation). + * + * For example, if ToString is called on a mutable Object, the result will be + * computed, cached, and returned. If the Object's state does not change, a + * subsequent call to ToString will recognize that the relevant result is + * cached and will simply return the result (without calling the Object's + * ToStringCallback to recompute it). However, when the Object's state + * changes, the cache needs to be invalidated in order to force a subsequent + * call to ToString to recompute the result. + * + * PARAMETERS: + * "object" + * Address of Object whose cache is to be invalidated. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * + * THREAD SAFETY + * Thread Safe - Object Type Table is locked during modification. + * + * Multiple threads can safely call this function without worrying about + * conflicts, even if they're operating on the same object. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Object_InvalidateCache( + PKIX_PL_Object *object, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_IncRef + * DESCRIPTION: + * + * Increments the reference count of the Object pointed to by "object". + * + * PARAMETERS: + * "object" + * Address of Object whose reference count is to be incremented. + * 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_PL_Object_IncRef( + PKIX_PL_Object *object, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_DecRef + * DESCRIPTION: + * + * Decrements the reference count of the Object pointed to by "object". If the + * resulting reference count is zero, the destructor (if any) registered for + * the Object's type (by PKIX_PL_RegisterType) will be called and then the + * Object will be destroyed. + * + * PARAMETERS: + * "object" + * Address of Object whose reference count is to be decremented. + * Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * If destructor is not called, multiple threads can safely call this function + * without worrying about conflicts, even if they're operating on the same + * object. If destructor is called, thread safety depends on the callback + * defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_PL_Object_DecRef( + PKIX_PL_Object *object, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Equals + * DESCRIPTION: + * + * Compares the Object pointed to by "firstObject" with the Object pointed to + * by "secondObject" for equality using the callback function registered for + * "firstObject"'s type, and stores the Boolean result at "pResult". While + * typical callbacks will return PKIX_FALSE if the objects are of different + * types, other callbacks may be capable of comparing objects of different + * types [which may correctly result in cases where Equals(first, second) + * differs from Equals(second, first)]. + * + * PARAMETERS: + * "firstObject" + * Address of the first Object to compare. Must be non-NULL. + * The EqualsCallback for this Object will be called. + * "secondObject" + * Address of the second Object to compare. Must be non-NULL. + * "pResult" + * Address where Boolean will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on the callback defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object 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_PL_Object_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Hashcode + * DESCRIPTION: + * + * Computes a hashcode of the Object pointed to by "object" using the + * callback registered for "object"'s type and stores it at "pValue". Two + * objects which are equal should have the same hashcode. Once a call to + * Hashcode has been made, the results are cached and subsequent calls to + * Hashcode will return the cached value. For mutable objects, an + * InvalidateCache function is provided, which should be called whenever + * changes are made to the object's state (after creation). + * + * PARAMETERS: + * "object" + * Address of the Object whose hashcode is desired. Must be non-NULL. + * The HashcodeCallback for this object will be called. + * "pValue" + * Address where PKIX_Int32 will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * + * THREAD SAFETY: + * Thread safety depends on the callback defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object 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_PL_Object_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pValue, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_ToString + * DESCRIPTION: + * + * Creates a string representation of the Object pointed to by "object" using + * the callback registered for "object"'s type and stores it at "pString". + * Once a call to ToString has been made, the results are cached and + * subsequent calls to ToString will return the cached value. For mutable + * objects, an InvalidateCache function is provided, which should be called + * whenever changes are made to the object's state (after creation). + * + * PARAMETERS: + * "object" + * Address of Object whose string representation is desired. + * Must be non-NULL. The ToStringCallback for this object will be called. + * "pString" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on the callback defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object 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_PL_Object_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Compare + * DESCRIPTION: + * + * Compares the Object pointed to by "firstObject" and the Object pointed to + * by "secondObject" using the comparator registered for "firstObject"'s type + * and stores the result at "pResult". Different types may be compared. This + * may correctly result in cases where Compare(first, second) is not the + * opposite of Compare(second, first). The PKIX_Int32 value stored at + * "pResult" will be: + * Less than 0 if "firstObject" < "secondObject" + * Equals to 0 if "firstObject" = "secondObject" + * Greater than 0 if "firstObject" > "secondObject" + * + * PARAMETERS: + * "firstObject" + * Address of first Object to compare. Must be non-NULL. + * The ComparatorCallback for this object will be called. + * "secondObject" + * Address of second object to compare. Must be non-NULL. + * "pResult + * Address where PKIX_Int32 will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on the comparator defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object 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_PL_Object_Compare( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Duplicate + * DESCRIPTION: + * + * Creates a duplicate copy of the Object pointed to by "object" using the + * callback registered for "object"'s type and stores the copy at + * "pNewObject". Changes to the new object will not affect the original and + * vice versa. + * + * Note that if "object" is immutable, the Duplicate callback function simply + * needs to increment the reference count on "object" and return a reference + * to "object". + * + * PARAMETERS: + * "object" + * Address of Object to be duplicated. Must be non-NULL. + * The DuplicateCallback for this Object will be called. + * "pNewObject" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread safety depends on the callback defined by PKIX_PL_RegisterType(). + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an Object 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_PL_Object_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_GetType + * DESCRIPTION: + * + * Retrieves the type code of the Object pointed to by "object" and stores it + * at "pType". See pkixt.h for type codes. + * + * PARAMETERS: + * "object" + * Address of Object whose type is desired. Must be non-NULL. + * "pType" + * Address where PKIX_UInt32 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_PL_Object_GetType( + PKIX_PL_Object *object, + PKIX_UInt32 *pType, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Lock + * DESCRIPTION: + * + * Locks the Mutex associated with the Object pointed to by "object". When an + * object is created, it is associated with an object-specific Mutex to allow + * for synchronization when the fields of the object are modified. + * + * PARAMETERS: + * "object" + * Address of Object whose Mutex is to be locked. 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_PL_Object_Lock( + PKIX_PL_Object *object, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Object_Unlock + * DESCRIPTION: + * + * Unlocks the Mutex associated with the Object pointed to by "object". When + * an object is created, it is associated with an object-specific Mutex to + * allow for synchronization when the fields of the object are modified. + * + * PARAMETERS: + * "object" + * Address of Object whose Mutex is to be unlocked. 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_PL_Object_Unlock( + PKIX_PL_Object *object, + void *plContext); + +/* mutexes (locks) */ + +/* + * FUNCTION: PKIX_PL_Mutex_Create + * DESCRIPTION: + * + * Creates a new Mutex and stores it at "pNewLock". + * + * PARAMETERS: + * "pNewLock" + * 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_PL_Mutex_Create( + PKIX_PL_Mutex **pNewLock, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Mutex_Lock + * DESCRIPTION: + * + * Locks the Mutex pointed to by "lock". If the Mutex is already locked, this + * function will block the current thread until the mutex can be locked by + * this thread. + * + * PARAMETERS: + * "lock" + * Address of Mutex to lock. 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_PL_Mutex_Lock( + PKIX_PL_Mutex *lock, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Mutex_Unlock + * DESCRIPTION: + * + * Unlocks the Mutex pointed to by "lock" if the current thread holds the + * Mutex. + * + * PARAMETERS: + * "lock" + * Address of Mutex to unlock. 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_PL_Mutex_Unlock( + PKIX_PL_Mutex *lock, + void *plContext); + +/* monitor (locks) */ + +/* + * FUNCTION: PKIX_PL_MonitorLock_Create + * DESCRIPTION: + * + * Creates a new PKIX_PL_MonitorLock and stores it at "pNewLock". + * + * PARAMETERS: + * "pNewLock" + * 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_PL_MonitorLock_Create( + PKIX_PL_MonitorLock **pNewLock, + void *plContext); + +/* + * FUNCTION: PKIX_PL_MonitorLock_Enter + * DESCRIPTION: + * + * Locks the MonitorLock pointed to by "lock". If the MonitorLock is already + * locked by other thread, this function will block the current thread. If + * the "lock" had been locked by current thread, this function will NOT block. + * + * PARAMETERS: + * "lock" + * Address of MonitorLock to lock. 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_PL_MonitorLock_Enter( + PKIX_PL_MonitorLock *lock, + void *plContext); + +/* + * FUNCTION: PKIX_PL_MonitorLock_Exit + * DESCRIPTION: + * + * Unlocks the MonitorLock pointed to by "lock" if the lock counter of + * current thread holds the MonitorLock reach 0, the lock is released. + * + * PARAMETERS: + * "lock" + * Address of MonitorLock to unlock. 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_PL_MonitorLock_Exit( + PKIX_PL_MonitorLock *lock, + void *plContext); + +/* strings and formatted printing */ + +/* + * FUNCTION: PKIX_PL_String_Create + * DESCRIPTION: + * + * Creates a new String using the data pointed to by "pString", the + * PKIX_UInt32 pointed to by "stringLen", and the PKIX_UInt32 pointed to by + * "fmtIndicator" and stores it at "pString". If the format is PKIX_ESCASCII + * the "stringLen" parameter is ignored and the string extends until a zero + * byte is found. Once created, a String object is immutable. + * + * Valid formats are: + * PKIX_ESCASCII + * PKIX_ESCASCII_DEBUG + * PKIX_UTF8 + * PKIX_UTF8_NULL_TERM + * PKIX_UTF16 + * + * PARAMETERS: + * "fmtIndicator" + * Format that "stringRep" is encoded with. Must be non-NULL. + * "stringRep" + * Address of encoded string representation. Must be non-NULL. + * "stringLen" + * Length of data stored at stringRep. + * "pString" + * 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 String 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_PL_String_Create( + PKIX_UInt32 fmtIndicator, + const void *stringRep, + PKIX_UInt32 stringLen, + PKIX_PL_String **pString, + void *plContext); + +/* + * FUNCTION: PKIX_PL_Sprintf + * DESCRIPTION: + * + * Creates a formatted string at "pOut" using the given format "fmt" and a + * variable length list of arguments. The format flags are identical to + * standard C with the exception that %s expects a PKIX_PL_String*, rather + * than a char *, and that {%d, %i, %o, %u, %x, %X} expect PKIX_UInt32 or + * PKIX_Int32 instead of int or unsigned int. + * + * PARAMETERS: + * "pOut" + * Address where object pointer will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * "fmt" + * Address of format string. Must be non-NULL. + * THREAD SAFETY: + * Not Thread Safe - Caller must have exclusive access to all arguments. + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a String 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_PL_Sprintf( + PKIX_PL_String **pOut, + void *plContext, + const PKIX_PL_String *fmt, ...); + +/* + * FUNCTION: PKIX_PL_GetString + * DESCRIPTION: + * + * Retrieves the String associated with the value of "stringID" (if any) and + * stores it at "pString". If no such string is associated with "stringID", + * this function uses "defaultString" to create a String and stores it at + * "pString". + * + * PARAMETERS: + * "stringID" + * PKIX_UInt32 valud of string identifier. + * "defaultString" + * Address of a PKIX_ESCASCII encoded string representation. + * Must be non-NULL. + * "pString" + * 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 String 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_PL_GetString( + PKIX_UInt32 stringID, + char *defaultString, + PKIX_PL_String **pString, + void *plContext); + +/* + * FUNCTION: PKIX_PL_String_GetEncoded + * DESCRIPTION: + * + * Retrieves the value of the String pointed to by "string" in the encoding + * specified by "fmtIndicator" and stores the result in "pStringRep" and + * "pLength", respectively. Note that "pStringRep" is not reference counted + * and will need to be freed with PKIX_PL_Free(). + * + * PARAMETERS: + * "string" + * Address of String whose encoded value is desired. Must be non-NULL. + * "fmtIndicator" + * Format of encoding. Supported formats are: + * PKIX_ESCASCII, PKIX_ESCASII_DEBUG, PKIX_UTF8, PKIX_UTF8_NULL_TERM, and + * PKIX_UTF16. XXX Where are these documented? + * "pStringRep" + * Address where pointer to encoded value will be stored. + * Must be non-NULL. + * "pLength" + * Address where byte length of encoded value will 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 String 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_PL_String_GetEncoded( + PKIX_PL_String *string, + PKIX_UInt32 fmtIndicator, + void **pStringRep, + PKIX_UInt32 *pLength, + void *plContext); + +/* + * Hashtable + * + * A hashtable is a very efficient data structure used for mapping keys to + * values. Any non-null PKIX_PL_Object can be used as a key or as a value, + * provided that it correctly implements the PKIX_PL_EqualsCallback and the + * PKIX_PL_HashcodeCallback. A hashtable consists of several buckets, with + * each bucket capable of holding a linked list of key/value mappings. When + * adding, retrieving, or deleting a value, the hashcode of the key is used to + * determine which bucket's linked list is relevant. The corresponding + * key/value pair is then appended, retrieved, or deleted. + */ + +/* + * FUNCTION: PKIX_PL_HashTable_Create + * DESCRIPTION: + * + * Creates a new Hashtable with an initial capacity of "numBuckets" buckets + * and "maxEntriesPerBucket" of entries limit for each bucket and stores it + * at "pResult". + * + * PARAMETERS: + * "numBuckets" + * The initial number of hash table buckets. Must be non-zero. + * "maxEntriesPerBucket" + * The limit of entries per bucket. Zero means no limit. + * "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_PL_HashTable_Create( + PKIX_UInt32 numBuckets, + PKIX_UInt32 maxEntriesPerBucket, + PKIX_PL_HashTable **pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_HashTable_Add + * DESCRIPTION: + * + * Adds a key/value mapping using the Objects pointed to by "key" and "value" + * to the Hashtable pointed to by "ht". + * + * Function increments key/value reference counts. Caller is responsible to + * to decrement(destroy) key/value ref counts(objects). + * + * PARAMETERS: + * "ht" + * Address of Hashtable to be added to. Must be non-NULL. + * "key" + * Address of Object to be associated with "value". Must be non-NULL. + * "value" + * Address of Object to be added to Hashtable. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Hashtable 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_PL_HashTable_Add( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + PKIX_PL_Object *value, + void *plContext); + +/* + * FUNCTION: PKIX_PL_HashTable_Remove + * DESCRIPTION: + * + * Removes the Object value whose key is equal to the Object pointed to by + * "key" from the Hashtable pointed to by "ht". If no such object exists, + * this function throws an Error. + * + * Function frees "value" object. Caller is responsible to free "key" + * object. + * + * PARAMETERS: + * "ht" + * Address of Hashtable to remove object from. Must be non-NULL. + * "key" + * Address of Object used for lookup. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Hashtable 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_PL_HashTable_Remove( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + void *plContext); + +/* + * FUNCTION: PKIX_PL_HashTable_Lookup + * DESCRIPTION: + * + * Retrieves the Object whose key equals the Object pointed to by "key" from + * the Hashtable associated with "ht" and stores it at "pResult". If no + * Object is found, this function stores NULL at "pResult". + * + * PARAMETERS: + * "ht" + * Address of Hashtable to lookup Object from. Must be non-NULL. + * "key" + * Address of key Object used for lookup. Must be non-NULL. + * "pResult" + * 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 Hashtable 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_PL_HashTable_Lookup( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + PKIX_PL_Object **pResult, + void *plContext); + +/* + * FUNCTION: PKIX_PL_ByteArray_Create + * DESCRIPTION: + * + * Creates a new ByteArray using "length" bytes of data pointed to by "array" + * and stores it at "pByteArray". Once created, a ByteArray is immutable. + * + * PARAMETERS: + * "array" + * Address of source data. + * "length" + * Number of bytes to copy. + * "pByteArray" + * 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_PL_ByteArray_Create( + void *array, + PKIX_UInt32 length, + PKIX_PL_ByteArray **pByteArray, + void *plContext); + +/* + * FUNCTION: PKIX_PL_ByteArray_GetPointer + * DESCRIPTION: + * + * Allocates enough memory to hold the contents of the ByteArray pointed to + * by "byteArray", copies the data from the ByteArray pointed to by + * "byteArray" into the newly allocated memory, and stores a pointer to the + * memory at "pArray". Note that "pArray" is not reference counted. It will + * need to be freed with PKIX_PL_Free(). + * + * PARAMETERS: + * "byteArray" + * Address of ByteArray whose data is desired. Must be non-NULL. + * "pArray" + * 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_PL_ByteArray_GetPointer( + PKIX_PL_ByteArray *byteArray, + void **pArray, + void *plContext); + +/* + * FUNCTION: PKIX_PL_ByteArray_GetLength + * DESCRIPTION: + * + * Retrieves the length of the ByteArray pointed to by "byteArray" and stores + * the length at "pLength". + * + * PARAMETERS: + * "byteArray" + * Address of ByteArray whose length is desired. Must be non-NULL. + * "pLength" + * Address where PKIX_UInt32 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_PL_ByteArray_GetLength( + PKIX_PL_ByteArray *byteArray, + PKIX_UInt32 *pLength, + void *plContext); + +/* + * FUNCTION: PKIX_PL_OID_Create + * DESCRIPTION: + * + * Creates a new OID using NSS oid tag. + * + * PARAMETERS: + * "idtag" + * nss oid id tag. + * "pOID" + * 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 OID 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_PL_OID_Create( + SECOidTag idtag, + PKIX_PL_OID **pOID, + void *plContext); + +/* + * FUNCTION: PKIX_PL_OID_CreateBySECItem + * DESCRIPTION: + * + * Creates a new OID using a DER encoded OID stored as SECItem. + * + * PARAMETERS: + * "derOid" + * Address of SECItem that holds DER encoded OID. + * "pOID" + * 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 OID 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_PL_OID_CreateBySECItem( + SECItem *derOid, + PKIX_PL_OID **pOID, + void *plContext); + +/* + * FUNCTION: PKIX_PL_BigInt_Create + * DESCRIPTION: + * + * Creates a new BigInt using the source String pointed to by "stringRep" and + * stores it at "pBigInt". Valid source Strings consist of an even number of + * hexadecimal digits, which are always interpreted as a positive number. + * Once created, a BigInt is immutable. + * + * The regexp format is: + * HexDigit ::= [0-9] | [A-F] | [a-f] + * DoubleHex ::= HexDigit HexDigit + * BigIntSrc ::= (DoubleHex)+ + * + * Note that since we are using DoubleHex, the number of characters in the + * source MUST be even. Additionally, the first DoubleHex MUST NOT be "00" + * unless it is the only DoubleHex. + * + * Valid : "09" + * Valid : "00" (special case where first and only DoubleHex is "00") + * Invalid: "9" (not DoubleHex: odd number of characters) + * Invalid: "0009" (first DoubleHex is "00") + * + * XXX Why does this take a String object while OID_Create takes a char* ? + * Perhaps because OID_Create is often used with constant strings and + * this function isn't. That's a good reason, but we should explain it + * (if it's right) + * PARAMETERS: + * "stringRep" + * Address of String representing a BigInt. Must be non-NULL. + * "pBigInt" + * 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 BigInt 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_PL_BigInt_Create( + PKIX_PL_String *stringRep, + PKIX_PL_BigInt **pBigInt, + void *plContext); + +#ifdef __cplusplus +} +#endif + +/* + * FUNCTION: PKIX_PL_GetPLErrorCode + * DESCRIPTION: + * + * Returns error code from PL layer. + * + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * PL layer error code. + */ +int +PKIX_PL_GetPLErrorCode(); + +#endif /* _LIBPKIX_SYSTEM_H */ diff --git a/security/nss/lib/libpkix/include/pkix_results.h b/security/nss/lib/libpkix/include/pkix_results.h new file mode 100644 index 0000000000..bf4a381faa --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_results.h @@ -0,0 +1,425 @@ +/* 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/. */ +/* + * This file defines functions associated with the results used + * by the top-level functions. + * + */ + +#ifndef _PKIX_RESULTS_H +#define _PKIX_RESULTS_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ +/* PKIX_ValidateResult + * + * PKIX_ValidateResult represents the result of a PKIX_ValidateChain call. It + * consists of the valid policy tree and public key resulting from validation, + * as well as the trust anchor used for this chain. Once created, a + * ValidateResult object is immutable. + */ + +/* + * FUNCTION: PKIX_ValidateResult_GetPolicyTree + * DESCRIPTION: + * + * Retrieves the PolicyNode component (representing the valid_policy_tree) + * from the ValidateResult object pointed to by "result" and stores it at + * "pPolicyTree". + * + * PARAMETERS: + * "result" + * Address of ValidateResult whose policy tree is to be stored. Must be + * non-NULL. + * "pPolicyTree" + * 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 Result 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_ValidateResult_GetPolicyTree( + PKIX_ValidateResult *result, + PKIX_PolicyNode **pPolicyTree, + void *plContext); + +/* + * FUNCTION: PKIX_ValidateResult_GetPublicKey + * DESCRIPTION: + * + * Retrieves the PublicKey component (representing the valid public_key) of + * the ValidateResult object pointed to by "result" and stores it at + * "pPublicKey". + * + * PARAMETERS: + * "result" + * Address of ValidateResult whose public key is to be stored. + * Must be non-NULL. + * "pPublicKey" + * 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 Result 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_ValidateResult_GetPublicKey( + PKIX_ValidateResult *result, + PKIX_PL_PublicKey **pPublicKey, + void *plContext); + +/* + * FUNCTION: PKIX_ValidateResult_GetTrustAnchor + * DESCRIPTION: + * + * Retrieves the TrustAnchor component (representing the trust anchor used + * during chain validation) of the ValidateResult object pointed to by + * "result" and stores it at "pTrustAnchor". + * + * PARAMETERS: + * "result" + * Address of ValidateResult whose trust anchor is to be stored. + * Must be non-NULL. + * "pTrustAnchor" + * 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 Result 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_ValidateResult_GetTrustAnchor( + PKIX_ValidateResult *result, + PKIX_TrustAnchor **pTrustAnchor, + void *plContext); + +/* PKIX_BuildResult + * + * PKIX_BuildResult represents the result of a PKIX_BuildChain call. It + * consists of a ValidateResult object, as well as the built and validated + * CertChain. Once created, a BuildResult object is immutable. + */ + +/* + * FUNCTION: PKIX_BuildResult_GetValidateResult + * DESCRIPTION: + * + * Retrieves the ValidateResult component (representing the build's validate + * result) of the BuildResult object pointed to by "result" and stores it at + * "pResult". + * + * PARAMETERS: + * "result" + * Address of BuildResult whose ValidateResult component is to be stored. + * 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 Result 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_BuildResult_GetValidateResult( + PKIX_BuildResult *result, + PKIX_ValidateResult **pResult, + void *plContext); + +/* + * FUNCTION: PKIX_BuildResult_GetCertChain + * DESCRIPTION: + * + * Retrieves the List of Certs (certChain) component (representing the built + * and validated CertChain) of the BuildResult object pointed to by "result" + * and stores it at "pChain". + * + * PARAMETERS: + * "result" + * Address of BuildResult whose CertChain component is to be stored. + * Must be non-NULL. + * "pChain" + * 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 Result 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_BuildResult_GetCertChain( + PKIX_BuildResult *result, + PKIX_List **pChain, + void *plContext); + +/* PKIX_PolicyNode + * + * PKIX_PolicyNode represents a node in the policy tree returned in + * ValidateResult. The policy tree is the same length as the validated + * certificate chain and the nodes are associated with a particular depth + * (corresponding to a particular certificate in the chain). + * PKIX_ValidateResult_GetPolicyTree returns the root node of the valid policy + * tree. Other nodes can be accessed using the getChildren and getParents + * functions, and individual elements of a node can be accessed with the + * appropriate gettors. Once created, a PolicyNode is immutable. + */ + +/* + * FUNCTION: PKIX_PolicyNode_GetChildren + * 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 child nodes, this function stores an empty List at "pChildren". + * + * Note that the List returned by this function is 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: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Result 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_GetChildren( + PKIX_PolicyNode *node, + PKIX_List **pChildren, /* list of PKIX_PolicyNode */ + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_GetParent + * DESCRIPTION: + * + * Retrieves the PolicyNode representing the parent node of the PolicyNode + * pointed to by "node" and stores it at "pParent". If "node" has no parent + * node, this function stores NULL at "pParent". + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose parent node is to be stored. + * Must be non-NULL. + * "pParent" + * 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 Result 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_GetParent( + PKIX_PolicyNode *node, + PKIX_PolicyNode **pParent, + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_GetValidPolicy + * DESCRIPTION: + * + * Retrieves the OID representing the valid policy of the PolicyNode pointed + * to by "node" and stores it at "pValidPolicy". + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose valid policy is to be stored. + * Must be non-NULL. + * "pValidPolicy" + * 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 Result 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_GetValidPolicy( + PKIX_PolicyNode *node, + PKIX_PL_OID **pValidPolicy, + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers + * DESCRIPTION: + * + * Retrieves the List of CertPolicyQualifiers representing the policy + * qualifiers associated with the PolicyNode pointed to by "node" and stores + * it at "pQualifiers". If "node" has no policy qualifiers, this function + * stores an empty List at "pQualifiers". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose policy qualifiers are to be stored. + * Must be non-NULL. + * "pQualifiers" + * 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 Result 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_GetPolicyQualifiers( + PKIX_PolicyNode *node, + PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */ + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies + * DESCRIPTION: + * + * Retrieves the List of OIDs representing the expected policies associated + * with the PolicyNode pointed to by "node" and stores it at "pExpPolicies". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose expected policies are to be stored. + * Must be non-NULL. + * "pExpPolicies" + * 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 Result 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_GetExpectedPolicies( + PKIX_PolicyNode *node, + PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */ + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_IsCritical + * DESCRIPTION: + * + * Checks the criticality field of the PolicyNode pointed to by "node" and + * stores the Boolean result at "pCritical". + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose criticality field is examined. + * Must be non-NULL. + * "pCritical" + * 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 Result 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_IsCritical( + PKIX_PolicyNode *node, + PKIX_Boolean *pCritical, + void *plContext); + +/* + * FUNCTION: PKIX_PolicyNode_GetDepth + * DESCRIPTION: + * + * Retrieves the depth component of the PolicyNode pointed to by "node" and + * stores it at "pDepth". + * + * PARAMETERS: + * "node" + * Address of PolicyNode whose depth component is to be stored. + * Must be non-NULL. + * "pDepth" + * Address where PKIX_UInt32 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 Result 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_GetDepth( + PKIX_PolicyNode *node, + PKIX_UInt32 *pDepth, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_RESULTS_H */ diff --git a/security/nss/lib/libpkix/include/pkix_revchecker.h b/security/nss/lib/libpkix/include/pkix_revchecker.h new file mode 100644 index 0000000000..a16d23a933 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_revchecker.h @@ -0,0 +1,215 @@ +/* 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/. */ +/* + * This file defines functions associated with the PKIX_RevocationChecker + * type. + * + */ + +#ifndef _PKIX_REVCHECKER_H +#define _PKIX_REVCHECKER_H + +#include "pkixt.h" +#include "pkix_pl_pki.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_RevocationChecker + * + * PKIX_RevocationChecker provides a standard way of revocation checking. + * Caller should configure two set of tests(represented at lists of + * RevocationMethod objects) to be performed on the leaf and on the rest of + * the chain certificates. + * + * PKIX_RevocationMethods provide a standard way for the caller to insert + * their own custom revocation checks to verify the revocation status of + * certificates. This may be useful in many scenarios, including when the + * caller wishes to use their own revocation checking mechanism instead of (or + * in addition to) the default revocation checking mechanism provided by + * libpkix, which uses CRLs and OCSP. + * + * Once the caller has created the RevocationMethod object(s), the caller + * then specifies the RevocationMethod object(s) in a RevocationCheck object + * and sets it into a ProcessingParams. + */ + +/* + * FUNCTION: PKIX_RevocationChecker_Create + * DESCRIPTION: + * + * Creates a revocation checker object with the given flags. Revocation will + * be checked at the current date. + * + * PARAMETERS: + * "leafMethodListFlags" + * Defines a set of method independent flags that will be used to check + * revocation of the leaf cert in the chain. + * "chainMethodListFlags" + * Defines a set of method independent flags that will be used to check + * revocation of the remaining certs in the chain. + * "pChecker" + * The return address of created checker. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a RevocationChecker 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_RevocationChecker_Create( + PKIX_UInt32 leafMethodListFlags, + PKIX_UInt32 chainMethodListFlags, + PKIX_RevocationChecker **pChecker, + void *plContext); + +/* + * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod + * DESCRIPTION: + * + * Creates revocation method object with given parameters and adds it + * to revocation checker method list. + * + * PARAMETERS: + * "revChecker" + * Address of revocation checker structure. + * "procParams" + * Address of ProcessingParams used to initialize the checker. + * Must be non-NULL. + * "methodType" + * Type of the method. Currently only two types are + * supported: crl and ocsp. (See PKIX_RevocationMethodType enum). + * "methodFlags" + * Set of flags for the method. + * "methodPriority" + * Method priority. (0 corresponds to the highest priority) + * "verificationFn" + * User call back function that will perform validation of fetched + * revocation information(new crl or ocsp response) + * "isLeafMethod" + * Boolean flag that if set to true indicates that the method should + * should be used for leaf cert revocation test(false for chain set + * methods). + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a RevocationChecker 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_RevocationChecker_CreateAndAddMethod( + PKIX_RevocationChecker *revChecker, + PKIX_ProcessingParams *params, + PKIX_RevocationMethodType methodType, + PKIX_UInt32 methodFlags, + PKIX_UInt32 methodPriority, + PKIX_PL_VerifyCallback verificationFn, + PKIX_Boolean isLeafMethod, + void *plContext); + +/* + * FUNCTION: PKIX_RevocationChecker_Check + * DESCRIPTION: + * + * Verifies revocation status of the certificate. Issuer cert is given to + * be used in verification of revocation information. Performed verification + * check depends on configured revocation methods(ocsp, crl. See + * PKIX_RevocationChecker_CreateAndAddMethod function) and a point of chain + * building process at which PKIX_RevocationChecker_Check was invoked. + * For security reasons, the cert status is checked only against cached + * revocation information during chain building stage(no trust anchor yes has + * been found). The fresh revocation information fetching is done only at chain + * verification stage after trust anchor was identified. + * + * PARAMETERS: + * "cert" + * Address of Cert whose revocation status is to be determined. + * Must be non-NULL. + * "issuer" + * Issuer cert that potentially holds public key that will be used + * to verify revocation info. + * "revChecker" + * Address of revocation checker structure. + * "procParams" + * Address of ProcessingParams used to initialize the checker. + * Must be non-NULL. + * "chainVerificationState" + * Need to be set to true, if the check was called during chain verification + * as an opposite to chain building. + * "testingLeafCert" + * Set to true if verifying revocation status of a leaf cert. + * "revStatus" + * Address of the returned revocation status of the cert. + * "pResultCode" + * Address where revocation status will be stored. Must be non-NULL. + * "pNBIOContext" + * Address at which platform-dependent non-blocking I/O context is stored. + * Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a RevocationChecker 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_RevocationChecker_Check(PKIX_PL_Cert *cert, + PKIX_PL_Cert *issuer, + PKIX_RevocationChecker *revChecker, + PKIX_ProcessingParams *procParams, + PKIX_Boolean chainVerificationState, + PKIX_Boolean testingLeafCert, + PKIX_RevocationStatus *revStatus, + PKIX_UInt32 *pReasonCode, + void **pNbioContext, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_REVCHECKER_H */ diff --git a/security/nss/lib/libpkix/include/pkix_sample_modules.h b/security/nss/lib/libpkix/include/pkix_sample_modules.h new file mode 100644 index 0000000000..75d9618c57 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_sample_modules.h @@ -0,0 +1,420 @@ +/* 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/. */ +/* + * This file defines functions associated with CertStore types. + * + */ + + +#ifndef _PKIX_SAMPLEMODULES_H +#define _PKIX_SAMPLEMODULES_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_PL_CollectionCertStore + * + * A PKIX_CollectionCertStore provides an example for showing how to retrieve + * certificates and CRLs from a repository, such as a directory in the system. + * It is expected the directory is an absolute directory which contains CRL + * and Cert data files. CRL files are expected to have the suffix of .crl + * and Cert files are expected to have the suffix of .crt . + * + * Once the caller has created the CollectionCertStoreContext object, the caller + * then can call pkix_pl_CollectionCertStore_GetCert or + * pkix_pl_CollectionCertStore_GetCRL to obtain Lists of PKIX_PL_Cert or + * PKIX_PL_CRL objects, respectively. + */ + +/* + * FUNCTION: PKIX_PL_CollectionCertStore_Create + * DESCRIPTION: + * + * Creates a new CollectionCertStore and returns it at + * "pColCertStore". + * + * PARAMETERS: + * "storeDir" + * The absolute path where *.crl files are located. + * "pColCertStoreContext" + * 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 CollectionCertStoreContext 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_PL_CollectionCertStore_Create( + PKIX_PL_String *storeDir, + PKIX_CertStore **pCertStore, + void *plContext); + +/* PKIX_PL_PK11CertStore + * + * A PKIX_PL_PK11CertStore retrieves certificates and CRLs from a PKCS11 + * database. The directory that contains the cert8.db, key3.db, and secmod.db + * files that comprise a PKCS11 database are specified in NSS initialization. + * + * Once the caller has created the Pk11CertStore object, the caller can call + * pkix_pl_Pk11CertStore_GetCert or pkix_pl_Pk11CertStore_GetCert to obtain + * a List of PKIX_PL_Certs or PKIX_PL_CRL objects, respectively. + */ + +/* + * FUNCTION: PKIX_PL_Pk11CertStore_Create + * DESCRIPTION: + * + * Creates a new Pk11CertStore and returns it at "pPk11CertStore". + * + * PARAMETERS: + * "pPk11CertStore" + * 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 CertStore 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_PL_Pk11CertStore_Create( + PKIX_CertStore **pPk11CertStore, + void *plContext); + +#ifndef NSS_PKIX_NO_LDAP +/* PKIX_PL_LdapCertStore + * + * A PKIX_PL_LdapCertStore retrieves certificates and CRLs from an LDAP server + * over a socket connection. It used the LDAP protocol as described in RFC1777. + * + * Once the caller has created the LdapCertStore object, the caller can call + * pkix_pl_LdapCertStore_GetCert or pkix_pl_LdapCertStore_GetCert to obtain + * a List of PKIX_PL_Certs or PKIX_PL_CRL objects, respectively. + */ + +/* + * FUNCTION: PKIX_PL_LdapDefaultClient_Create + * DESCRIPTION: + * + * Creates an LdapDefaultClient using the PRNetAddr poined to by "sockaddr", + * with a timeout value of "timeout", and a BindAPI pointed to by "bindAPI"; + * and stores the address of the default LdapClient at "pClient". + * + * At the time of this version, there are unresolved questions about the LDAP + * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not + * clear whether they are appropriate to this application. We have tested only + * using servers that do not expect authentication, and that reject BIND + * messages. It is not clear what values might be appropriate for the bindname + * and authentication fields, which are currently implemented as char strings + * supplied by the caller. (If this changes, the API and possibly the templates + * will have to change.) Therefore the Client_Create API contains a BindAPI + * structure, a union, which will have to be revised and extended when this + * area of the protocol is better understood. + * + * PARAMETERS: + * "sockaddr" + * Address of the PRNetAddr to be used for the socket connection. Must be + * non-NULL. + * "timeout" + * The PRIntervalTime value to be used as a timeout value in socket calls; + * a zero value indicates non-blocking I/O is to be used. + * "bindAPI" + * The address of a BindAPI to be used if a BIND message is required. If + * this argument is NULL, no Bind (or Unbind) will be sent. + * "pClient" + * 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 CertStore 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_PL_LdapDefaultClient_Create( + PRNetAddr *sockaddr, + PRIntervalTime timeout, + LDAPBindAPI *bindAPI, + PKIX_PL_LdapDefaultClient **pClient, + void *plContext); + +/* + * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName + * DESCRIPTION: + * + * Creates an LdapDefaultClient using the hostname poined to by "hostname", + * with a timeout value of "timeout", and a BindAPI pointed to by "bindAPI"; + * and stores the address of the default LdapClient at "pClient". + * + * At the time of this version, there are unresolved questions about the LDAP + * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not + * clear whether they are appropriate to this application. We have tested only + * using servers that do not expect authentication, and that reject BIND + * messages. It is not clear what values might be appropriate for the bindname + * and authentication fields, which are currently implemented as char strings + * supplied by the caller. (If this changes, the API and possibly the templates + * will have to change.) Therefore the Client_Create API contains a BindAPI + * structure, a union, which will have to be revised and extended when this + * area of the protocol is better understood. + * + * PARAMETERS: + * "hostname" + * Address of the hostname to be used for the socket connection. Must be + * non-NULL. + * "timeout" + * The PRIntervalTime value to be used as a timeout value in socket calls; + * a zero value indicates non-blocking I/O is to be used. + * "bindAPI" + * The address of a BindAPI to be used if a BIND message is required. If + * this argument is NULL, no Bind (or Unbind) will be sent. + * "pClient" + * 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 CertStore 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_PL_LdapDefaultClient_CreateByName( + char *hostname, + PRIntervalTime timeout, + LDAPBindAPI *bindAPI, + PKIX_PL_LdapDefaultClient **pClient, + void *plContext); + +/* + * FUNCTION: PKIX_PL_LdapCertStore_Create + * DESCRIPTION: + * + * Creates a new LdapCertStore using the LdapClient pointed to by "client", + * and stores the address of the CertStore at "pCertStore". + * + * PARAMETERS: + * "client" + * Address of the LdapClient to be used. Must be non-NULL. + * "pCertStore" + * 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 CertStore 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_PL_LdapCertStore_Create( + PKIX_PL_LdapClient *client, + PKIX_CertStore **pCertStore, + void *plContext); +#endif /* !NSS_PKIX_NO_LDAP */ + +/* PKIX_PL_NssContext + * + * A PKIX_PL_NssContext provides an example showing how the "plContext" + * argument, that is part of every libpkix function call, can be used. + * The "plContext" is the Portability Layer Context, which can be used + * to communicate layer-specific information from the application to the + * underlying Portability Layer (while bypassing the Portable Code, which + * blindly passes the plContext on to every function call). + * + * In this case, NSS serves as both the application and the Portability Layer. + * We define an NSS-specific structure, which includes an arena and a number + * of SECCertificateUsage bit flags encoded as a PKIX_UInt32. A third argument, + * wincx, is used on Windows platforms for PKCS11 access, and should be set to + * NULL for other platforms. + * Before calling any of the libpkix functions, the caller should create the NSS + * context, by calling PKIX_PL_NssContext_Create, and provide that NSS context + * as the "plContext" argument in every libpkix function call the caller makes. + * When the caller is finished using the NSS context (usually just after he + * calls PKIX_Shutdown), the caller should call PKIX_PL_NssContext_Destroy to + * free the NSS context structure. + */ + +/* + * FUNCTION: PKIX_PL_NssContext_Create + * DESCRIPTION: + * + * Creates a new NssContext using the certificate usage(s) specified by + * "certUsage" and stores it at "pNssContext". This function also internally + * creates an arena and stores it as part of the NssContext structure. Unlike + * most other libpkix API functions, this function does not take a "plContext" + * parameter. + * + * PARAMETERS: + * "certUsage" + * The desired SECCertificateUsage(s). + * "useNssArena" + * Boolean flag indicates NSS Arena is used for memory allocation. + * "wincx" + * A Windows-dependent pointer for PKCS11 token handling. + * "pNssContext" + * Address where object pointer will be stored. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_Create( + PKIX_UInt32 certificateUsage, + PKIX_Boolean useNssArena, + void *wincx, + void **pNssContext); + +/* + * FUNCTION: PKIX_PL_NssContext_Destroy + * DESCRIPTION: + * + * Frees the structure pointed to by "nssContext" along with any of its + * associated memory. Unlike most other libpkix API functions, this function + * does not take a "plContext" parameter. + * + * PARAMETERS: + * "nssContext" + * Address of NssContext to be destroyed. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_Destroy( + void *nssContext); + +/* + * FUNCTION: PKIX_PL_NssContext_SetTimeout + * DESCRIPTION: + * + * Sets IO timeout for network operations like OCSP response and cert + * fetching. + * + * PARAMETERS: + * "nssContext" + * Address of NssContext to be destroyed. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_SetTimeout(PKIX_UInt32 timeout, PKIX_PL_NssContext *nssContext); + +/* + * FUNCTION: PKIX_PL_NssContext_SetMaxResponseLen + * DESCRIPTION: + * + * Sets maximum responce length allowed during network IO operations. + * + * PARAMETERS: + * "nssContext" + * Address of NssContext to be destroyed. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_SetMaxResponseLen(PKIX_UInt32 len, PKIX_PL_NssContext *nssContext); + +/* + * FUNCTION: PKIX_PL_NssContext_SetCrlReloadDelay + * DESCRIPTION: + * + * Sets user defined timeout between attempts to load crl using + * CRLDP. + * + * PARAMETERS: + * "delaySeconds" + * Reload delay in seconds. + * "nssContext" + * Address of NssContext to be destroyed. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_SetCrlReloadDelay(PKIX_UInt32 delaySeconds, + PKIX_PL_NssContext *nssContext); + +/* + * FUNCTION: PKIX_PL_NssContext_SetBadDerCrlReloadDelay + * DESCRIPTION: + * + * Sets user defined timeout between attempts to load crls + * that failed to decode. + * + * PARAMETERS: + * "delaySeconds" + * Reload delay in seconds. + * "nssContext" + * Address of NssContext to be destroyed. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Context 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_PL_NssContext_SetBadDerCrlReloadDelay(PKIX_UInt32 delaySeconds, + PKIX_PL_NssContext *nssContext); +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_SAMPLEMODULES_H */ diff --git a/security/nss/lib/libpkix/include/pkix_util.h b/security/nss/lib/libpkix/include/pkix_util.h new file mode 100644 index 0000000000..e42f608c17 --- /dev/null +++ b/security/nss/lib/libpkix/include/pkix_util.h @@ -0,0 +1,941 @@ +/* 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/. */ +/* + * These functions provide support for a number of other functions + * by creating and manipulating data structures used by those functions. + * + */ + +#ifndef _PKIX_UTIL_H +#define _PKIX_UTIL_H + +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* General + * + * Please refer to the libpkix Programmer's Guide for detailed information + * about how to use the libpkix library. Certain key warnings and notices from + * that document are repeated here for emphasis. + * + * All identifiers in this file (and all public identifiers defined in + * libpkix) begin with "PKIX_". Private identifiers only intended for use + * within the library begin with "pkix_". + * + * A function returns NULL upon success, and a PKIX_Error pointer upon failure. + * + * Unless otherwise noted, for all accessor (gettor) functions that return a + * PKIX_PL_Object pointer, callers should assume that this pointer refers to a + * shared object. Therefore, the caller should treat this shared object as + * read-only and should not modify this shared object. When done using the + * shared object, the caller should release the reference to the object by + * using the PKIX_PL_Object_DecRef function. + * + * While a function is executing, if its arguments (or anything referred to by + * its arguments) are modified, free'd, or destroyed, the function's behavior + * is undefined. + * + */ + +/* PKIX_Logger + * + * PKIX_Loggers provide a standard way for the caller to insert custom logging + * facilities. These are used by libpkix to log errors, debug information, + * status, etc. The LogCallback allows custom logging to take place. + * Additionally, a Logger can be initialized with a loggerContext, which is + * where the caller can specify configuration data such as the name of a + * logfile or database. Note that this loggerContext must be a PKIX_PL_Object, + * allowing it to be reference-counted and allowing it to provide the standard + * PKIX_PL_Object functions (Equals, Hashcode, ToString, Compare, Duplicate). + * + * Once the caller has created the Logger object(s) (and set the loggerContext + * (if any) and the Log callback), the caller then registers these Loggers + * with the system by calling PKIX_SetLoggers or PKIX_AddLogger. All log + * entries will then be logged using the specified Loggers. If multiple + * Loggers are specified, every log entry will be logged with each of them. + * + * XXX Maybe give some guidance somewhere on how much detail each logging + * level should have and where component boundaries should be. Maybe in + * Implementor's Guide or Programmer's Guide. + */ + +#define PKIX_LOGGER_LEVEL_TRACE 5 +#define PKIX_LOGGER_LEVEL_DEBUG 4 +#define PKIX_LOGGER_LEVEL_WARNING 3 +#define PKIX_LOGGER_LEVEL_ERROR 2 +#define PKIX_LOGGER_LEVEL_FATALERROR 1 + +#define PKIX_LOGGER_LEVEL_MAX 5 + +/* + * FUNCTION: PKIX_Logger_LogCallback + * DESCRIPTION: + * + * This callback function logs a log entry containing the String pointed to + * by "message", the integer value of logLevel, and the String pointed to by + * "logComponent". A log entry can be associated with a particular log + * level (i.e. level 3) and a particular log component (i.e. "CertStore"). + * For example, someone reading the log may only be interested in very general + * log entries so they look only for log level 1. Similarly, they may only be + * interested in log entries pertaining to the CertStore component so they + * look only for that log component. This function can be used before calling + * PKIX_Initialize. + * + * PARAMETERS: + * "logger" + * Address of logger whose LogCallback is to be used. Must be non-NULL. + * "message" + * Address of String that is to be logged used "logger". Must be non-NULL. + * "logLevel" + * Integer value representing the log level for this entry. The higher the + * level, the more detail. Must be non-NULL. + * "logComponent" + * PKIXERRORNUM value (defined in pkixt.h) designating the log component + * for this entry. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe + * + * Multiple threads must be able to safely call this function without + * worrying about conflicts, even if they're operating on the same objects. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Logger Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +typedef PKIX_Error * +(*PKIX_Logger_LogCallback)( + PKIX_Logger *logger, + PKIX_PL_String *message, + PKIX_UInt32 logLevel, + PKIX_ERRORCLASS logComponent, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_Create + * DESCRIPTION: + * + * Creates a new Logger using the Object pointed to by "loggerContext" + * (if any) and stores it at "pLogger". The new Logger uses the LogCallback + * pointed to by "callback". The Logger's maximum logging level is initially + * set to a very high level and its logging component is set to NULL (all + * components). + * + * PARAMETERS: + * "callback" + * The LogCallback function to be used. Must be non-NULL. + * "loggerContext" + * Address of Object representing the Logger's context (if any). + * "pLogger" + * 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 Logger 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_Logger_Create( + PKIX_Logger_LogCallback callback, + PKIX_PL_Object *loggerContext, + PKIX_Logger **pLogger, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_GetLogCallback + * DESCRIPTION: + * + * Retrieves a pointer to "logger's" Log callback function and puts it in + * "pCallback". + * + * PARAMETERS: + * "logger" + * Address of Logger whose Log callback is desired. Must be non-NULL. + * "pCallback" + * Address where Log callback function 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 Logger 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_Logger_GetLogCallback( + PKIX_Logger *logger, + PKIX_Logger_LogCallback *pCallback, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_GetLoggerContext + * DESCRIPTION: + * + * Retrieves a pointer to a PKIX_PL_Object representing the context (if any) + * of the Logger pointed to by "logger" and stores it at "pLoggerContext". + * + * PARAMETERS: + * "logger" + * Address of Logger whose context is to be stored. Must be non-NULL. + * "pLoggerContext" + * 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 Logger 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_Logger_GetLoggerContext( + PKIX_Logger *logger, + PKIX_PL_Object **pLoggerContext, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_GetMaxLoggingLevel + * DESCRIPTION: + * + * Retrieves a pointer to a PKIX_UInt32 representing the maximum logging + * level of the Logger pointed to by "logger" and stores it at "pLevel". Only + * log entries whose log level is less than or equal to this maximum logging + * level will be logged. + * + * PARAMETERS: + * "logger" + * Address of Logger whose maximum logging level is to be stored. + * Must be non-NULL. + * "pLevel" + * Address where PKIX_UInt32 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 Logger 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_Logger_GetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 *pLevel, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_SetMaxLoggingLevel + * DESCRIPTION: + * + * Sets the maximum logging level of the Logger pointed to by "logger" with + * the integer value of "level". + * + * PARAMETERS: + * "logger" + * Address of Logger whose maximum logging level is to be set. + * Must be non-NULL. + * "level" + * Maximum logging level to be set + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "logger" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Logger 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_Logger_SetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 level, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_GetLoggingComponent + * DESCRIPTION: + * + * Retrieves a pointer to a String representing the logging component of the + * Logger pointed to by "logger" and stores it at "pComponent". Only log + * entries whose log component matches the specified logging component will + * be logged. + * + * PARAMETERS: + * "logger" + * Address of Logger whose logging component is to be stored. + * Must be non-NULL. + * "pComponent" + * Address where PKIXERRORNUM 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 Logger 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_Logger_GetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS *pComponent, + void *plContext); + +/* + * FUNCTION: PKIX_Logger_SetLoggingComponent + * DESCRIPTION: + * + * Sets the logging component of the Logger pointed to by "logger" with the + * PKIXERRORNUM pointed to by "component". To match a small set of components, + * create a Logger for each. + * + * PARAMETERS: + * "logger" + * Address of Logger whose logging component is to be set. + * Must be non-NULL. + * "component" + * PKIXERRORNUM value representing logging component to be set. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "logger" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a Logger 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_Logger_SetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS component, + void *plContext); + +/* + * FUNCTION: PKIX_GetLoggers + * DESCRIPTION: + * + * Retrieves a pointer to the List of Loggers (if any) being used for logging + * by libpkix and stores it at "pLoggers". If no loggers are being used, this + * function stores an empty List at "pLoggers". + * + * Note that the List returned by this function is immutable. + * + * PARAMETERS: + * "pLoggers" + * 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 Logger 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_GetLoggers( + PKIX_List **pLoggers, /* list of PKIX_Logger */ + void *plContext); + +/* + * FUNCTION: PKIX_SetLoggers + * DESCRIPTION: + * + * Sets the Loggers to be used by libpkix to the List of Loggers pointed to + * by "loggers". If "loggers" is NULL, no Loggers will be used. + * + * PARAMETERS: + * "loggers" + * Address of List of Loggers to be set. NULL for no Loggers. + * "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 Logger 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_SetLoggers( + PKIX_List *loggers, /* list of PKIX_Logger */ + void *plContext); + +/* + * FUNCTION: PKIX_AddLogger + * DESCRIPTION: + * + * Adds the Logger pointed to by "logger" to the List of Loggers used by + * libpkix. + * + * PARAMETERS: + * "logger" + * Address of Logger to be added. 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 Logger 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_AddLogger( + PKIX_Logger *logger, + void *plContext); + +/* Functions pertaining to the PKIX_Error type */ + +/* Error + * + * An Error object is returned by a function upon encountering some error + * condition. Each Error is associated with an errorCode specified in pkixt.h. + * The remaining components of an Error are optional. An Error's description + * specifies a text message describing the Error. An Error's supplementary info + * specifies additional information that might be useful. Finally, an Error's + * cause specifies the underlying Error (if any) that resulted in this Error + * being returned, thereby allowing Errors to be chained so that an entire + * "error stack trace" can be represented. Once created, an Error is immutable. + * + * Note that the Error's supplementary info must be an Object (although any + * object type), allowing it to be reference-counted and allowing it to + * provide the standard Object functions (Equals, Hashcode, ToString, Compare, + * Duplicate). + * + * Errors are classified as either being fatal or non-fatal. If a function + * fails in an unrecoverable way, it returns an Error whose errorCode is + * PKIX_FATAL_ERROR. If such an error is encountered, the caller should + * not attempt to recover since something seriously wrong has happened + * (e.g. corrupted memory, memory finished, etc.). All other errorCodes + * are considered non-fatal errors and can be handled by the caller as they + * see fit. + */ + +/* + * FUNCTION: PKIX_Error_Create + * DESCRIPTION: + * + * Creates a new Error using the value of "errorCode", the Error pointed to by + * "cause" (if any), the Object pointed to by "info" (if any), and the String + * pointed to by "desc" and stores it at "pError". If any error occurs during + * error allocation, it will be returned without chaining, since new errors + * cannot be created. Once created, an Error is immutable. + * + * PARAMETERS: + * "errorCode" + * Value of error code. + * "cause" + * Address of Error representing error's cause. + * NULL if none or unspecified. + * "info" + * Address of Object representing error's supplementary information. + * NULL if none. + * "desc" + * Address of String representing error's description. NULL if none. + * "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_Error_Create( + PKIX_ERRORCLASS errClass, + PKIX_Error *cause, + PKIX_PL_Object *info, + PKIX_ERRORCODE errCode, + PKIX_Error **pError, + void *plContext); + +/* + * FUNCTION: PKIX_Error_GetErrorClass + * DESCRIPTION: + * + * Retrieves the error class of the Error pointed to by "error" and + * stores it at "pClass". Supported error codes are defined in pkixt.h. + * + * PARAMETERS: + * "error" + * Address of Error whose error code is desired. Must be non-NULL. + * "pClass" + * Address where PKIX_UInt32 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_Error_GetErrorClass( + PKIX_Error *error, + PKIX_ERRORCLASS *pClass, + void *plContext); + +/* + * FUNCTION: PKIX_Error_GetErrorCode + * DESCRIPTION: + * + * Retrieves the error code of the Error pointed to by "error" and + * stores it at "pCode". Supported error codes are defined in pkixt.h. + * + * PARAMETERS: + * "error" + * Address of Error whose error code is desired. Must be non-NULL. + * "pCode" + * Address where PKIX_UInt32 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_Error_GetErrorCode( + PKIX_Error *error, + PKIX_ERRORCODE *pCode, + void *plContext); + +/* + * FUNCTION: PKIX_Error_GetCause + * DESCRIPTION: + * + * Retrieves the cause of the Error pointed to by "error" and stores it at + * "pCause". If no cause was specified, NULL will be stored at "pCause". + * + * PARAMETERS: + * "error" + * Address of Error whose cause is desired. Must be non-NULL. + * "pCause" + * 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_Error_GetCause( + PKIX_Error *error, + PKIX_Error **pCause, + void *plContext); + +/* + * FUNCTION: PKIX_Error_GetSupplementaryInfo + * DESCRIPTION: + * + * Retrieves the supplementary info of the Error pointed to by "error" and + * stores it at "pInfo". + * + * PARAMETERS: + * "error" + * Address of Error whose info is desired. Must be non-NULL. + * "pInfo" + * Address where info 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_Error_GetSupplementaryInfo( + PKIX_Error *error, + PKIX_PL_Object **pInfo, + void *plContext); + +/* + * FUNCTION: PKIX_Error_GetDescription + * DESCRIPTION: + * + * Retrieves the description of the Error pointed to by "error" and stores it + * at "pDesc". If no description was specified, NULL will be stored at + * "pDesc". + * + * PARAMETERS: + * "error" + * Address of Error whose description is desired. Must be non-NULL. + * "pDesc" + * 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_Error_GetDescription( + PKIX_Error *error, + PKIX_PL_String **pDesc, + void *plContext); + +/* PKIX_List + * + * Represents a collection of items. NULL is considered a valid item. + */ + +/* + * FUNCTION: PKIX_List_Create + * DESCRIPTION: + * + * Creates a new List 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: + * "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. + */ +PKIX_Error * +PKIX_List_Create( + PKIX_List **pList, + void *plContext); + +/* + * FUNCTION: PKIX_List_SetImmutable + * DESCRIPTION: + * + * Sets the List pointed to by "list" to be immutable. If a caller tries to + * change a List after it has been marked immutable (i.e. by calling + * PKIX_List_AppendItem, PKIX_List_InsertItem, PKIX_List_SetItem, or + * PKIX_List_DeleteItem), an Error is returned. + * + * PARAMETERS: + * "list" + * Address of List to be marked immutable. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "list" + * (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_SetImmutable( + PKIX_List *list, + void *plContext); + +/* + * FUNCTION: PKIX_List_IsImmutable + * DESCRIPTION: + * + * Checks whether the List pointed to by "list" is immutable and stores + * the Boolean result at "pImmutable". If a caller tries to change a List + * after it has been marked immutable (i.e. by calling PKIX_List_AppendItem, + * PKIX_List_InsertItem, PKIX_List_SetItem, or PKIX_List_DeleteItem), an + * Error is returned. + * + * PARAMETERS: + * "list" + * Address of List whose immutability is to be determined. + * Must be non-NULL. + * "pImmutable" + * Address where PKIX_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 the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_List_IsImmutable( + PKIX_List *list, + PKIX_Boolean *pImmutable, + void *plContext); + +/* + * FUNCTION: PKIX_List_GetLength + * DESCRIPTION: + * + * Retrieves the length of the List pointed to by "list" and stores it at + * "pLength". + * + * PARAMETERS: + * "list" + * Address of List whose length is desired. Must be non-NULL. + * "pLength" + * Address where PKIX_UInt32 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. + */ +PKIX_Error * +PKIX_List_GetLength( + PKIX_List *list, + PKIX_UInt32 *pLength, + void *plContext); + +/* + * FUNCTION: PKIX_List_IsEmpty + * DESCRIPTION: + * + * Checks whether the List pointed to by "list" is empty and stores + * the Boolean result at "pEmpty". + * + * PARAMETERS: + * "list" + * Address of List whose emptiness is to be determined. Must be non-NULL. + * "pEmpty" + * Address where PKIX_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 the function succeeds. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +PKIX_List_IsEmpty( + PKIX_List *list, + PKIX_Boolean *pEmpty, + void *plContext); + +/* + * FUNCTION: PKIX_List_AppendItem + * DESCRIPTION: + * + * Appends the Object pointed to by "item" after the last non-NULL item in + * List pointed to by "list", if any. Note that a List may validly contain + * NULL items. Appending "c" into the List ("a", NULL, "b", NULL) will result + * in ("a", NULL, "b", "c"). + * + * PARAMETERS: + * "list" + * Address of List to append to. Must be non-NULL. + * "item" + * Address of new item to append. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "list" + * (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_AppendItem( + PKIX_List *list, + PKIX_PL_Object *item, + void *plContext); + +/* + * FUNCTION: PKIX_List_InsertItem + * DESCRIPTION: + * + * Inserts the Object pointed to by "item" into the List pointed to by "list" + * at the given "index". The index counts from zero and must be less than the + * List's length. Existing list entries at or after this index will be moved + * to the next highest index. + * + * XXX why not allow equal to length which would be equivalent to AppendItem? + * + * PARAMETERS: + * "list" + * Address of List to insert into. Must be non-NULL. + * "index" + * Position to insert into. Must be less than List's length. + * "item" + * Address of new item to append. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "list" + * (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_InsertItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext); + +/* + * FUNCTION: PKIX_List_GetItem + * DESCRIPTION: + * + * Copies the "list"'s item at "index" into "pItem". The index counts from + * zero and must be less than the list's length. Increments the reference + * count on the returned object, if non-NULL. + * + * PARAMETERS: + * "list" + * Address of List to get item from. Must be non-NULL. + * "index" + * Index of list to get item from. Must be less than List's length. + * "pItem" + * 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. + */ +PKIX_Error * +PKIX_List_GetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object **pItem, + void *plContext); + +/* + * FUNCTION: PKIX_List_SetItem + * DESCRIPTION: + * + * Sets the item at "index" of the List pointed to by "list" with the Object + * pointed to by "item". The index counts from zero and must be less than the + * List's length. The previous entry at this index will have its reference + * count decremented and the new entry will have its reference count + * incremented. + * + * PARAMETERS: + * "list" + * Address of List to modify. Must be non-NULL. + * "index" + * Position in List to set. Must be less than List's length. + * "item" + * Address of Object to set at "index". + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "list" + * (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_SetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext); + +/* + * FUNCTION: PKIX_List_DeleteItem + * + * Deletes the item at "index" from the List pointed to by "list". The index + * counts from zero and must be less than the List's length. Note that this + * function does not destroy the List. It simply decrements the reference + * count of the item at "index" in the List, deletes that item from the list + * and moves all subsequent entries to a lower index in the list. If there is + * only a single element in the List and that element is deleted, then the + * List will be empty. + * + * PARAMETERS: + * "list" + * Address of List to delete from. Must be non-NULL. + * "index" + * Position in List to delete. Must be less than List's length. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "list" + * (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_DeleteItem( + PKIX_List *list, + PKIX_UInt32 index, + void *plContext); + +/* + * FUNCTION: PKIX_List_ReverseList + * DESCRIPTION: + * + * Creates a new List whose elements are in the reverse order as the elements + * of the Object pointed to by "list" and stores the copy at "pReversedList". + * If "list" is empty, the new reversed List will be a copy of "list". + * Changes to the new object will not affect the original and vice versa. + * + * PARAMETERS: + * "list" + * Address of List whose elements are to be reversed. Must be non-NULL. + * "pReversedList" + * 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. + */ +PKIX_Error * +PKIX_List_ReverseList( + PKIX_List *list, + PKIX_List **pReversedList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_UTIL_H */ diff --git a/security/nss/lib/libpkix/include/pkixt.h b/security/nss/lib/libpkix/include/pkixt.h new file mode 100644 index 0000000000..71997f700b --- /dev/null +++ b/security/nss/lib/libpkix/include/pkixt.h @@ -0,0 +1,485 @@ +/* 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/. */ +/* + * This file defines the types in the libpkix API. + * XXX Maybe we should specify the API version number in all API header files + * + */ + +#ifndef _PKIXT_H +#define _PKIXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "secerr.h" + +/* Types + * + * This header file provides typedefs for the abstract types used by libpkix. + * It also provides several useful macros. + * + * Note that all these abstract types are typedef'd as opaque structures. This + * is intended to discourage the caller from looking at the contents directly, + * since the format of the contents may change from one version of the library + * to the next. Instead, callers should only access these types using the + * functions defined in the public header files. + * + * An instance of an abstract type defined in this file is called an "object" + * here, although C does not have real support for objects. + * + * Because C does not typically have automatic garbage collection, the caller + * is expected to release the reference to any object that they create or that + * is returned to them by a libpkix function. The caller should do this by + * using the PKIX_PL_Object_DecRef function. Note that the caller should not + * release the reference to an object if the object has been passed to a + * libpkix function and that function has not returned. + * + * Please refer to libpkix Programmer's Guide for more details. + */ + +/* Version + * + * These macros specify the major and minor version of the libpkix API defined + * by this header file. + */ + +#define PKIX_MAJOR_VERSION ((PKIX_UInt32) 0) +#define PKIX_MINOR_VERSION ((PKIX_UInt32) 3) + +/* Maximum minor version + * + * This macro is used to specify that the caller wants the largest minor + * version available. + */ + +#define PKIX_MAX_MINOR_VERSION ((PKIX_UInt32) 4000000000) + +/* Define Cert Store type for database access */ +#define PKIX_STORE_TYPE_NONE 0 +#define PKIX_STORE_TYPE_PK11 1 + +/* Portable Code (PC) data types + * + * These types are used to perform the primary operations of this library: + * building and validating chains of X.509 certificates. + */ + +typedef struct PKIX_ErrorStruct PKIX_Error; +typedef struct PKIX_ProcessingParamsStruct PKIX_ProcessingParams; +typedef struct PKIX_ValidateParamsStruct PKIX_ValidateParams; +typedef struct PKIX_ValidateResultStruct PKIX_ValidateResult; +typedef struct PKIX_ResourceLimitsStruct PKIX_ResourceLimits; +typedef struct PKIX_BuildResultStruct PKIX_BuildResult; +typedef struct PKIX_CertStoreStruct PKIX_CertStore; +typedef struct PKIX_CertChainCheckerStruct PKIX_CertChainChecker; +typedef struct PKIX_RevocationCheckerStruct PKIX_RevocationChecker; +typedef struct PKIX_CertSelectorStruct PKIX_CertSelector; +typedef struct PKIX_CRLSelectorStruct PKIX_CRLSelector; +typedef struct PKIX_ComCertSelParamsStruct PKIX_ComCertSelParams; +typedef struct PKIX_ComCRLSelParamsStruct PKIX_ComCRLSelParams; +typedef struct PKIX_TrustAnchorStruct PKIX_TrustAnchor; +typedef struct PKIX_PolicyNodeStruct PKIX_PolicyNode; +typedef struct PKIX_LoggerStruct PKIX_Logger; +typedef struct PKIX_ListStruct PKIX_List; +typedef struct PKIX_ForwardBuilderStateStruct PKIX_ForwardBuilderState; +typedef struct PKIX_DefaultRevocationCheckerStruct + PKIX_DefaultRevocationChecker; +typedef struct PKIX_VerifyNodeStruct PKIX_VerifyNode; + +/* Portability Layer (PL) data types + * + * These types are used are used as portable data types that are defined + * consistently across platforms + */ + +typedef struct PKIX_PL_NssContextStruct PKIX_PL_NssContext; +typedef struct PKIX_PL_ObjectStruct PKIX_PL_Object; +typedef struct PKIX_PL_ByteArrayStruct PKIX_PL_ByteArray; +typedef struct PKIX_PL_HashTableStruct PKIX_PL_HashTable; +typedef struct PKIX_PL_MutexStruct PKIX_PL_Mutex; +typedef struct PKIX_PL_RWLockStruct PKIX_PL_RWLock; +typedef struct PKIX_PL_MonitorLockStruct PKIX_PL_MonitorLock; +typedef struct PKIX_PL_BigIntStruct PKIX_PL_BigInt; +typedef struct PKIX_PL_StringStruct PKIX_PL_String; +typedef struct PKIX_PL_OIDStruct PKIX_PL_OID; +typedef struct PKIX_PL_CertStruct PKIX_PL_Cert; +typedef struct PKIX_PL_GeneralNameStruct PKIX_PL_GeneralName; +typedef struct PKIX_PL_X500NameStruct PKIX_PL_X500Name; +typedef struct PKIX_PL_PublicKeyStruct PKIX_PL_PublicKey; +typedef struct PKIX_PL_DateStruct PKIX_PL_Date; +typedef struct PKIX_PL_CertNameConstraintsStruct PKIX_PL_CertNameConstraints; +typedef struct PKIX_PL_CertBasicConstraintsStruct PKIX_PL_CertBasicConstraints; +typedef struct PKIX_PL_CertPoliciesStruct PKIX_PL_CertPolicies; +typedef struct PKIX_PL_CertPolicyInfoStruct PKIX_PL_CertPolicyInfo; +typedef struct PKIX_PL_CertPolicyQualifierStruct PKIX_PL_CertPolicyQualifier; +typedef struct PKIX_PL_CertPolicyMapStruct PKIX_PL_CertPolicyMap; +typedef struct PKIX_PL_CRLStruct PKIX_PL_CRL; +typedef struct PKIX_PL_CRLEntryStruct PKIX_PL_CRLEntry; +typedef struct PKIX_PL_CollectionCertStoreStruct PKIX_PL_CollectionCertStore; +typedef struct PKIX_PL_CollectionCertStoreContext + PKIX_PL_CollectionCertStoreContext; +typedef struct PKIX_PL_LdapCertStoreContext PKIX_PL_LdapCertStoreContext; +typedef struct PKIX_PL_LdapRequestStruct PKIX_PL_LdapRequest; +typedef struct PKIX_PL_LdapResponseStruct PKIX_PL_LdapResponse; +typedef struct PKIX_PL_LdapDefaultClientStruct PKIX_PL_LdapDefaultClient; +typedef struct PKIX_PL_SocketStruct PKIX_PL_Socket; +typedef struct PKIX_PL_InfoAccessStruct PKIX_PL_InfoAccess; +typedef struct PKIX_PL_AIAMgrStruct PKIX_PL_AIAMgr; +typedef struct PKIX_PL_OcspCertIDStruct PKIX_PL_OcspCertID; +typedef struct PKIX_PL_OcspRequestStruct PKIX_PL_OcspRequest; +typedef struct PKIX_PL_OcspResponseStruct PKIX_PL_OcspResponse; +typedef struct PKIX_PL_HttpClientStruct PKIX_PL_HttpClient; +typedef struct PKIX_PL_HttpDefaultClientStruct PKIX_PL_HttpDefaultClient; +typedef struct PKIX_PL_HttpCertStoreContextStruct PKIX_PL_HttpCertStoreContext; + +/* Primitive types + * + * In order to guarantee desired behavior as well as platform-independence, we + * typedef these types depending on the platform. XXX This needs more work! + */ + +/* XXX Try compiling these files (and maybe the whole libpkix-nss) on Win32. + * We don't know what type is at least 32 bits long. ISO C probably requires + * at least 32 bits for long. we could default to that and only list platforms + * where that's not true. + * + * #elif + * #error + * #endif + */ + +/* currently, int is 32 bits on all our supported platforms */ + +typedef unsigned int PKIX_UInt32; +typedef int PKIX_Int32; + +typedef int PKIX_Boolean; + +/* Object Types + * + * Every reference-counted PKIX_PL_Object is associated with an integer type. + */ +#define PKIX_TYPES \ + TYPEMACRO(AIAMGR), \ + TYPEMACRO(BASICCONSTRAINTSCHECKERSTATE), \ + TYPEMACRO(BIGINT), \ + TYPEMACRO(BUILDRESULT), \ + TYPEMACRO(BYTEARRAY), \ + TYPEMACRO(CERT), \ + TYPEMACRO(CERTBASICCONSTRAINTS), \ + TYPEMACRO(CERTCHAINCHECKER), \ + TYPEMACRO(CERTNAMECONSTRAINTS), \ + TYPEMACRO(CERTNAMECONSTRAINTSCHECKERSTATE), \ + TYPEMACRO(CERTPOLICYCHECKERSTATE), \ + TYPEMACRO(CERTPOLICYINFO), \ + TYPEMACRO(CERTPOLICYMAP), \ + TYPEMACRO(CERTPOLICYNODE), \ + TYPEMACRO(CERTPOLICYQUALIFIER), \ + TYPEMACRO(CERTSELECTOR), \ + TYPEMACRO(CERTSTORE), \ + TYPEMACRO(COLLECTIONCERTSTORECONTEXT), \ + TYPEMACRO(COMCERTSELPARAMS), \ + TYPEMACRO(COMCRLSELPARAMS), \ + TYPEMACRO(CRL), \ + TYPEMACRO(CRLDP), \ + TYPEMACRO(CRLENTRY), \ + TYPEMACRO(CRLSELECTOR), \ + TYPEMACRO(DATE), \ + TYPEMACRO(CRLCHECKER), \ + TYPEMACRO(EKUCHECKER), \ + TYPEMACRO(ERROR), \ + TYPEMACRO(FORWARDBUILDERSTATE), \ + TYPEMACRO(GENERALNAME), \ + TYPEMACRO(HASHTABLE), \ + TYPEMACRO(HTTPCERTSTORECONTEXT), \ + TYPEMACRO(HTTPDEFAULTCLIENT), \ + TYPEMACRO(INFOACCESS), \ + TYPEMACRO(LDAPDEFAULTCLIENT), \ + TYPEMACRO(LDAPREQUEST), \ + TYPEMACRO(LDAPRESPONSE), \ + TYPEMACRO(LIST), \ + TYPEMACRO(LOGGER), \ + TYPEMACRO(MONITORLOCK), \ + TYPEMACRO(MUTEX), \ + TYPEMACRO(OBJECT), \ + TYPEMACRO(OCSPCERTID), \ + TYPEMACRO(OCSPCHECKER), \ + TYPEMACRO(OCSPREQUEST), \ + TYPEMACRO(OCSPRESPONSE), \ + TYPEMACRO(OID), \ + TYPEMACRO(REVOCATIONCHECKER), \ + TYPEMACRO(PROCESSINGPARAMS), \ + TYPEMACRO(PUBLICKEY), \ + TYPEMACRO(RESOURCELIMITS), \ + TYPEMACRO(RWLOCK), \ + TYPEMACRO(SIGNATURECHECKERSTATE), \ + TYPEMACRO(SOCKET), \ + TYPEMACRO(STRING), \ + TYPEMACRO(TARGETCERTCHECKERSTATE), \ + TYPEMACRO(TRUSTANCHOR), \ + TYPEMACRO(VALIDATEPARAMS), \ + TYPEMACRO(VALIDATERESULT), \ + TYPEMACRO(VERIFYNODE), \ + TYPEMACRO(X500NAME) + +#define TYPEMACRO(type) PKIX_ ## type ## _TYPE + +typedef enum { /* Now invoke all those TYPEMACROs to assign the numbers */ + PKIX_TYPES, + PKIX_NUMTYPES /* This gets PKIX_NUMTYPES defined as the total number */ +} PKIX_TYPENUM; + + +#ifdef PKIX_USER_OBJECT_TYPE + +/* User Define Object Types + * + * User may define their own object types offset from PKIX_USER_OBJECT_TYPE + */ +#define PKIX_USER_OBJECT_TYPEBASE 1000 + +#endif /* PKIX_USER_OBJECT_TYPE */ + +/* Error Codes + * + * This list is used to define a set of PKIX_Error exception class numbers. + * ERRMACRO is redefined to produce a corresponding set of + * strings in the table "const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES]" in + * pkix_error.c. 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 in pkix_error.c with the value "MUTEX". + */ +#define PKIX_ERRORCLASSES \ + ERRMACRO(AIAMGR), \ + ERRMACRO(BASICCONSTRAINTSCHECKERSTATE), \ + ERRMACRO(BIGINT), \ + ERRMACRO(BUILD), \ + ERRMACRO(BUILDRESULT), \ + ERRMACRO(BYTEARRAY), \ + ERRMACRO(CERT), \ + ERRMACRO(CERTBASICCONSTRAINTS), \ + ERRMACRO(CERTCHAINCHECKER), \ + ERRMACRO(CERTNAMECONSTRAINTS), \ + ERRMACRO(CERTNAMECONSTRAINTSCHECKERSTATE), \ + ERRMACRO(CERTPOLICYCHECKERSTATE), \ + ERRMACRO(CERTPOLICYINFO), \ + ERRMACRO(CERTPOLICYMAP), \ + ERRMACRO(CERTPOLICYNODE), \ + ERRMACRO(CERTPOLICYQUALIFIER), \ + ERRMACRO(CERTSELECTOR), \ + ERRMACRO(CERTSTORE), \ + ERRMACRO(CERTVFYPKIX), \ + ERRMACRO(COLLECTIONCERTSTORECONTEXT), \ + ERRMACRO(COMCERTSELPARAMS), \ + ERRMACRO(COMCRLSELPARAMS), \ + ERRMACRO(CONTEXT), \ + ERRMACRO(CRL), \ + ERRMACRO(CRLDP), \ + ERRMACRO(CRLENTRY), \ + ERRMACRO(CRLSELECTOR), \ + ERRMACRO(CRLCHECKER), \ + ERRMACRO(DATE), \ + ERRMACRO(EKUCHECKER), \ + ERRMACRO(ERROR), \ + ERRMACRO(FATAL), \ + ERRMACRO(FORWARDBUILDERSTATE), \ + ERRMACRO(GENERALNAME), \ + ERRMACRO(HASHTABLE), \ + ERRMACRO(HTTPCERTSTORECONTEXT), \ + ERRMACRO(HTTPDEFAULTCLIENT), \ + ERRMACRO(INFOACCESS), \ + ERRMACRO(LDAPCLIENT), \ + ERRMACRO(LDAPDEFAULTCLIENT), \ + ERRMACRO(LDAPREQUEST), \ + ERRMACRO(LDAPRESPONSE), \ + ERRMACRO(LIFECYCLE), \ + ERRMACRO(LIST), \ + ERRMACRO(LOGGER), \ + ERRMACRO(MEM), \ + ERRMACRO(MONITORLOCK), \ + ERRMACRO(MUTEX), \ + ERRMACRO(OBJECT), \ + ERRMACRO(OCSPCERTID), \ + ERRMACRO(OCSPCHECKER), \ + ERRMACRO(OCSPREQUEST), \ + ERRMACRO(OCSPRESPONSE), \ + ERRMACRO(OID), \ + ERRMACRO(PROCESSINGPARAMS), \ + ERRMACRO(PUBLICKEY), \ + ERRMACRO(RESOURCELIMITS), \ + ERRMACRO(REVOCATIONMETHOD), \ + ERRMACRO(REVOCATIONCHECKER), \ + ERRMACRO(RWLOCK), \ + ERRMACRO(SIGNATURECHECKERSTATE), \ + ERRMACRO(SOCKET), \ + ERRMACRO(STRING), \ + ERRMACRO(TARGETCERTCHECKERSTATE), \ + ERRMACRO(TRUSTANCHOR), \ + ERRMACRO(USERDEFINEDMODULES), \ + ERRMACRO(VALIDATE), \ + ERRMACRO(VALIDATEPARAMS), \ + ERRMACRO(VALIDATERESULT), \ + ERRMACRO(VERIFYNODE), \ + ERRMACRO(X500NAME) + +#define ERRMACRO(type) PKIX_ ## type ## _ERROR + +typedef enum { /* Now invoke all those ERRMACROs to assign the numbers */ + PKIX_ERRORCLASSES, + PKIX_NUMERRORCLASSES /* This gets PKIX_NUMERRORCLASSES defined as the total number */ +} PKIX_ERRORCLASS; + +/* Now define error strings (for internationalization) */ + +#define PKIX_ERRORENTRY(name,desc,plerr) PKIX_ ## name + +/* Define all the error numbers */ +typedef enum { +#include "pkix_errorstrings.h" +, PKIX_NUMERRORCODES +} PKIX_ERRORCODE; + +extern const char * const PKIX_ErrorText[]; + +/* String Formats + * + * These formats specify supported encoding formats for Strings. + */ + +#define PKIX_ESCASCII 0 +#define PKIX_UTF8 1 +#define PKIX_UTF16 2 +#define PKIX_UTF8_NULL_TERM 3 +#define PKIX_ESCASCII_DEBUG 4 + +/* Name Types + * + * These types specify supported formats for GeneralNames. + */ + +#define PKIX_OTHER_NAME 1 +#define PKIX_RFC822_NAME 2 +#define PKIX_DNS_NAME 3 +#define PKIX_X400_ADDRESS 4 +#define PKIX_DIRECTORY_NAME 5 +#define PKIX_EDIPARTY_NAME 6 +#define PKIX_URI_NAME 7 +#define PKIX_IP_NAME 8 +#define PKIX_OID_NAME 9 + +/* Key Usages + * + * These types specify supported Key Usages + */ + +#define PKIX_DIGITAL_SIGNATURE 0x001 +#define PKIX_NON_REPUDIATION 0x002 +#define PKIX_KEY_ENCIPHERMENT 0x004 +#define PKIX_DATA_ENCIPHERMENT 0x008 +#define PKIX_KEY_AGREEMENT 0x010 +#define PKIX_KEY_CERT_SIGN 0x020 +#define PKIX_CRL_SIGN 0x040 +#define PKIX_ENCIPHER_ONLY 0x080 +#define PKIX_DECIPHER_ONLY 0x100 + +/* Reason Flags + * + * These macros specify supported Reason Flags + */ + +#define PKIX_UNUSED 0x001 +#define PKIX_KEY_COMPROMISE 0x002 +#define PKIX_CA_COMPROMISE 0x004 +#define PKIX_AFFILIATION_CHANGED 0x008 +#define PKIX_SUPERSEDED 0x010 +#define PKIX_CESSATION_OF_OPERATION 0x020 +#define PKIX_CERTIFICATE_HOLD 0x040 +#define PKIX_PRIVILEGE_WITHDRAWN 0x080 +#define PKIX_AA_COMPROMISE 0x100 + +/* Boolean values + * + * These macros specify the Boolean values of TRUE and FALSE + * XXX Is it the case that any non-zero value is actually considered TRUE + * and this is just a convenient mnemonic macro? + */ + +#define PKIX_TRUE ((PKIX_Boolean) 1) +#define PKIX_FALSE ((PKIX_Boolean) 0) + +/* + * Define constants for basic constraints selector + * (see comments in pkix_certsel.h) + */ + +#define PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH (-2) +#define PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH (-1) + +/* + * PKIX_ALLOC_ERROR is a special error object hard-coded into the pkix_error.o + * object file. It is thrown if system memory cannot be allocated or may be + * thrown for other unrecoverable errors. PKIX_ALLOC_ERROR is immutable. + * IncRef, DecRef and all Settor functions cannot be called. + * XXX Does anyone actually need to know about this? + * XXX Why no DecRef? Would be good to handle it the same. + */ + +PKIX_Error* PKIX_ALLOC_ERROR(void); + +/* + * In a CertBasicConstraints extension, if the CA flag is set, + * indicating the certificate refers to a Certification + * Authority, then the pathLen field indicates how many intermediate + * certificates (not counting self-signed ones) can exist in a valid + * chain following this certificate. If the pathLen has the value + * of this constant, then the length of the chain is unlimited + */ +#define PKIX_UNLIMITED_PATH_CONSTRAINT ((PKIX_Int32) -1) + +/* + * Define Certificate Extension hard-coded OID's + */ +#define PKIX_UNKNOWN_OID SEC_OID_UNKNOWN +#define PKIX_CERTKEYUSAGE_OID SEC_OID_X509_KEY_USAGE +#define PKIX_CERTSUBJALTNAME_OID SEC_OID_X509_SUBJECT_ALT_NAME +#define PKIX_BASICCONSTRAINTS_OID SEC_OID_X509_BASIC_CONSTRAINTS +#define PKIX_CRLREASONCODE_OID SEC_OID_X509_REASON_CODE +#define PKIX_NAMECONSTRAINTS_OID SEC_OID_X509_NAME_CONSTRAINTS +#define PKIX_CERTIFICATEPOLICIES_OID SEC_OID_X509_CERTIFICATE_POLICIES +#define PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID SEC_OID_X509_ANY_POLICY +#define PKIX_POLICYMAPPINGS_OID SEC_OID_X509_POLICY_MAPPINGS +#define PKIX_POLICYCONSTRAINTS_OID SEC_OID_X509_POLICY_CONSTRAINTS +#define PKIX_EXTENDEDKEYUSAGE_OID SEC_OID_X509_EXT_KEY_USAGE +#define PKIX_INHIBITANYPOLICY_OID SEC_OID_X509_INHIBIT_ANY_POLICY +#define PKIX_NSCERTTYPE_OID SEC_OID_NS_CERT_EXT_CERT_TYPE +#define PKIX_KEY_USAGE_SERVER_AUTH_OID SEC_OID_EXT_KEY_USAGE_SERVER_AUTH +#define PKIX_KEY_USAGE_CLIENT_AUTH_OID SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH +#define PKIX_KEY_USAGE_CODE_SIGN_OID SEC_OID_EXT_KEY_USAGE_CODE_SIGN +#define PKIX_KEY_USAGE_EMAIL_PROTECT_OID SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT +#define PKIX_KEY_USAGE_TIME_STAMP_OID SEC_OID_EXT_KEY_USAGE_TIME_STAMP +#define PKIX_KEY_USAGE_OCSP_RESPONDER_OID SEC_OID_OCSP_RESPONDER + + +/* Available revocation method types. */ +typedef enum PKIX_RevocationMethodTypeEnum { + PKIX_RevocationMethod_CRL = 0, + PKIX_RevocationMethod_OCSP, + PKIX_RevocationMethod_MAX +} PKIX_RevocationMethodType; + +/* A set of statuses revocation checker operates on */ +typedef enum PKIX_RevocationStatusEnum { + PKIX_RevStatus_NoInfo = 0, + PKIX_RevStatus_Revoked, + PKIX_RevStatus_Success +} PKIX_RevocationStatus; + + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIXT_H */ diff --git a/security/nss/lib/libpkix/libpkix.gyp b/security/nss/lib/libpkix/libpkix.gyp new file mode 100644 index 0000000000..ec6e006179 --- /dev/null +++ b/security/nss/lib/libpkix/libpkix.gyp @@ -0,0 +1,31 @@ +# 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': 'libpkix', + 'type': 'none', + 'conditions': [ + [ 'disable_libpkix==0', { + 'dependencies': [ + 'pkix/certsel/certsel.gyp:pkixcertsel', + 'pkix/checker/checker.gyp:pkixchecker', + 'pkix/crlsel/crlsel.gyp:pkixcrlsel', + 'pkix/params/params.gyp:pkixparams', + 'pkix/results/results.gyp:pkixresults', + 'pkix/store/store.gyp:pkixstore', + 'pkix/top/top.gyp:pkixtop', + 'pkix/util/util.gyp:pkixutil', + 'pkix_pl_nss/module/module.gyp:pkixmodule', + 'pkix_pl_nss/pki/pki.gyp:pkixpki', + 'pkix_pl_nss/system/system.gyp:pkixsystem', + ], + }], + ], + }, + ], +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/manifest.mn b/security/nss/lib/libpkix/manifest.mn new file mode 100644 index 0000000000..31990da63d --- /dev/null +++ b/security/nss/lib/libpkix/manifest.mn @@ -0,0 +1,13 @@ +# +# 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 = include pkix pkix_pl_nss \ + $(NULL) + +# This part of the code, including all sub-dirs, can be optimized for size +export ALLOW_OPT_CODE_SIZE = 1 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 diff --git a/security/nss/lib/libpkix/pkix_pl_nss/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/Makefile new file mode 100644 index 0000000000..2b5492506c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/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_pl_nss/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/manifest.mn new file mode 100644 index 0000000000..f3c83511a9 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/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 = pki system module \ + $(NULL) + diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile new file mode 100644 index 0000000000..e97ad8e4de --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile @@ -0,0 +1,66 @@ +#! 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). # +####################################################################### + +ifdef NSS_PKIX_NO_LDAP +LDAP_HEADERS = +LDAP_CSRCS = +else +LDAP_HEADERS = \ + pkix_pl_ldapt.h \ + pkix_pl_ldapcertstore.h \ + pkix_pl_ldapresponse.h \ + pkix_pl_ldaprequest.h \ + pkix_pl_ldapdefaultclient.h \ + $(NULL) + +LDAP_CSRCS = \ + pkix_pl_ldaptemplates.c \ + pkix_pl_ldapcertstore.c \ + pkix_pl_ldapresponse.c \ + pkix_pl_ldaprequest.c \ + pkix_pl_ldapdefaultclient.c \ + $(NULL) +endif + +####################################################################### +# (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_pl_nss/module/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp new file mode 100644 index 0000000000..064a17ce44 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp @@ -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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'lib_libpkix_pkix_pl_nss_module_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_pl_aiamgr.h', + 'pkix_pl_colcertstore.h', + 'pkix_pl_httpcertstore.h', + 'pkix_pl_httpdefaultclient.h', + 'pkix_pl_ldapcertstore.h', + 'pkix_pl_ldapdefaultclient.h', + 'pkix_pl_ldaprequest.h', + 'pkix_pl_ldapresponse.h', + 'pkix_pl_ldapt.h', + 'pkix_pl_nsscontext.h', + 'pkix_pl_pk11certstore.h', + 'pkix_pl_socket.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn new file mode 100644 index 0000000000..31231e4edf --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn @@ -0,0 +1,34 @@ +# +# 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_pl_aiamgr.h \ + pkix_pl_colcertstore.h \ + pkix_pl_httpcertstore.h \ + pkix_pl_httpdefaultclient.h \ + $(LDAP_HEADERS) \ + pkix_pl_nsscontext.h \ + pkix_pl_pk11certstore.h \ + pkix_pl_socket.h \ + $(NULL) + +MODULE = nss + +DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" + +CSRCS = \ + pkix_pl_aiamgr.c \ + pkix_pl_colcertstore.c \ + pkix_pl_httpcertstore.c \ + pkix_pl_httpdefaultclient.c \ + $(LDAP_CSRCS) \ + pkix_pl_nsscontext.c \ + pkix_pl_pk11certstore.c \ + pkix_pl_socket.c \ + $(NULL) + +LIBRARY_NAME = pkixmodule +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp b/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp new file mode 100644 index 0000000000..8d7459ded6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp @@ -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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'pkixmodule', + 'type': 'static_library', + 'sources': [ + 'pkix_pl_aiamgr.c', + 'pkix_pl_colcertstore.c', + 'pkix_pl_httpcertstore.c', + 'pkix_pl_httpdefaultclient.c', + 'pkix_pl_ldapcertstore.c', + 'pkix_pl_ldapdefaultclient.c', + 'pkix_pl_ldaprequest.c', + 'pkix_pl_ldapresponse.c', + 'pkix_pl_ldaptemplates.c', + 'pkix_pl_nsscontext.c', + 'pkix_pl_pk11certstore.c', + 'pkix_pl_socket.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'target_defaults': { + 'defines': [ + 'SHLIB_SUFFIX=\"<(dll_suffix)\"', + 'SHLIB_PREFIX=\"<(dll_prefix)\"', + 'SHLIB_VERSION=\"\"' + ] + }, + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c new file mode 100644 index 0000000000..d9f5662303 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c @@ -0,0 +1,699 @@ +/* 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_pl_aiamgr.c + * + * AIAMgr Object Definitions + * + */ + +#include "pkix_pl_aiamgr.h" +extern PKIX_PL_HashTable *aiaConnectionCache; + +#ifndef NSS_PKIX_NO_LDAP +/* --Virtual-LdapClient-Functions------------------------------------ */ + +PKIX_Error * +PKIX_PL_LdapClient_InitiateRequest( + PKIX_PL_LdapClient *client, + LDAPRequestParams *requestParams, + void **pNBIO, + PKIX_List **pResponse, + void *plContext) +{ + PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_InitiateRequest"); + PKIX_NULLCHECK_TWO(client, client->initiateFcn); + + PKIX_CHECK(client->initiateFcn + (client, requestParams, pNBIO, pResponse, plContext), + PKIX_LDAPCLIENTINITIATEREQUESTFAILED); +cleanup: + + PKIX_RETURN(LDAPCLIENT); + +} + +PKIX_Error * +PKIX_PL_LdapClient_ResumeRequest( + PKIX_PL_LdapClient *client, + void **pNBIO, + PKIX_List **pResponse, + void *plContext) +{ + PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_ResumeRequest"); + PKIX_NULLCHECK_TWO(client, client->resumeFcn); + + PKIX_CHECK(client->resumeFcn + (client, pNBIO, pResponse, plContext), + PKIX_LDAPCLIENTRESUMEREQUESTFAILED); +cleanup: + + PKIX_RETURN(LDAPCLIENT); + +} +#endif /* !NSS_PKIX_NO_LDAP */ + +/* --Private-AIAMgr-Functions----------------------------------*/ + +/* + * FUNCTION: pkix_pl_AIAMgr_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h) + */ +static PKIX_Error * +pkix_pl_AIAMgr_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_AIAMgr *aiaMgr = NULL; + + PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_AIAMGR_TYPE, plContext), + PKIX_OBJECTNOTAIAMGR); + + aiaMgr = (PKIX_PL_AIAMgr *)object; + + /* pointer to cert cache */ + /* pointer to crl cache */ + aiaMgr->method = 0; + aiaMgr->aiaIndex = 0; + aiaMgr->numAias = 0; + PKIX_DECREF(aiaMgr->aia); + PKIX_DECREF(aiaMgr->location); + PKIX_DECREF(aiaMgr->results); +#ifndef NSS_PKIX_NO_LDAP + PKIX_DECREF(aiaMgr->client.ldapClient); +#endif + +cleanup: + + PKIX_RETURN(AIAMGR); +} + +/* + * FUNCTION: pkix_pl_AIAMgr_RegisterSelf + * DESCRIPTION: + * Registers PKIX_AIAMGR_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_pl_AIAMgr_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_AIAMGR_TYPE]; + + PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_RegisterSelf"); + + entry->description = "AIAMgr"; + entry->typeObjectSize = sizeof(PKIX_PL_AIAMgr); + entry->destructor = pkix_pl_AIAMgr_Destroy; + + PKIX_RETURN(AIAMGR); +} + +#ifndef NSS_PKIX_NO_LDAP +/* + * FUNCTION: pkix_pl_AiaMgr_FindLDAPClient + * DESCRIPTION: + * + * This function checks the collection of LDAPClient connections held by the + * AIAMgr pointed to by "aiaMgr" for one matching the domain name given by + * "domainName". The string may include a port number: e.g., "betty.nist.gov" + * or "nss.red.iplanet.com:1389". If a match is found, that LDAPClient is + * stored at "pClient". Otherwise, an LDAPClient is created and added to the + * collection, and then stored at "pClient". + * + * PARAMETERS: + * "aiaMgr" + * The AIAMgr whose LDAPClient connected are to be managed. Must be + * non-NULL. + * "domainName" + * Address of a string pointing to a server name. Must be non-NULL. + * An empty string (which means no <host> is given in the LDAP URL) is + * not supported. + * "pClient" + * Address at which the returned LDAPClient 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 an AIAMgr 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_pl_AiaMgr_FindLDAPClient( + PKIX_PL_AIAMgr *aiaMgr, + char *domainName, + PKIX_PL_LdapClient **pClient, + void *plContext) +{ + PKIX_PL_String *domainString = NULL; + PKIX_PL_LdapDefaultClient *client = NULL; + + PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient"); + PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient); + + /* + * An LDAP URL may not have a <host> part, for example, + * ldap:///o=University%20of%20Michigan,c=US + * PKIX_PL_LdapDefaultClient doesn't know how to discover the default + * LDAP server, so we don't support this kind of LDAP URL. + */ + if (*domainName == '\0') { + /* Simulate a PKIX_PL_LdapDefaultClient_CreateByName failure. */ + PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED); + } + + /* create PKIX_PL_String from domain name */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, domainName, 0, &domainString, plContext), + PKIX_STRINGCREATEFAILED); + + /* Is this domainName already in cache? */ + PKIX_CHECK(PKIX_PL_HashTable_Lookup + (aiaConnectionCache, + (PKIX_PL_Object *)domainString, + (PKIX_PL_Object **)&client, + plContext), + PKIX_HASHTABLELOOKUPFAILED); + + if (client == NULL) { + + /* No, create a connection (and cache it) */ + PKIX_CHECK(PKIX_PL_LdapDefaultClient_CreateByName + (domainName, + /* Do not use NBIO until we verify, that + * it is working. For now use 1 min timeout. */ + PR_SecondsToInterval( + ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), + NULL, + &client, + plContext), + PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED); + + PKIX_CHECK(PKIX_PL_HashTable_Add + (aiaConnectionCache, + (PKIX_PL_Object *)domainString, + (PKIX_PL_Object *)client, + plContext), + PKIX_HASHTABLEADDFAILED); + + } + + *pClient = (PKIX_PL_LdapClient *)client; + +cleanup: + + PKIX_DECREF(domainString); + + PKIX_RETURN(AIAMGR); +} +#endif /* !NSS_PKIX_NO_LDAP */ + +PKIX_Error * +pkix_pl_AIAMgr_GetHTTPCerts( + PKIX_PL_AIAMgr *aiaMgr, + PKIX_PL_InfoAccess *ia, + void **pNBIOContext, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_PL_GeneralName *location = NULL; + PKIX_PL_String *locationString = NULL; + PKIX_UInt32 len = 0; + PRUint16 port = 0; + const SEC_HttpClientFcn *httpClient = NULL; + const SEC_HttpClientFcnV1 *hcv1 = NULL; + SECStatus rv = SECFailure; + SEC_HTTP_SERVER_SESSION serverSession = NULL; + SEC_HTTP_REQUEST_SESSION requestSession = NULL; + char *path = NULL; + char *hostname = NULL; + char *locationAscii = NULL; + void *nbio = NULL; + PRUint16 responseCode = 0; + const char *responseContentType = NULL; + const char *responseData = NULL; + + PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetHTTPCerts"); + PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts); + + nbio = *pNBIOContext; + *pNBIOContext = NULL; + *pCerts = NULL; + + if (nbio == NULL) { /* a new request */ + + PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation + (ia, &location, plContext), + PKIX_INFOACCESSGETLOCATIONFAILED); + + /* find or create httpClient = default client */ + httpClient = SEC_GetRegisteredHttpClient(); + aiaMgr->client.hdata.httpClient = httpClient; + if (!httpClient) + PKIX_ERROR(PKIX_OUTOFMEMORY); + + if (httpClient->version == 1) { + + PKIX_UInt32 timeout = + ((PKIX_PL_NssContext*)plContext)->timeoutSeconds; + + hcv1 = &(httpClient->fcnTable.ftable1); + + /* create server session */ + PKIX_TOSTRING(location, &locationString, plContext, + PKIX_GENERALNAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (locationString, + PKIX_ESCASCII, + (void **)&locationAscii, + &len, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + rv = CERT_ParseURL(locationAscii, &hostname, &port, + &path); + if ((rv != SECSuccess) || + (hostname == NULL) || + (path == NULL)) { + PKIX_ERROR(PKIX_URLPARSINGFAILED); + } + + rv = (*hcv1->createSessionFcn)(hostname, port, + &serverSession); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED); + } + + aiaMgr->client.hdata.serverSession = serverSession; + + /* create request session */ + rv = (*hcv1->createFcn)(serverSession, "http", path, + "GET", PR_SecondsToInterval(timeout), + &requestSession); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + aiaMgr->client.hdata.requestSession = requestSession; + } else { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + } + + httpClient = aiaMgr->client.hdata.httpClient; + + if (httpClient->version == 1) { + PRUint32 responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + hcv1 = &(httpClient->fcnTable.ftable1); + requestSession = aiaMgr->client.hdata.requestSession; + + /* trySendAndReceive */ + rv = (*hcv1->trySendAndReceiveFcn)(requestSession, + (PRPollDesc **)&nbio, + &responseCode, + (const char **)&responseContentType, + NULL, /* &responseHeaders */ + (const char **)&responseData, + &responseDataLen); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + if (nbio != 0) { + *pNBIOContext = nbio; + goto cleanup; + } + + PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse + (responseCode, + responseContentType, + responseData, + responseDataLen, + pCerts, + plContext), + PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); + + /* Session and request cleanup in case of success */ + if (aiaMgr->client.hdata.requestSession != NULL) { + (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession); + aiaMgr->client.hdata.requestSession = NULL; + } + if (aiaMgr->client.hdata.serverSession != NULL) { + (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession); + aiaMgr->client.hdata.serverSession = NULL; + } + aiaMgr->client.hdata.httpClient = 0; /* callback fn */ + + } else { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + +cleanup: + /* Session and request cleanup in case of error. Passing through without cleanup + * if interrupted by blocked IO. */ + if (PKIX_ERROR_RECEIVED) { + if (aiaMgr->client.hdata.requestSession != NULL) { + (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession); + aiaMgr->client.hdata.requestSession = NULL; + } + if (aiaMgr->client.hdata.serverSession != NULL) { + (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession); + aiaMgr->client.hdata.serverSession = NULL; + } + aiaMgr->client.hdata.httpClient = 0; /* callback fn */ + } + + PKIX_DECREF(location); + PKIX_DECREF(locationString); + + if (locationAscii) { + PORT_Free(locationAscii); + } + if (hostname) { + PORT_Free(hostname); + } + if (path) { + PORT_Free(path); + } + + PKIX_RETURN(AIAMGR); +} + +#ifndef NSS_PKIX_NO_LDAP +PKIX_Error * +pkix_pl_AIAMgr_GetLDAPCerts( + PKIX_PL_AIAMgr *aiaMgr, + PKIX_PL_InfoAccess *ia, + void **pNBIOContext, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_List *result = NULL; + PKIX_PL_GeneralName *location = NULL; + PKIX_PL_LdapClient *client = NULL; + LDAPRequestParams request; + PLArenaPool *arena = NULL; + char *domainName = NULL; + void *nbio = NULL; + + PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts"); + PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts); + + nbio = *pNBIOContext; + *pNBIOContext = NULL; + *pCerts = NULL; + + if (nbio == NULL) { /* a new request */ + + /* Initiate an LDAP request */ + + request.scope = WHOLE_SUBTREE; + request.derefAliases = NEVER_DEREF; + request.sizeLimit = 0; + request.timeLimit = 0; + + PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation + (ia, &location, plContext), + PKIX_INFOACCESSGETLOCATIONFAILED); + + /* + * Get a short-lived arena. We'll be done with + * this space once the request is encoded. + */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); + } + + PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation + (location, arena, &request, &domainName, plContext), + PKIX_INFOACCESSPARSELOCATIONFAILED); + + PKIX_DECREF(location); + + /* Find or create a connection to LDAP server */ + PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient + (aiaMgr, domainName, &client, plContext), + PKIX_AIAMGRFINDLDAPCLIENTFAILED); + + aiaMgr->client.ldapClient = client; + + PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest + (aiaMgr->client.ldapClient, + &request, + &nbio, + &result, + plContext), + PKIX_LDAPCLIENTINITIATEREQUESTFAILED); + + PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE)); + + } else { + + PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest + (aiaMgr->client.ldapClient, &nbio, &result, plContext), + PKIX_LDAPCLIENTRESUMEREQUESTFAILED); + + } + + if (nbio != NULL) { /* WOULDBLOCK */ + *pNBIOContext = nbio; + *pCerts = NULL; + goto cleanup; + } + + PKIX_DECREF(aiaMgr->client.ldapClient); + + if (result == NULL) { + *pCerts = NULL; + } else { + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList + (result, pCerts, plContext), + PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); + } + + *pNBIOContext = nbio; + +cleanup: + + if (arena && (PKIX_ERROR_RECEIVED)) { + PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE)); + } + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(aiaMgr->client.ldapClient); + } + + PKIX_DECREF(location); + + PKIX_RETURN(AIAMGR); +} +#endif /* !NSS_PKIX_NO_LDAP */ + +/* + * FUNCTION: PKIX_PL_AIAMgr_Create + * DESCRIPTION: + * + * This function creates an AIAMgr, storing the result at "pAIAMgr". + * + * PARAMETERS: + * "pAIAMGR" + * Address at which the returned AIAMgr 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 an AIAMgr 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_PL_AIAMgr_Create( + PKIX_PL_AIAMgr **pAIAMgr, + void *plContext) +{ + PKIX_PL_AIAMgr *aiaMgr = NULL; + + PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_Create"); + PKIX_NULLCHECK_ONE(pAIAMgr); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_AIAMGR_TYPE, + sizeof(PKIX_PL_AIAMgr), + (PKIX_PL_Object **)&aiaMgr, + plContext), + PKIX_COULDNOTCREATEAIAMGROBJECT); + /* pointer to cert cache */ + /* pointer to crl cache */ + aiaMgr->method = 0; + aiaMgr->aiaIndex = 0; + aiaMgr->numAias = 0; + aiaMgr->aia = NULL; + aiaMgr->location = NULL; + aiaMgr->results = NULL; + aiaMgr->client.hdata.httpClient = NULL; + aiaMgr->client.hdata.serverSession = NULL; + aiaMgr->client.hdata.requestSession = NULL; + + *pAIAMgr = aiaMgr; + +cleanup: + + PKIX_RETURN(AIAMGR); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts (see description in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_AIAMgr_GetAIACerts( + PKIX_PL_AIAMgr *aiaMgr, + PKIX_PL_Cert *prevCert, + void **pNBIOContext, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_UInt32 numAias = 0; + PKIX_UInt32 aiaIndex = 0; + PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN; + PKIX_List *certs = NULL; + PKIX_PL_InfoAccess *ia = NULL; + void *nbio = NULL; + + PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_GetAIACerts"); + PKIX_NULLCHECK_FOUR(aiaMgr, prevCert, pNBIOContext, pCerts); + + nbio = *pNBIOContext; + *pCerts = NULL; + *pNBIOContext = NULL; + + if (nbio == NULL) { /* a new request */ + + /* Does this Cert have an AIA extension? */ + PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess + (prevCert, &aiaMgr->aia, plContext), + PKIX_CERTGETAUTHORITYINFOACCESSFAILED); + + if (aiaMgr->aia != NULL) { + PKIX_CHECK(PKIX_List_GetLength + (aiaMgr->aia, &numAias, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + /* And if so, does it have any entries? */ + if ((aiaMgr->aia == NULL) || (numAias == 0)) { + *pCerts = NULL; + goto cleanup; + } + + aiaMgr->aiaIndex = 0; + aiaMgr->numAias = numAias; + aiaMgr->results = NULL; + + } + + for (aiaIndex = aiaMgr->aiaIndex; + aiaIndex < aiaMgr->numAias; + aiaIndex ++) { + PKIX_UInt32 method = 0; + + PKIX_CHECK(PKIX_List_GetItem + (aiaMgr->aia, + aiaIndex, + (PKIX_PL_Object **)&ia, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_InfoAccess_GetMethod + (ia, &method, plContext), + PKIX_INFOACCESSGETMETHODFAILED); + + if (method != PKIX_INFOACCESS_CA_ISSUERS && + method != PKIX_INFOACCESS_CA_REPOSITORY) { + PKIX_DECREF(ia); + continue; + } + + PKIX_CHECK(PKIX_PL_InfoAccess_GetLocationType + (ia, &iaType, plContext), + PKIX_INFOACCESSGETLOCATIONTYPEFAILED); + + if (iaType == PKIX_INFOACCESS_LOCATION_HTTP) { + PKIX_CHECK(pkix_pl_AIAMgr_GetHTTPCerts + (aiaMgr, ia, &nbio, &certs, plContext), + PKIX_AIAMGRGETHTTPCERTSFAILED); +#ifndef NSS_PKIX_NO_LDAP + } else if (iaType == PKIX_INFOACCESS_LOCATION_LDAP) { + PKIX_CHECK(pkix_pl_AIAMgr_GetLDAPCerts + (aiaMgr, ia, &nbio, &certs, plContext), + PKIX_AIAMGRGETLDAPCERTSFAILED); +#endif + } else { + /* We only support http and ldap requests. */ + PKIX_DECREF(ia); + continue; + } + + if (nbio != NULL) { /* WOULDBLOCK */ + aiaMgr->aiaIndex = aiaIndex; + *pNBIOContext = nbio; + *pCerts = NULL; + goto cleanup; + } + + /* + * We can't just use and modify the List we received. + * Because it's cached, it's set immutable. + */ + if (aiaMgr->results == NULL) { + PKIX_CHECK(PKIX_List_Create + (&(aiaMgr->results), plContext), + PKIX_LISTCREATEFAILED); + } + PKIX_CHECK(pkix_List_AppendList + (aiaMgr->results, certs, plContext), + PKIX_APPENDLISTFAILED); + PKIX_DECREF(certs); + + PKIX_DECREF(ia); + } + + PKIX_DECREF(aiaMgr->aia); + + *pNBIOContext = NULL; + *pCerts = aiaMgr->results; + aiaMgr->results = NULL; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(aiaMgr->aia); + PKIX_DECREF(aiaMgr->results); +#ifndef NSS_PKIX_NO_LDAP + PKIX_DECREF(aiaMgr->client.ldapClient); +#endif + } + + PKIX_DECREF(certs); + PKIX_DECREF(ia); + + PKIX_RETURN(AIAMGR); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h new file mode 100644 index 0000000000..356c1ecdf2 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h @@ -0,0 +1,65 @@ +/* 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_pl_aiamgr.h + * + * AIAMgr Object Definitions + * + */ + +#ifndef _PKIX_PL_AIAMGR_H +#define _PKIX_PL_AIAMGR_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_AIAMgrStruct { + /* pointer to cert cache */ + /* pointer to crl cache */ + PKIX_UInt32 method; + PKIX_UInt32 aiaIndex; + PKIX_UInt32 numAias; + PKIX_List *aia; + PKIX_PL_GeneralName *location; + PKIX_List *results; + union { +#ifndef NSS_PKIX_NO_LDAP + PKIX_PL_LdapClient *ldapClient; +#endif + struct { + const SEC_HttpClientFcn *httpClient; + SEC_HTTP_SERVER_SESSION serverSession; + SEC_HTTP_REQUEST_SESSION requestSession; + char *path; + } hdata; + } client; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_AIAMgr_RegisterSelf(void *plContext); + +#ifndef NSS_PKIX_NO_LDAP +PKIX_Error *PKIX_PL_LdapClient_InitiateRequest( + PKIX_PL_LdapClient *client, + LDAPRequestParams *requestParams, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext); + +PKIX_Error *PKIX_PL_LdapClient_ResumeRequest( + PKIX_PL_LdapClient *client, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext); +#endif /* !NSS_PKIX_NO_LDAP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_AIAMGR_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c new file mode 100644 index 0000000000..4cc5607cf6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c @@ -0,0 +1,1292 @@ +/* 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_pl_colcertstore.c + * + * CollectionCertStore Function Definitions + * + */ + +#include "pkix_pl_colcertstore.h" + +/* + * This Object is going to be taken out from libpkix SOON. The following + * function is copied from nss/cmd library, but not supported by NSS as + * public API. We use it since ColCertStore are read in Cert/Crl from + * files and need this support. + */ + +static SECStatus +SECU_FileToItem(SECItem *dst, PRFileDesc *src) +{ + PRFileInfo info; + PRInt32 numBytes; + PRStatus prStatus; + + prStatus = PR_GetOpenFileInfo(src, &info); + + if (prStatus != PR_SUCCESS) { + PORT_SetError(SEC_ERROR_IO); + return SECFailure; + } + + /* XXX workaround for 3.1, not all utils zero dst before sending */ + dst->data = 0; + if (!SECITEM_AllocItem(NULL, dst, info.size)) + goto loser; + + numBytes = PR_Read(src, dst->data, info.size); + if (numBytes != info.size) { + PORT_SetError(SEC_ERROR_IO); + goto loser; + } + + return SECSuccess; +loser: + SECITEM_FreeItem(dst, PR_FALSE); + return SECFailure; +} + +static SECStatus +SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) +{ + SECStatus rv; + if (ascii) { + /* First convert ascii to binary */ + SECItem filedata; + + /* Read in ascii data */ + rv = SECU_FileToItem(&filedata, inFile); + if (rv != SECSuccess) { + return rv; + } + if (!filedata.data) { + fprintf(stderr, "unable to read data from input file\n"); + return SECFailure; + } + /* need one additional byte for zero terminator */ + rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len + 1); + if (rv != SECSuccess) { + PORT_Free(filedata.data); + return rv; + } + char *asc = (char *)filedata.data; + asc[filedata.len - 1] = '\0'; + + char *body; + /* check for headers and trailers and remove them */ + if ((body = strstr(asc, "-----BEGIN")) != NULL) { + char *trailer = NULL; + asc = body; + body = PORT_Strchr(body, '\n'); + if (!body) + body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ + if (body) + trailer = strstr(++body, "-----END"); + if (trailer != NULL) { + *trailer = '\0'; + } else { + fprintf(stderr, "input has header but no trailer\n"); + PORT_Free(filedata.data); + return SECFailure; + } + } else { + body = asc; + } + + /* Convert to binary */ + rv = ATOB_ConvertAsciiToItem(der, body); + if (rv) { + return SECFailure; + } + + PORT_Free(filedata.data); + } else { + /* Read in binary der */ + rv = SECU_FileToItem(der, inFile); + if (rv) { + return SECFailure; + } + } + return SECSuccess; +} + +/* + * FUNCTION: PKIX_PL_CollectionCertStoreContext_Create + * DESCRIPTION: + * + * Creates a new CollectionCertStoreContext using the String pointed to + * by "storeDir" and stores it at "pColCertStoreContext". + * + * PARAMETERS: + * "storeDir" + * The absolute path where *.crl and *.crt files are located. + * "pColCertStoreContext" + * 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 CollectionCertStoreContext 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_pl_CollectionCertStoreContext_Create( + PKIX_PL_String *storeDir, + PKIX_PL_CollectionCertStoreContext **pColCertStoreContext, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_Create"); + PKIX_NULLCHECK_TWO(storeDir, pColCertStoreContext); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, + sizeof (PKIX_PL_CollectionCertStoreContext), + (PKIX_PL_Object **)&colCertStoreContext, + plContext), + PKIX_COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT); + + PKIX_INCREF(storeDir); + colCertStoreContext->storeDir = storeDir; + + colCertStoreContext->crlList = NULL; + colCertStoreContext->certList = NULL; + + *pColCertStoreContext = colCertStoreContext; + colCertStoreContext = NULL; + +cleanup: + + PKIX_DECREF(colCertStoreContext); + + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CollectionCertStoreContext_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, plContext), + PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT); + + colCertStoreContext = (PKIX_PL_CollectionCertStoreContext *)object; + + PKIX_DECREF(colCertStoreContext->storeDir); + PKIX_DECREF(colCertStoreContext->crlList); + PKIX_DECREF(colCertStoreContext->certList); + +cleanup: + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CollectionCertStoreContext_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *collectionCSContext = NULL; + PKIX_UInt32 tempHash = 0; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, + PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, + plContext), + PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT); + + collectionCSContext = (PKIX_PL_CollectionCertStoreContext *)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *) collectionCSContext->storeDir, + &tempHash, + plContext), + PKIX_STRINGHASHCODEFAILED); + + *pHashcode = tempHash << 7; + + /* should not hash on crlList and certList, values are dynamic */ + +cleanup: + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CollectionCertStoreContext_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *firstCCSContext = NULL; + PKIX_PL_CollectionCertStoreContext *secondCCSContext = NULL; + PKIX_Boolean cmpResult = 0; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, + secondObject, + PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, + plContext), + PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT); + + firstCCSContext = (PKIX_PL_CollectionCertStoreContext *)firstObject; + secondCCSContext = (PKIX_PL_CollectionCertStoreContext *)secondObject; + + if (firstCCSContext->storeDir == secondCCSContext->storeDir) { + + cmpResult = PKIX_TRUE; + + } else { + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *) firstCCSContext->storeDir, + (PKIX_PL_Object *) secondCCSContext->storeDir, + &cmpResult, + plContext), + PKIX_STRINGEQUALSFAILED); + } + + *pResult = cmpResult; + + /* should not check equal on crlList and certList, data are dynamic */ + +cleanup: + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStore_CheckTrust + * DESCRIPTION: + * This function checks the trust status of this "cert" that was retrieved + * from the CertStore "store" and returns its trust status at "pTrusted". + * + * PARAMETERS: + * "store" + * Address of the CertStore. Must be non-NULL. + * "cert" + * Address of the Cert. Must be non-NULL. + * "pTrusted" + * Address of PKIX_Boolean where the "cert" trust status 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 CertStore 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_pl_CollectionCertStore_CheckTrust( + PKIX_CertStore *store, + PKIX_PL_Cert *cert, + PKIX_Boolean *pTrusted, + void *plContext) +{ + PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_CheckTrust"); + PKIX_NULLCHECK_THREE(store, cert, pTrusted); + + *pTrusted = PKIX_TRUE; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_CreateCert + * DESCRIPTION: + * + * Creates Cert using data file path name pointed to by "certFileName" and + * stores it at "pCert". If the Cert can not be decoded, NULL is stored + * at "pCert". + * + * PARAMETERS + * "certFileName" - Address of Cert data file path name. Must be non-NULL. + * "pCert" - 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 CollectionCertStoreContext 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_pl_CollectionCertStoreContext_CreateCert( + const char *certFileName, + PKIX_PL_Cert **pCert, + void *plContext) +{ + PKIX_PL_ByteArray *byteArray = NULL; + PKIX_PL_Cert *cert = NULL; + PRFileDesc *inFile = NULL; + SECItem certDER; + void *buf = NULL; + PKIX_UInt32 len; + SECStatus rv; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_CreateCert"); + PKIX_NULLCHECK_TWO(certFileName, pCert); + + *pCert = NULL; + certDER.data = NULL; + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_Open.\n"); + inFile = PR_Open(certFileName, PR_RDONLY, 0); + + if (!inFile){ + PKIX_ERROR(PKIX_UNABLETOOPENCERTFILE); + } else { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECU_ReadDerFromFile.\n"); + rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); + if (!rv){ + buf = (void *)certDER.data; + len = certDER.len; + + PKIX_CHECK(PKIX_PL_ByteArray_Create + (buf, len, &byteArray, plContext), + PKIX_BYTEARRAYCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Cert_Create + (byteArray, &cert, plContext), + PKIX_CERTCREATEFAILED); + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECITEM_FreeItem.\n"); + SECITEM_FreeItem(&certDER, PR_FALSE); + + } else { + PKIX_ERROR(PKIX_UNABLETOREADDERFROMCERTFILE); + } + } + + *pCert = cert; + +cleanup: + if (inFile){ + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_CloseDir.\n"); + PR_Close(inFile); + } + + if (PKIX_ERROR_RECEIVED){ + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&certDER, PR_FALSE); + + PKIX_DECREF(cert); + } + PKIX_DECREF(byteArray); + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_CreateCRL + * DESCRIPTION: + * + * Creates CRL using data file path name pointed to by "crlFileName" and + * stores it at "pCrl". If the CRL can not be decoded, NULL is stored + * at "pCrl". + * + * PARAMETERS + * "crlFileName" - Address of CRL data file path name. Must be non-NULL. + * "pCrl" - 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 CollectionCertStoreContext 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_pl_CollectionCertStoreContext_CreateCRL( + const char *crlFileName, + PKIX_PL_CRL **pCrl, + void *plContext) +{ + PKIX_PL_ByteArray *byteArray = NULL; + PKIX_PL_CRL *crl = NULL; + PRFileDesc *inFile = NULL; + SECItem crlDER; + void *buf = NULL; + PKIX_UInt32 len; + SECStatus rv; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_CreateCRL"); + PKIX_NULLCHECK_TWO(crlFileName, pCrl); + + *pCrl = NULL; + crlDER.data = NULL; + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_Open.\n"); + inFile = PR_Open(crlFileName, PR_RDONLY, 0); + + if (!inFile){ + PKIX_ERROR(PKIX_UNABLETOOPENCRLFILE); + } else { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECU_ReadDerFromFile.\n"); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + if (!rv){ + buf = (void *)crlDER.data; + len = crlDER.len; + + PKIX_CHECK(PKIX_PL_ByteArray_Create + (buf, len, &byteArray, plContext), + PKIX_BYTEARRAYCREATEFAILED); + + PKIX_CHECK(PKIX_PL_CRL_Create + (byteArray, &crl, plContext), + PKIX_CRLCREATEFAILED); + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECITEM_FreeItem.\n"); + SECITEM_FreeItem(&crlDER, PR_FALSE); + + } else { + PKIX_ERROR(PKIX_UNABLETOREADDERFROMCRLFILE); + } + } + + *pCrl = crl; + +cleanup: + if (inFile){ + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_CloseDir.\n"); + PR_Close(inFile); + } + + if (PKIX_ERROR_RECEIVED){ + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&crlDER, PR_FALSE); + + PKIX_DECREF(crl); + if (crlDER.data != NULL) { + SECITEM_FreeItem(&crlDER, PR_FALSE); + } + } + + PKIX_DECREF(byteArray); + + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCert + * DESCRIPTION: + * + * Create list of Certs from *.crt files at directory specified in dirName, + * Not recursive to sub-directory. Also assume the directory contents are + * not changed dynamically. + * + * PARAMETERS + * "colCertStoreContext" - Address of CollectionCertStoreContext + * where the dirName is specified and where the return + * Certs are stored as a list. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe - A lock at top level is required. + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CollectionCertStoreContext 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_pl_CollectionCertStoreContext_PopulateCert( + PKIX_PL_CollectionCertStoreContext *colCertStoreContext, + void *plContext) +{ + PKIX_List *certList = NULL; + PKIX_PL_Cert *certItem = NULL; + char *dirName = NULL; + char *pathName = NULL; + PKIX_UInt32 dirNameLen = 0; + PRErrorCode prError = 0; + PRDir *dir = NULL; + PRDirEntry *dirEntry = NULL; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_PopulateCert"); + PKIX_NULLCHECK_ONE(colCertStoreContext); + + /* convert directory to ascii */ + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (colCertStoreContext->storeDir, + PKIX_ESCASCII, + (void **)&dirName, + &dirNameLen, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + /* create cert list, if no cert file, should return an empty list */ + + PKIX_CHECK(PKIX_List_Create(&certList, plContext), + PKIX_LISTCREATEFAILED); + + /* open directory and read in .crt files */ + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n"); + dir = PR_OpenDir(dirName); + + if (!dir) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG + ("\t\t Directory Name:%s\n", dirName); + PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n"); + dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); + + if (!dirEntry) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Empty directory.\n"); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_GetError.\n"); + prError = PR_GetError(); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n"); + PR_SetError(0, 0); + + while (dirEntry != NULL && prError == 0) { + if (PL_strrstr(dirEntry->name, ".crt") == + dirEntry->name + PL_strlen(dirEntry->name) - 4) { + + PKIX_CHECK_ONLY_FATAL + (PKIX_PL_Malloc + (dirNameLen + PL_strlen(dirEntry->name) + 2, + (void **)&pathName, + plContext), + PKIX_MALLOCFAILED); + + if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){ + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcpy for dirName.\n"); + PL_strcpy(pathName, dirName); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcat for dirName.\n"); + PL_strcat(pathName, "/"); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcat for /.\n"); + PL_strcat(pathName, dirEntry->name); + + PKIX_CHECK_ONLY_FATAL + (pkix_pl_CollectionCertStoreContext_CreateCert + (pathName, &certItem, plContext), + PKIX_COLLECTIONCERTSTORECONTEXTCREATECERTFAILED); + + if (!PKIX_ERROR_RECEIVED){ + PKIX_CHECK_ONLY_FATAL + (PKIX_List_AppendItem + (certList, + (PKIX_PL_Object *)certItem, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + } + + PKIX_DECREF(certItem); + PKIX_FREE(pathName); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_SetError.\n"); + PR_SetError(0, 0); + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_ReadDir.\n"); + dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); + + if (!dirEntry) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_GetError.\n"); + prError = PR_GetError(); + } + } + + if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) { + PKIX_ERROR(PKIX_COLLECTIONCERTSTOREPOPULATECERTFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(certList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + PKIX_INCREF(certList); + colCertStoreContext->certList = certList; + +cleanup: + if (dir) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_CloseDir.\n"); + PR_CloseDir(dir); + } + + PKIX_FREE(pathName); + PKIX_FREE(dirName); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(certList); + } + + PKIX_DECREF(certItem); + PKIX_DECREF(certList); + + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCRL + * DESCRIPTION: + * + * Create list of CRLs from *.crl files at directory specified in dirName, + * Not recursive to sub-dirctory. Also assume the directory contents are + * not changed dynamically. + * + * PARAMETERS + * "colCertStoreContext" - Address of CollectionCertStoreContext + * where the dirName is specified and where the return + * CRLs are stored as a list. Must be non-NULL. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe - A lock at top level is required. + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CollectionCertStoreContext 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_pl_CollectionCertStoreContext_PopulateCRL( + PKIX_PL_CollectionCertStoreContext *colCertStoreContext, + void *plContext) +{ + PKIX_List *crlList = NULL; + PKIX_PL_CRL *crlItem = NULL; + char *dirName = NULL; + char *pathName = NULL; + PKIX_UInt32 dirNameLen = 0; + PRErrorCode prError = 0; + PRDir *dir = NULL; + PRDirEntry *dirEntry = NULL; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_PopulateCRL"); + PKIX_NULLCHECK_ONE(colCertStoreContext); + + /* convert directory to ascii */ + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (colCertStoreContext->storeDir, + PKIX_ESCASCII, + (void **)&dirName, + &dirNameLen, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + /* create CRL list, if no CRL file, should return an empty list */ + + PKIX_CHECK(PKIX_List_Create(&crlList, plContext), + PKIX_LISTCREATEFAILED); + + /* open directory and read in .crl files */ + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n"); + dir = PR_OpenDir(dirName); + + if (!dir) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG + ("\t\t Directory Name:%s\n", dirName); + PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n"); + dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); + + if (!dirEntry) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Empty directory.\n"); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_GetError.\n"); + prError = PR_GetError(); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n"); + PR_SetError(0, 0); + + while (dirEntry != NULL && prError == 0) { + if (PL_strrstr(dirEntry->name, ".crl") == + dirEntry->name + PL_strlen(dirEntry->name) - 4) { + + PKIX_CHECK_ONLY_FATAL + (PKIX_PL_Malloc + (dirNameLen + PL_strlen(dirEntry->name) + 2, + (void **)&pathName, + plContext), + PKIX_MALLOCFAILED); + + if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){ + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcpy for dirName.\n"); + PL_strcpy(pathName, dirName); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcat for dirName.\n"); + PL_strcat(pathName, "/"); + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PL_strcat for /.\n"); + PL_strcat(pathName, dirEntry->name); + + PKIX_CHECK_ONLY_FATAL + (pkix_pl_CollectionCertStoreContext_CreateCRL + (pathName, &crlItem, plContext), + PKIX_COLLECTIONCERTSTORECONTEXTCREATECRLFAILED); + + if (!PKIX_ERROR_RECEIVED){ + PKIX_CHECK_ONLY_FATAL + (PKIX_List_AppendItem + (crlList, + (PKIX_PL_Object *)crlItem, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + } + + PKIX_DECREF(crlItem); + PKIX_FREE(pathName); + } + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_SetError.\n"); + PR_SetError(0, 0); + + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_ReadDir.\n"); + dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH); + + if (!dirEntry) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_GetError.\n"); + prError = PR_GetError(); + } + } + + if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) { + PKIX_ERROR(PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED); + } + + PKIX_CHECK(PKIX_List_SetImmutable(crlList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + PKIX_INCREF(crlList); + colCertStoreContext->crlList = crlList; + +cleanup: + if (dir) { + PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG + ("\t\t Calling PR_CloseDir.\n"); + PR_CloseDir(dir); + } + + PKIX_FREE(pathName); + PKIX_FREE(dirName); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(crlList); + } + + PKIX_DECREF(crlItem); + PKIX_DECREF(crlList); + + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_GetSelectedCert + * DESCRIPTION: + * + * Finds the Certs that match the criterion of the CertSelector pointed + * to by "selector" using the List of Certs pointed to by "certList" and + * stores the matching Certs at "pSelectedCertList". + * + * Not recursive to sub-directory. + * + * PARAMETERS + * "certList" - Address of List of Certs to be searched. Must be non-NULL. + * "colCertStoreContext" - Address of CollectionCertStoreContext + * where the cached Certs are stored. + * "selector" - CertSelector for chosing Cert based on Params set + * "pSelectedCertList" - Certs that qualified by selector. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe - A lock at top level is required. + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CollectionCertStoreContext 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_pl_CollectionCertStoreContext_GetSelectedCert( + PKIX_List *certList, + PKIX_CertSelector *selector, + PKIX_List **pSelectedCertList, + void *plContext) +{ + PKIX_List *selectCertList = NULL; + PKIX_PL_Cert *certItem = NULL; + PKIX_CertSelector_MatchCallback certSelectorMatch = NULL; + PKIX_UInt32 numCerts = 0; + PKIX_UInt32 i = 0; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_GetSelectedCert"); + PKIX_NULLCHECK_THREE(certList, selector, pSelectedCertList); + + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (selector, &certSelectorMatch, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + PKIX_CHECK(PKIX_List_GetLength(certList, &numCerts, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (certSelectorMatch) { + + PKIX_CHECK(PKIX_List_Create(&selectCertList, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; i < numCerts; i++) { + PKIX_CHECK_ONLY_FATAL + (PKIX_List_GetItem + (certList, + i, + (PKIX_PL_Object **) &certItem, + plContext), + PKIX_LISTGETITEMFAILED); + + if (!PKIX_ERROR_RECEIVED){ + PKIX_CHECK_ONLY_FATAL + (certSelectorMatch + (selector, certItem, plContext), + PKIX_CERTSELECTORMATCHFAILED); + + if (!PKIX_ERROR_RECEIVED){ + PKIX_CHECK_ONLY_FATAL + (PKIX_List_AppendItem + (selectCertList, + (PKIX_PL_Object *)certItem, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + } + + PKIX_DECREF(certItem); + } + + } else { + + PKIX_INCREF(certList); + + selectCertList = certList; + } + + *pSelectedCertList = selectCertList; + +cleanup: + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_GetSelectedCRL + * DESCRIPTION: + * + * Finds the CRLs that match the criterion of the CRLSelector pointed + * to by "selector" using the List of CRLs pointed to by "crlList" and + * stores the matching CRLs at "pSelectedCrlList". + * + * Not recursive to sub-directory. + * + * PARAMETERS + * "crlList" - Address of List of CRLs to be searched. Must be non-NULL + * "selector" - CRLSelector for chosing CRL based on Params set + * "pSelectedCrlList" - CRLs that qualified by selector. + * "plContext" - Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe - A lock at top level is required. + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CollectionCertStoreContext 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_pl_CollectionCertStoreContext_GetSelectedCRL( + PKIX_List *crlList, + PKIX_CRLSelector *selector, + PKIX_List **pSelectedCrlList, + void *plContext) +{ + PKIX_List *selectCrlList = NULL; + PKIX_PL_CRL *crlItem = NULL; + PKIX_CRLSelector_MatchCallback crlSelectorMatch = NULL; + PKIX_UInt32 numCrls = 0; + PKIX_UInt32 i = 0; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_GetSelectedCRL"); + PKIX_NULLCHECK_THREE(crlList, selector, pSelectedCrlList); + + PKIX_CHECK(PKIX_CRLSelector_GetMatchCallback + (selector, &crlSelectorMatch, plContext), + PKIX_CRLSELECTORGETMATCHCALLBACKFAILED); + + PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (crlSelectorMatch) { + + PKIX_CHECK(PKIX_List_Create(&selectCrlList, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; i < numCrls; i++) { + PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem + (crlList, + i, + (PKIX_PL_Object **) &crlItem, + plContext), + PKIX_LISTGETITEMFAILED); + + if (!PKIX_ERROR_RECEIVED){ + PKIX_CHECK_ONLY_FATAL + (crlSelectorMatch + (selector, crlItem, &match, plContext), + PKIX_CRLSELECTORMATCHFAILED); + + if (!(PKIX_ERROR_RECEIVED) && match) { + PKIX_CHECK_ONLY_FATAL + (PKIX_List_AppendItem + (selectCrlList, + (PKIX_PL_Object *)crlItem, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + } + + PKIX_DECREF(crlItem); + } + } else { + + PKIX_INCREF(crlList); + + selectCrlList = crlList; + } + + /* Don't throw away the list if one CRL was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pSelectedCrlList = selectCrlList; + +cleanup: + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStore_GetCert + * DESCRIPTION: + * + * Retrieve Certs in a list of PKIX_PL_Cert object. + * + * PARAMETERS: + * "colCertStoreContext" + * The object CertStore is the object passed in by checker call. + * "crlSelector" + * CRLSelector specifies criteria for chosing CRL's + * "pNBIOContext" + * Address where platform-dependent information is returned for CertStores + * that use non-blocking I/O. Must be non-NULL. + * "pCertList" + * Address where object pointer will be 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 CertStore 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_pl_CollectionCertStore_GetCert( + PKIX_CertStore *certStore, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; + PKIX_List *selectedCerts = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_GetCert"); + PKIX_NULLCHECK_FOUR(certStore, selector, pNBIOContext, pCerts); + + *pNBIOContext = NULL; /* We don't use non-blocking I/O */ + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (certStore, + (PKIX_PL_Object **) &colCertStoreContext, + plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (colCertStoreContext->certList == NULL) { + + PKIX_OBJECT_LOCK(colCertStoreContext); + + /* + * Certs in the directory are cached based on the + * assumption that the directory contents won't be + * changed dynamically. + */ + if (colCertStoreContext->certList == NULL){ + PKIX_CHECK(pkix_pl_CollectionCertStoreContext_PopulateCert + (colCertStoreContext, plContext), + PKIX_COLLECTIONCERTSTORECONTEXTPOPULATECERTFAILED); + } + + PKIX_OBJECT_UNLOCK(colCertStoreContext); + } + + PKIX_CHECK(pkix_pl_CollectionCertStoreContext_GetSelectedCert + (colCertStoreContext->certList, + selector, + &selectedCerts, + plContext), + PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCERTFAILED); + + *pCerts = selectedCerts; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_DECREF(colCertStoreContext); + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStore_GetCRL + * DESCRIPTION: + * + * Retrieve CRL's in a list of PKIX_PL_CRL object. + * + * PARAMETERS: + * "colCertStoreContext" + * The object CertStore is passed in by checker call. + * "crlSelector" + * CRLSelector specifies criteria for chosing CRL's + * "pNBIOContext" + * Address where platform-dependent information is returned for CertStores + * that use non-blocking I/O. Must be non-NULL. + * "pCrlList" + * Address where object pointer will be 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 CertStore 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_pl_CollectionCertStore_GetCRL( + PKIX_CertStore *certStore, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; + PKIX_List *selectCrl = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_GetCRL"); + PKIX_NULLCHECK_FOUR(certStore, selector, pNBIOContext, pCrlList); + + *pNBIOContext = NULL; /* We don't use non-blocking I/O */ + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (certStore, + (PKIX_PL_Object **) &colCertStoreContext, + plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (colCertStoreContext->crlList == NULL) { + + PKIX_OBJECT_LOCK(colCertStoreContext); + + /* + * CRLs in the directory are cached based on the + * assumption that the directory contents won't be + * changed dynamically. + */ + if (colCertStoreContext->crlList == NULL){ + PKIX_CHECK(pkix_pl_CollectionCertStoreContext_PopulateCRL + (colCertStoreContext, plContext), + PKIX_COLLECTIONCERTSTORECONTEXTPOPULATECRLFAILED); + } + + PKIX_OBJECT_UNLOCK(colCertStoreContext); + + } + + PKIX_CHECK(pkix_pl_CollectionCertStoreContext_GetSelectedCRL + (colCertStoreContext->crlList, + selector, + &selectCrl, + plContext), + PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED); + + *pCrlList = selectCrl; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_DECREF(colCertStoreContext); + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_CollectionCertStoreContext_RegisterSelf + * DESCRIPTION: + * + * Registers PKIX_PL_COLLECTIONCERTSTORECONTEXT_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_pl_CollectionCertStoreContext_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, + "pkix_pl_CollectionCertStoreContext_RegisterSelf"); + + entry.description = "CollectionCertStoreContext"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CollectionCertStoreContext); + entry.destructor = pkix_pl_CollectionCertStoreContext_Destroy; + entry.equalsFunction = pkix_pl_CollectionCertStoreContext_Equals; + entry.hashcodeFunction = pkix_pl_CollectionCertStoreContext_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_COLLECTIONCERTSTORECONTEXT_TYPE] = entry; + + PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); +} + +/* --Public-CollectionCertStoreContext-Functions--------------------------- */ + +/* + * FUNCTION: PKIX_PL_CollectionCertStore_Create + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_CollectionCertStore_Create( + PKIX_PL_String *storeDir, + PKIX_CertStore **pCertStore, + void *plContext) +{ + PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL; + PKIX_CertStore *certStore = NULL; + + PKIX_ENTER(CERTSTORE, "PKIX_PL_CollectionCertStore_Create"); + PKIX_NULLCHECK_TWO(storeDir, pCertStore); + + PKIX_CHECK(pkix_pl_CollectionCertStoreContext_Create + (storeDir, &colCertStoreContext, plContext), + PKIX_COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT); + + PKIX_CHECK(PKIX_CertStore_Create + (pkix_pl_CollectionCertStore_GetCert, + pkix_pl_CollectionCertStore_GetCRL, + NULL, /* GetCertContinue */ + NULL, /* GetCRLContinue */ + pkix_pl_CollectionCertStore_CheckTrust, + NULL, /* can not store crls */ + NULL, /* can not do revocation check */ + (PKIX_PL_Object *)colCertStoreContext, + PKIX_TRUE, /* cache flag */ + PKIX_TRUE, /* local - no network I/O */ + &certStore, + plContext), + PKIX_CERTSTORECREATEFAILED); + + PKIX_DECREF(colCertStoreContext); + + *pCertStore = certStore; + +cleanup: + PKIX_RETURN(CERTSTORE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h new file mode 100644 index 0000000000..f41e6fa5e8 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h @@ -0,0 +1,34 @@ +/* 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_pl_colcertstore.h + * + * CollectionCertstore Object Type Definition + * + */ + +#ifndef _PKIX_PL_COLCERTSTORE_H +#define _PKIX_PL_COLCERTSTORE_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_CollectionCertStoreContext { + PKIX_PL_String *storeDir; + PKIX_List *crlList; + PKIX_List *certList; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_CollectionCertStoreContext_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_COLCERTSTORE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c new file mode 100644 index 0000000000..471f92004a --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c @@ -0,0 +1,1147 @@ +/* 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_pl_httpcertstore.c + * + * HTTPCertStore Function Definitions + * + */ + +/* We can't decode the length of a message without at least this many bytes */ + +#include "pkix_pl_httpcertstore.h" +extern PKIX_PL_HashTable *httpSocketCache; +SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) +SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate) +SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) + +SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate) +SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate) +/* SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate) +SEC_ASN1_CHOOSER_DECLARE(CERT_SetOfSignedCrlTemplate) + +const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(CERTIssuerAndSN) }, + { SEC_ASN1_SAVE, + offsetof(CERTIssuerAndSN,derIssuer) }, + { SEC_ASN1_INLINE, + offsetof(CERTIssuerAndSN,issuer), + CERT_NameTemplate }, + { SEC_ASN1_INTEGER, + offsetof(CERTIssuerAndSN,serialNumber) }, + { 0 } +}; + +const SEC_ASN1Template SECOID_AlgorithmIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECAlgorithmID) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SECAlgorithmID,algorithm) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(SECAlgorithmID,parameters) }, + { 0 } +}; */ + +/* --Private-HttpCertStoreContext-Object Functions----------------------- */ + +/* + * FUNCTION: pkix_pl_HttpCertStoreContext_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_HttpCertStoreContext_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *context = NULL; + + PKIX_ENTER + (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStoreContext_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_HTTPCERTSTORECONTEXT_TYPE, plContext), + PKIX_OBJECTNOTANHTTPCERTSTORECONTEXT); + + context = (PKIX_PL_HttpCertStoreContext *)object; + hcv1 = (const SEC_HttpClientFcnV1 *)(context->client); + if (context->requestSession != NULL) { + (*hcv1->freeFcn)(context->requestSession); + context->requestSession = NULL; + } + if (context->serverSession != NULL) { + (*hcv1->freeSessionFcn)(context->serverSession); + context->serverSession = NULL; + } + if (context->path != NULL) { + PORT_Free(context->path); + context->path = NULL; + } + +cleanup: + + PKIX_RETURN(HTTPCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_HttpCertStoreContext_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_pl_HttpCertStoreContext_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_HTTPCERTSTORECONTEXT_TYPE]; + + PKIX_ENTER(HTTPCERTSTORECONTEXT, + "pkix_pl_HttpCertStoreContext_RegisterSelf"); + + entry->description = "HttpCertStoreContext"; + entry->typeObjectSize = sizeof(PKIX_PL_HttpCertStoreContext); + entry->destructor = pkix_pl_HttpCertStoreContext_Destroy; + + PKIX_RETURN(HTTPCERTSTORECONTEXT); +} + + +/* --Private-Http-CertStore-Database-Functions----------------------- */ + +typedef struct callbackContextStruct { + PKIX_List *pkixCertList; + PKIX_Error *error; + void *plContext; +} callbackContext; + + +/* + * FUNCTION: certCallback + * DESCRIPTION: + * + * This function processes the null-terminated array of SECItems produced by + * extracting the contents of a signedData message received in response to an + * HTTP cert query. Its address is supplied as a callback function to + * CERT_DecodeCertPackage; it is not expected to be called directly. + * + * Note that it does not conform to the libpkix API standard of returning + * a PKIX_Error*. It returns a SECStatus. + * + * PARAMETERS: + * "arg" + * The address of the callbackContext provided as a void* argument to + * CERT_DecodeCertPackage. Must be non-NULL. + * "secitemCerts" + * The address of the null-terminated array of SECItems. Must be non-NULL. + * "numcerts" + * The number of SECItems found in the signedData. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns SECSuccess if the function succeeds. + * Returns SECFailure if the function fails. + */ +static SECStatus +certCallback(void *arg, SECItem **secitemCerts, int numcerts) +{ + callbackContext *cbContext; + PKIX_List *pkixCertList = NULL; + PKIX_Error *error = NULL; + void *plContext = NULL; + int itemNum = 0; + + if ((arg == NULL) || (secitemCerts == NULL)) { + return (SECFailure); + } + + cbContext = (callbackContext *)arg; + plContext = cbContext->plContext; + pkixCertList = cbContext->pkixCertList; + + for (; itemNum < numcerts; itemNum++ ) { + error = pkix_pl_Cert_CreateToList(secitemCerts[itemNum], + pkixCertList, plContext); + if (error != NULL) { + if (error->errClass == PKIX_FATAL_ERROR) { + cbContext->error = error; + return SECFailure; + } + /* reuse "error" since we could not destruct the old * + * value */ + error = PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, + plContext); + if (error) { + /* Treat decref failure as a fatal error. + * In this case will leak error, but can not do + * anything about it. */ + error->errClass = PKIX_FATAL_ERROR; + cbContext->error = error; + return SECFailure; + } + } + } + + return SECSuccess; +} + + +typedef SECStatus (*pkix_DecodeCertsFunc)(char *certbuf, int certlen, + CERTImportCertificateFunc f, void *arg); + + +struct pkix_DecodeFuncStr { + pkix_DecodeCertsFunc func; /* function pointer to the + * CERT_DecodeCertPackage function */ + PRLibrary *smimeLib; /* Pointer to the smime shared lib*/ + PRCallOnceType once; +}; + +static struct pkix_DecodeFuncStr pkix_decodeFunc; +static const PRCallOnceType pkix_pristine; + +#define SMIME_LIB_NAME SHLIB_PREFIX"smime3."SHLIB_SUFFIX + +/* + * load the smime library and look up the SEC_ReadPKCS7Certs function. + * we do this so we don't have a circular depenency on the smime library, + * and also so we don't have to load the smime library in applications that + * don't use it. + */ +static PRStatus PR_CALLBACK pkix_getDecodeFunction(void) +{ + pkix_decodeFunc.smimeLib = + PR_LoadLibrary(SHLIB_PREFIX"smime3."SHLIB_SUFFIX); + if (pkix_decodeFunc.smimeLib == NULL) { + return PR_FAILURE; + } + + pkix_decodeFunc.func = (pkix_DecodeCertsFunc) PR_FindFunctionSymbol( + pkix_decodeFunc.smimeLib, "CERT_DecodeCertPackage"); + if (!pkix_decodeFunc.func) { + return PR_FAILURE; + } + return PR_SUCCESS; + +} + +/* + * clears our global state on shutdown. + */ +void +pkix_pl_HttpCertStore_Shutdown(void *plContext) +{ + if (pkix_decodeFunc.smimeLib) { + PR_UnloadLibrary(pkix_decodeFunc.smimeLib); + pkix_decodeFunc.smimeLib = NULL; + } + /* the function pointer just need to be cleared, not freed */ + pkix_decodeFunc.func = NULL; + pkix_decodeFunc.once = pkix_pristine; +} + +/* + * This function is based on CERT_DecodeCertPackage from lib/pkcs7/certread.c + * read an old style ascii or binary certificate chain + */ +PKIX_Error * +pkix_pl_HttpCertStore_DecodeCertPackage + (const char *certbuf, + int certlen, + CERTImportCertificateFunc f, + void *arg, + void *plContext) +{ + + PRStatus status; + SECStatus rv; + + PKIX_ENTER + (HTTPCERTSTORECONTEXT, + "pkix_pl_HttpCertStore_DecodeCertPackage"); + PKIX_NULLCHECK_TWO(certbuf, f); + + status = PR_CallOnce(&pkix_decodeFunc.once, pkix_getDecodeFunction); + + if (status != PR_SUCCESS) { + PKIX_ERROR(PKIX_CANTLOADLIBSMIME); + } + + /* paranoia, shouldn't happen if status == PR_SUCCESS); */ + if (!pkix_decodeFunc.func) { + PKIX_ERROR(PKIX_CANTLOADLIBSMIME); + } + + rv = (*pkix_decodeFunc.func)((char*)certbuf, certlen, f, arg); + + if (rv != SECSuccess) { + PKIX_ERROR (PKIX_SECREADPKCS7CERTSFAILED); + } + + +cleanup: + + PKIX_RETURN(HTTPCERTSTORECONTEXT); +} + + +/* + * FUNCTION: pkix_pl_HttpCertStore_ProcessCertResponse + * DESCRIPTION: + * + * This function verifies that the response code pointed to by "responseCode" + * and the content type pointed to by "responseContentType" are as expected, + * and then decodes the data pointed to by "responseData", of length + * "responseDataLen", into a List of Certs, possibly empty, which is returned + * at "pCertList". + * + * PARAMETERS: + * "responseCode" + * The value of the HTTP response code. + * "responseContentType" + * The address of the Content-type string. Must be non-NULL. + * "responseData" + * The address of the message data. Must be non-NULL. + * "responseDataLen" + * The length of the message data. + * "pCertList" + * The address of the List that is created. 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 HttpCertStore 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_pl_HttpCertStore_ProcessCertResponse( + PRUint16 responseCode, + const char *responseContentType, + const char *responseData, + PRUint32 responseDataLen, + PKIX_List **pCertList, + void *plContext) +{ + callbackContext cbContext; + + PKIX_ENTER(HTTPCERTSTORECONTEXT, + "pkix_pl_HttpCertStore_ProcessCertResponse"); + + cbContext.error = NULL; + cbContext.plContext = plContext; + cbContext.pkixCertList = NULL; + + PKIX_NULLCHECK_ONE(pCertList); + + if (responseCode != 200) { + PKIX_ERROR(PKIX_BADHTTPRESPONSE); + } + + /* check that response type is application/pkcs7-mime */ + if (responseContentType == NULL) { + PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); + } + + if (responseData == NULL) { + PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE); + } + + PKIX_CHECK( + PKIX_List_Create(&cbContext.pkixCertList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK_ONLY_FATAL( + pkix_pl_HttpCertStore_DecodeCertPackage(responseData, + responseDataLen, + certCallback, + &cbContext, + plContext), + PKIX_HTTPCERTSTOREDECODECERTPACKAGEFAILED); + if (cbContext.error) { + /* Aborting on a fatal error(See certCallback fn) */ + pkixErrorResult = cbContext.error; + goto cleanup; + } + + *pCertList = cbContext.pkixCertList; + cbContext.pkixCertList = NULL; + +cleanup: + + PKIX_DECREF(cbContext.pkixCertList); + + PKIX_RETURN(HTTPCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse + * DESCRIPTION: + * + * This function verifies that the response code pointed to by "responseCode" + * and the content type pointed to by "responseContentType" are as expected, + * and then decodes the data pointed to by "responseData", of length + * "responseDataLen", into a List of Crls, possibly empty, which is returned + * at "pCrlList". + * + * PARAMETERS: + * "responseCode" + * The value of the HTTP response code. + * "responseContentType" + * The address of the Content-type string. Must be non-NULL. + * "responseData" + * The address of the message data. Must be non-NULL. + * "responseDataLen" + * The length of the message data. + * "pCrlList" + * The address of the List that is created. 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 HttpCertStore 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_pl_HttpCertStore_ProcessCrlResponse( + PRUint16 responseCode, + const char *responseContentType, + const char *responseData, + PRUint32 responseDataLen, + PKIX_List **pCrlList, + void *plContext) +{ + SECItem encodedResponse; + PRInt16 compareVal = 0; + PKIX_List *crls = NULL; + SECItem *derCrlCopy = NULL; + CERTSignedCrl *nssCrl = NULL; + PKIX_PL_CRL *crl = NULL; + + PKIX_ENTER(HTTPCERTSTORECONTEXT, + "pkix_pl_HttpCertStore_ProcessCrlResponse"); + PKIX_NULLCHECK_ONE(pCrlList); + + if (responseCode != 200) { + PKIX_ERROR(PKIX_BADHTTPRESPONSE); + } + + /* check that response type is application/pkix-crl */ + if (responseContentType == NULL) { + PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE); + } + + compareVal = PORT_Strcasecmp(responseContentType, + "application/pkix-crl"); + if (compareVal != 0) { + PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL); + } + encodedResponse.type = siBuffer; + encodedResponse.data = (void*)responseData; + encodedResponse.len = responseDataLen; + + derCrlCopy = SECITEM_DupItem(&encodedResponse); + if (!derCrlCopy) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + /* crl will be based on derCrlCopy, but will not own the der. */ + nssCrl = + CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE, + CRL_DECODE_DONT_COPY_DER | + CRL_DECODE_SKIP_ENTRIES); + if (!nssCrl) { + PKIX_ERROR(PKIX_FAILEDTODECODECRL); + } + /* pkix crls own the der. */ + PKIX_CHECK( + pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, NULL, + &crl, plContext), + PKIX_CRLCREATEWITHSIGNEDCRLFAILED); + /* Left control over memory pointed by derCrlCopy and + * nssCrl to pkix crl. */ + derCrlCopy = NULL; + nssCrl = NULL; + PKIX_CHECK(PKIX_List_Create(&crls, plContext), + PKIX_LISTCREATEFAILED); + PKIX_CHECK(PKIX_List_AppendItem + (crls, (PKIX_PL_Object *) crl, plContext), + PKIX_LISTAPPENDITEMFAILED); + *pCrlList = crls; + crls = NULL; +cleanup: + if (derCrlCopy) { + SECITEM_FreeItem(derCrlCopy, PR_TRUE); + } + if (nssCrl) { + SEC_DestroyCrl(nssCrl); + } + PKIX_DECREF(crl); + PKIX_DECREF(crls); + + PKIX_RETURN(HTTPCERTSTORECONTEXT); +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_CreateRequestSession + * DESCRIPTION: + * + * This function takes elements from the HttpCertStoreContext pointed to by + * "context" (path, client, and serverSession) and creates a RequestSession. + * See the HTTPClient API described in ocspt.h for further details. + * + * PARAMETERS: + * "context" + * The address of the HttpCertStoreContext. 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 HttpCertStore 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_pl_HttpCertStore_CreateRequestSession( + PKIX_PL_HttpCertStoreContext *context, + void *plContext) +{ + const SEC_HttpClientFcnV1 *hcv1 = NULL; + SECStatus rv = SECFailure; + + PKIX_ENTER + (HTTPCERTSTORECONTEXT, + "pkix_pl_HttpCertStore_CreateRequestSession"); + PKIX_NULLCHECK_TWO(context, context->serverSession); + + if (context->client->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + + hcv1 = &(context->client->fcnTable.ftable1); + if (context->requestSession != NULL) { + (*hcv1->freeFcn)(context->requestSession); + context->requestSession = 0; + } + + rv = (*hcv1->createFcn)(context->serverSession, "http", + context->path, "GET", + PR_SecondsToInterval( + ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), + &(context->requestSession)); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } +cleanup: + + PKIX_RETURN(HTTPCERTSTORECONTEXT); + +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_GetCert + * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_HttpCertStore_GetCert( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *context = NULL; + void *nbioContext = NULL; + SECStatus rv = SECFailure; + PRUint16 responseCode = 0; + const char *responseContentType = NULL; + const char *responseData = NULL; + PRUint32 responseDataLen = 0; + PKIX_List *certList = NULL; + + PKIX_ENTER(HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_GetCert"); + PKIX_NULLCHECK_THREE(store, selector, pCertList); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&context, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (context->client->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + + hcv1 = &(context->client->fcnTable.ftable1); + + PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession + (context, plContext), + PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); + + responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, + (PRPollDesc **)&nbioContext, + &responseCode, + (const char **)&responseContentType, + NULL, /* &responseHeaders */ + (const char **)&responseData, + &responseDataLen); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + if (nbioContext != 0) { + *pNBIOContext = nbioContext; + goto cleanup; + } + + PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse + (responseCode, + responseContentType, + responseData, + responseDataLen, + &certList, + plContext), + PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); + + *pCertList = certList; + +cleanup: + PKIX_DECREF(context); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_GetCertContinue + * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_HttpCertStore_GetCertContinue( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *context = NULL; + void *nbioContext = NULL; + SECStatus rv = SECFailure; + PRUint16 responseCode = 0; + const char *responseContentType = NULL; + const char *responseData = NULL; + PRUint32 responseDataLen = 0; + PKIX_List *certList = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCertContinue"); + PKIX_NULLCHECK_THREE(store, selector, pCertList); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&context, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (context->client->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + + hcv1 = &(context->client->fcnTable.ftable1); + PKIX_NULLCHECK_ONE(context->requestSession); + + responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, + (PRPollDesc **)&nbioContext, + &responseCode, + (const char **)&responseContentType, + NULL, /* &responseHeaders */ + (const char **)&responseData, + &responseDataLen); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + if (nbioContext != 0) { + *pNBIOContext = nbioContext; + goto cleanup; + } + + PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse + (responseCode, + responseContentType, + responseData, + responseDataLen, + &certList, + plContext), + PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED); + + *pCertList = certList; + +cleanup: + PKIX_DECREF(context); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_GetCRL + * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_HttpCertStore_GetCRL( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *context = NULL; + void *nbioContext = NULL; + SECStatus rv = SECFailure; + PRUint16 responseCode = 0; + const char *responseContentType = NULL; + const char *responseData = NULL; + PRUint32 responseDataLen = 0; + PKIX_List *crlList = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRL"); + PKIX_NULLCHECK_THREE(store, selector, pCrlList); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&context, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (context->client->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + + hcv1 = &(context->client->fcnTable.ftable1); + PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession + (context, plContext), + PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); + + responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, + (PRPollDesc **)&nbioContext, + &responseCode, + (const char **)&responseContentType, + NULL, /* &responseHeaders */ + (const char **)&responseData, + &responseDataLen); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + if (nbioContext != 0) { + *pNBIOContext = nbioContext; + goto cleanup; + } + + PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse + (responseCode, + responseContentType, + responseData, + responseDataLen, + &crlList, + plContext), + PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED); + + *pCrlList = crlList; + +cleanup: + PKIX_DECREF(context); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_HttpCertStore_GetCRLContinue + * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_HttpCertStore_GetCRLContinue( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *context = NULL; + void *nbioContext = NULL; + SECStatus rv = SECFailure; + PRUint16 responseCode = 0; + const char *responseContentType = NULL; + const char *responseData = NULL; + PRUint32 responseDataLen = 0; + PKIX_List *crlList = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRLContinue"); + PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&context, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + if (context->client->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + hcv1 = &(context->client->fcnTable.ftable1); + + PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession + (context, plContext), + PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED); + + responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession, + (PRPollDesc **)&nbioContext, + &responseCode, + (const char **)&responseContentType, + NULL, /* &responseHeaders */ + (const char **)&responseData, + &responseDataLen); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPSERVERERROR); + } + + if (nbioContext != 0) { + *pNBIOContext = nbioContext; + goto cleanup; + } + + PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse + (responseCode, + responseContentType, + responseData, + responseDataLen, + &crlList, + plContext), + PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED); + + *pCrlList = crlList; + +cleanup: + PKIX_DECREF(context); + + PKIX_RETURN(CERTSTORE); +} + +/* --Public-HttpCertStore-Functions----------------------------------- */ + +/* + * FUNCTION: pkix_pl_HttpCertStore_CreateWithAsciiName + * DESCRIPTION: + * + * This function uses the HttpClient pointed to by "client" and the string + * (hostname:portnum/path, with portnum optional) pointed to by "locationAscii" + * to create an HttpCertStore connected to the desired location, storing the + * created CertStore at "pCertStore". + * + * PARAMETERS: + * "client" + * The address of the HttpClient. Must be non-NULL. + * "locationAscii" + * The address of the character string indicating the hostname, port, and + * path to be queried for Certs or Crls. Must be non-NULL. + * "pCertStore" + * The address in which the object 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 HttpCertStore 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_pl_HttpCertStore_CreateWithAsciiName( + PKIX_PL_HttpClient *client, + char *locationAscii, + PKIX_CertStore **pCertStore, + void *plContext) +{ + const SEC_HttpClientFcn *clientFcn = NULL; + const SEC_HttpClientFcnV1 *hcv1 = NULL; + PKIX_PL_HttpCertStoreContext *httpCertStore = NULL; + PKIX_CertStore *certStore = NULL; + char *hostname = NULL; + char *path = NULL; + PRUint16 port = 0; + SECStatus rv = SECFailure; + + PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_CreateWithAsciiName"); + PKIX_NULLCHECK_TWO(locationAscii, pCertStore); + + if (client == NULL) { + clientFcn = SEC_GetRegisteredHttpClient(); + if (clientFcn == NULL) { + PKIX_ERROR(PKIX_NOREGISTEREDHTTPCLIENT); + } + } else { + clientFcn = (const SEC_HttpClientFcn *)client; + } + + if (clientFcn->version != 1) { + PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT); + } + + /* create a PKIX_PL_HttpCertStore object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_HTTPCERTSTORECONTEXT_TYPE, + sizeof (PKIX_PL_HttpCertStoreContext), + (PKIX_PL_Object **)&httpCertStore, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* Initialize fields */ + httpCertStore->client = clientFcn; /* not a PKIX object! */ + + /* parse location -> hostname, port, path */ + rv = CERT_ParseURL(locationAscii, &hostname, &port, &path); + if (rv == SECFailure || hostname == NULL || path == NULL) { + PKIX_ERROR(PKIX_URLPARSINGFAILED); + } + + httpCertStore->path = path; + path = NULL; + + hcv1 = &(clientFcn->fcnTable.ftable1); + rv = (*hcv1->createSessionFcn)(hostname, port, + &(httpCertStore->serverSession)); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED); + } + + httpCertStore->requestSession = NULL; + + PKIX_CHECK(PKIX_CertStore_Create + (pkix_pl_HttpCertStore_GetCert, + pkix_pl_HttpCertStore_GetCRL, + pkix_pl_HttpCertStore_GetCertContinue, + pkix_pl_HttpCertStore_GetCRLContinue, + NULL, /* don't support trust */ + NULL, /* can not store crls */ + NULL, /* can not do revocation check */ + (PKIX_PL_Object *)httpCertStore, + PKIX_TRUE, /* cache flag */ + PKIX_FALSE, /* not local */ + &certStore, + plContext), + PKIX_CERTSTORECREATEFAILED); + + *pCertStore = certStore; + certStore = NULL; + +cleanup: + PKIX_DECREF(httpCertStore); + if (hostname) { + PORT_Free(hostname); + } + if (path) { + PORT_Free(path); + } + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: PKIX_PL_HttpCertStore_Create + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_HttpCertStore_Create( + PKIX_PL_HttpClient *client, + PKIX_PL_GeneralName *location, + PKIX_CertStore **pCertStore, + void *plContext) +{ + PKIX_PL_String *locationString = NULL; + char *locationAscii = NULL; + PKIX_UInt32 len = 0; + + PKIX_ENTER(CERTSTORE, "PKIX_PL_HttpCertStore_Create"); + PKIX_NULLCHECK_TWO(location, pCertStore); + + PKIX_TOSTRING(location, &locationString, plContext, + PKIX_GENERALNAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (locationString, + PKIX_ESCASCII, + (void **)&locationAscii, + &len, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_CHECK(pkix_pl_HttpCertStore_CreateWithAsciiName + (client, locationAscii, pCertStore, plContext), + PKIX_HTTPCERTSTORECREATEWITHASCIINAMEFAILED); + +cleanup: + + PKIX_DECREF(locationString); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_HttpCertStore_FindSocketConnection + * DESCRIPTION: + * + PRIntervalTime timeout, + char *hostname, + PRUint16 portnum, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + + * This function checks for an existing socket, creating a new one if unable + * to find an existing one, for the host pointed to by "hostname" and the port + * pointed to by "portnum". If a new socket is created the PRIntervalTime in + * "timeout" will be used for the timeout value and a creation status is + * returned at "pStatus". The address of the socket is stored at "pSocket". + * + * PARAMETERS: + * "timeout" + * The PRIntervalTime of the timeout value. + * "hostname" + * The address of the string containing the hostname. Must be non-NULL. + * "portnum" + * The port number for the desired socket. + * "pStatus" + * The address at which the status is stored. Must be non-NULL. + * "pSocket" + * The address at which the socket 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 HttpCertStore 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_HttpCertStore_FindSocketConnection( + PRIntervalTime timeout, + char *hostname, + PRUint16 portnum, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext) +{ + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *hostString = NULL; + PKIX_PL_String *domainString = NULL; + PKIX_PL_Socket *socket = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_HttpCertStore_FindSocketConnection"); + PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket); + + *pStatus = 0; + + /* create PKIX_PL_String from hostname and port */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "%s:%d", 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + +#if 0 +hostname = "variation.red.iplanet.com"; +portnum = 2001; +#endif + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, hostname, 0, &hostString, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&domainString, plContext, formatString, hostString, portnum), + PKIX_STRINGCREATEFAILED); + +#ifdef PKIX_SOCKETCACHE + /* Is this domainName already in cache? */ + PKIX_CHECK(PKIX_PL_HashTable_Lookup + (httpSocketCache, + (PKIX_PL_Object *)domainString, + (PKIX_PL_Object **)&socket, + plContext), + PKIX_HASHTABLELOOKUPFAILED); +#endif + if (socket == NULL) { + + /* No, create a connection (and cache it) */ + PKIX_CHECK(pkix_pl_Socket_CreateByHostAndPort + (PKIX_FALSE, /* create a client, not a server */ + timeout, + hostname, + portnum, + pStatus, + &socket, + plContext), + PKIX_SOCKETCREATEBYHOSTANDPORTFAILED); + +#ifdef PKIX_SOCKETCACHE + PKIX_CHECK(PKIX_PL_HashTable_Add + (httpSocketCache, + (PKIX_PL_Object *)domainString, + (PKIX_PL_Object *)socket, + plContext), + PKIX_HASHTABLEADDFAILED); +#endif + } + + *pSocket = socket; + socket = NULL; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(hostString); + PKIX_DECREF(domainString); + PKIX_DECREF(socket); + + PKIX_RETURN(CERTSTORE); +} + diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h new file mode 100644 index 0000000000..a03ea94d86 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h @@ -0,0 +1,62 @@ +/* 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_pl_httpcertstore.h + * + * HTTPCertstore Object Type Definition + * + */ + +#ifndef _PKIX_PL_HTTPCERTSTORE_H +#define _PKIX_PL_HTTPCERTSTORE_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_HttpCertStoreContextStruct { + const SEC_HttpClientFcn *client; + SEC_HTTP_SERVER_SESSION serverSession; + SEC_HTTP_REQUEST_SESSION requestSession; + char *path; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_HttpCertStoreContext_RegisterSelf(void *plContext); + +void pkix_pl_HttpCertStore_Shutdown(void *plContext); + +PKIX_Error * +pkix_pl_HttpCertStore_CreateWithAsciiName( + PKIX_PL_HttpClient *client, + char *locationAscii, + PKIX_CertStore **pCertStore, + void *plContext); + +PKIX_Error * +pkix_HttpCertStore_FindSocketConnection( + PRIntervalTime timeout, + char *hostname, + PRUint16 portnum, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext); + +PKIX_Error * +pkix_pl_HttpCertStore_ProcessCertResponse( + PRUint16 responseCode, + const char *responseContentType, + const char *responseData, + PRUint32 responseDataLen, + PKIX_List **pCertList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_HTTPCERTSTORE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c new file mode 100644 index 0000000000..f73b95f686 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c @@ -0,0 +1,1654 @@ +/* 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_pl_httpdefaultclient.c + * + * HTTPDefaultClient Function Definitions + * + */ + +#include "pkix_pl_httpdefaultclient.h" + +static void *plContext = NULL; + +/* + * The interface specification for an http client requires that it register + * a function table of type SEC_HttpClientFcn, which is defined as a union + * of tables, of which only version 1 is defined at present. + * + * Note: these functions violate the PKIX calling conventions, in that they + * return SECStatus rather than PKIX_Error*, and that they do not provide a + * plContext argument. They are implemented here as calls to PKIX functions, + * but the plContext value is circularly defined - a true kludge. Its value + * is saved at the time of the call to pkix_pl_HttpDefaultClient_Create for + * subsequent use, but since that initial call comes from the + * pkix_pl_HttpDefaultClient_CreateSessionFcn, it's not really getting saved. + */ +static SEC_HttpClientFcnV1 vtable = { + pkix_pl_HttpDefaultClient_CreateSessionFcn, + pkix_pl_HttpDefaultClient_KeepAliveSessionFcn, + pkix_pl_HttpDefaultClient_FreeSessionFcn, + pkix_pl_HttpDefaultClient_RequestCreateFcn, + pkix_pl_HttpDefaultClient_SetPostDataFcn, + pkix_pl_HttpDefaultClient_AddHeaderFcn, + pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn, + pkix_pl_HttpDefaultClient_CancelFcn, + pkix_pl_HttpDefaultClient_FreeFcn +}; + +static SEC_HttpClientFcn httpClient; + +static const char *eohMarker = "\r\n\r\n"; +static const PKIX_UInt32 eohMarkLen = 4; /* strlen(eohMarker) */ +static const char *crlf = "\r\n"; +static const PKIX_UInt32 crlfLen = 2; /* strlen(crlf) */ +static const char *httpprotocol = "HTTP/"; +static const PKIX_UInt32 httpprotocolLen = 5; /* strlen(httpprotocol) */ + + +#define HTTP_UNKNOWN_CONTENT_LENGTH -1 + +/* --Private-HttpDefaultClient-Functions------------------------- */ + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_HdrCheckComplete + * DESCRIPTION: + * + * This function determines whether the headers in the current receive buffer + * in the HttpDefaultClient pointed to by "client" are complete. If so, the + * input data is checked for status code, content-type and content-length are + * extracted, and the client is set up to read the body of the response. + * Otherwise, the client is set up to continue reading header data. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "bytesRead" + * The UInt32 number of bytes received in the latest read. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_HdrCheckComplete( + PKIX_PL_HttpDefaultClient *client, + PKIX_UInt32 bytesRead, + PKIX_Boolean *pKeepGoing, + void *plCtx) +{ + PKIX_UInt32 alreadyScanned = 0; + PKIX_UInt32 comp = 0; + PKIX_UInt32 headerLength = 0; + PKIX_Int32 contentLength = HTTP_UNKNOWN_CONTENT_LENGTH; + char *eoh = NULL; + char *statusLineEnd = NULL; + char *space = NULL; + char *nextHeader = NULL; + const char *httpcode = NULL; + char *thisHeaderEnd = NULL; + char *value = NULL; + char *colon = NULL; + char *copy = NULL; + char *body = NULL; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_HdrCheckComplete"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + *pKeepGoing = PKIX_FALSE; + + /* Does buffer contain end-of-header marker? */ + + /* Copy number of scanned bytes into a variable. */ + alreadyScanned = client->filledupBytes; + /* + * If this is the initial buffer, we have to scan from the beginning. + * If we scanned, failed to find eohMarker, and read some more, we + * only have to scan from where we left off. + */ + if (alreadyScanned > eohMarkLen) { + /* Back up and restart scanning over a few bytes that were + * scanned before */ + PKIX_UInt32 searchStartPos = alreadyScanned - eohMarkLen; + eoh = PL_strnstr(&(client->rcvBuf[searchStartPos]), eohMarker, + bytesRead + searchStartPos); + } else { + /* A search from the beginning of the buffer. */ + eoh = PL_strnstr(client->rcvBuf, eohMarker, bytesRead); + } + + client->filledupBytes += bytesRead; + + if (eoh == NULL) { /* did we see end-of-header? */ + /* No. Continue to read header data */ + client->connectStatus = HTTP_RECV_HDR; + *pKeepGoing = PKIX_TRUE; + goto cleanup; + } + + /* Yes. Calculate how many bytes in header (not counting eohMarker) */ + headerLength = (eoh - client->rcvBuf); + + /* allocate space to copy header (and for the NULL terminator) */ + PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)©, plCtx), + PKIX_MALLOCFAILED); + + /* copy header data before we corrupt it (by storing NULLs) */ + PORT_Memcpy(copy, client->rcvBuf, headerLength); + /* Store the NULL terminator */ + copy[headerLength] = '\0'; + client->rcvHeaders = copy; + + /* Did caller want a pointer to header? */ + if (client->rcv_http_headers != NULL) { + /* store pointer for caller */ + *(client->rcv_http_headers) = copy; + } + + /* Check that message status is okay. */ + statusLineEnd = PL_strnstr(client->rcvBuf, crlf, client->capacity); + if (statusLineEnd == NULL) { + client->connectStatus = HTTP_ERROR; + PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE); + goto cleanup; + } + + *statusLineEnd = '\0'; + + space = strchr((const char *)client->rcvBuf, ' '); + if (space == NULL) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + + comp = PORT_Strncasecmp((const char *)client->rcvBuf, httpprotocol, + httpprotocolLen); + if (comp != 0) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + + httpcode = space + 1; + space = strchr(httpcode, ' '); + if (space == NULL) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + *space = '\0'; + + client->responseCode = atoi(httpcode); + if (client->responseCode != 200) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + + /* Find the content-type and content-length */ + nextHeader = statusLineEnd + crlfLen; + *eoh = '\0'; + do { + thisHeaderEnd = NULL; + value = NULL; + + colon = strchr(nextHeader, ':'); + if (colon == NULL) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + *colon = '\0'; + value = colon + 1; + if (*value != ' ') { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + value++; + thisHeaderEnd = strstr(value, crlf); + if (thisHeaderEnd != NULL) { + *thisHeaderEnd = '\0'; + } + comp = PORT_Strcasecmp(nextHeader, "content-type"); + if (comp == 0) { + client->rcvContentType = PORT_Strdup(value); + } else { + comp = PORT_Strcasecmp(nextHeader, "content-length"); + if (comp == 0) { + contentLength = atoi(value); + } + } + if (thisHeaderEnd != NULL) { + nextHeader = thisHeaderEnd + crlfLen; + } else { + nextHeader = NULL; + } + } while ((nextHeader != NULL) && (nextHeader < (eoh + crlfLen))); + + /* Did caller provide a pointer to return content-type? */ + if (client->rcv_http_content_type != NULL) { + *(client->rcv_http_content_type) = client->rcvContentType; + } + + if (client->rcvContentType == NULL) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + + /* How many bytes remain in current buffer, beyond the header? */ + headerLength += eohMarkLen; + client->filledupBytes -= headerLength; + + /* + * The headers have passed validation. Now figure out whether the + * message is within the caller's size limit (if one was specified). + */ + switch (contentLength) { + case 0: + client->rcv_http_data_len = 0; + client->connectStatus = HTTP_COMPLETE; + *pKeepGoing = PKIX_FALSE; + break; + + case HTTP_UNKNOWN_CONTENT_LENGTH: + /* Unknown contentLength indicator.Will be set by + * pkix_pl_HttpDefaultClient_RecvBody whey connection get closed */ + client->rcv_http_data_len = HTTP_UNKNOWN_CONTENT_LENGTH; + contentLength = /* Try to reserve 4K+ buffer */ + client->filledupBytes + HTTP_DATA_BUFSIZE; + if (client->maxResponseLen > 0 && + contentLength > (PKIX_Int32)client->maxResponseLen) { + if (client->filledupBytes < client->maxResponseLen) { + contentLength = client->maxResponseLen; + } else { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + } + /* set available number of bytes in the buffer */ + client->capacity = contentLength; + client->connectStatus = HTTP_RECV_BODY; + *pKeepGoing = PKIX_TRUE; + break; + + default: + client->rcv_http_data_len = contentLength; + if (client->maxResponseLen > 0 && + (PKIX_Int32)client->maxResponseLen < contentLength) { + client->connectStatus = HTTP_ERROR; + goto cleanup; + } + + /* + * Do we have all of the message body, or do we need to read some more? + */ + if ((PKIX_Int32)client->filledupBytes < contentLength) { + client->connectStatus = HTTP_RECV_BODY; + *pKeepGoing = PKIX_TRUE; + } else { + client->connectStatus = HTTP_COMPLETE; + *pKeepGoing = PKIX_FALSE; + } + } + + if (contentLength > 0) { + /* allocate a buffer of size contentLength for the content */ + PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plCtx), + PKIX_MALLOCFAILED); + + /* copy any remaining bytes in current buffer into new buffer */ + if (client->filledupBytes > 0) { + PORT_Memcpy(body, &(client->rcvBuf[headerLength]), + client->filledupBytes); + } + } + + PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plCtx), + PKIX_FREEFAILED); + client->rcvBuf = body; + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: PKIX_PL_HttpDefaultClient_Create + * DESCRIPTION: + * + * This function creates a new HttpDefaultClient, and stores the result at + * "pClient". + * + * The HttpClient API does not include a plContext argument in its + * function calls. Its value at the time of this Create call must be the + * same as when the client is invoked. + * + * PARAMETERS: + * "host" + * The name of the server with which we hope to exchange messages. Must + * be non-NULL. + * "portnum" + * The port number to be used for our connection to the server. + * "pClient" + * The address at which the created HttpDefaultClient is to be stored. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_Create( + const char *host, + PRUint16 portnum, + PKIX_PL_HttpDefaultClient **pClient, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "PKIX_PL_HttpDefaultClient_Create"); + PKIX_NULLCHECK_TWO(pClient, host); + + /* allocate an HttpDefaultClient */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_HTTPDEFAULTCLIENT_TYPE, + sizeof (PKIX_PL_HttpDefaultClient), + (PKIX_PL_Object **)&client, + plCtx), + PKIX_COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT); + + /* Client timeout is overwritten in HttpDefaultClient_RequestCreate + * function. Default value will be ignored. */ + client->timeout = 0; + client->connectStatus = HTTP_NOT_CONNECTED; + client->portnum = portnum; + client->bytesToWrite = 0; + client->send_http_data_len = 0; + client->rcv_http_data_len = 0; + client->capacity = 0; + client->filledupBytes = 0; + client->responseCode = 0; + client->maxResponseLen = 0; + client->GETLen = 0; + client->POSTLen = 0; + client->pRcv_http_data_len = NULL; + client->callbackList = NULL; + client->GETBuf = NULL; + client->POSTBuf = NULL; + client->rcvBuf = NULL; + /* "host" is a parsing result by CERT_GetURL function that adds + * "end of line" to the value. OK to dup the string. */ + client->host = PORT_Strdup(host); + if (!client->host) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + client->path = NULL; + client->rcvContentType = NULL; + client->rcvHeaders = NULL; + client->send_http_method = HTTP_POST_METHOD; + client->send_http_content_type = NULL; + client->send_http_data = NULL; + client->rcv_http_response_code = NULL; + client->rcv_http_content_type = NULL; + client->rcv_http_headers = NULL; + client->rcv_http_data = NULL; + client->socket = NULL; + + /* + * The HttpClient API does not include a plCtx argument in its + * function calls. Save it here. + */ + client->plContext = plCtx; + + *pClient = client; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(client); + } + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_HttpDefaultClient_Destroy( + PKIX_PL_Object *object, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plCtx), + PKIX_OBJECTNOTANHTTPDEFAULTCLIENT); + + client = (PKIX_PL_HttpDefaultClient *)object; + + if (client->rcvHeaders) { + PKIX_PL_Free(client->rcvHeaders, plCtx); + client->rcvHeaders = NULL; + } + if (client->rcvContentType) { + PORT_Free(client->rcvContentType); + client->rcvContentType = NULL; + } + if (client->GETBuf != NULL) { + PR_smprintf_free(client->GETBuf); + client->GETBuf = NULL; + } + if (client->POSTBuf != NULL) { + PKIX_PL_Free(client->POSTBuf, plCtx); + client->POSTBuf = NULL; + } + if (client->rcvBuf != NULL) { + PKIX_PL_Free(client->rcvBuf, plCtx); + client->rcvBuf = NULL; + } + if (client->host) { + PORT_Free(client->host); + client->host = NULL; + } + if (client->path) { + PORT_Free(client->path); + client->path = NULL; + } + PKIX_DECREF(client->socket); + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_PL_HTTPDEFAULTCLIENT_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_pl_HttpDefaultClient_RegisterSelf(void *plCtx) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = + &systemClasses[PKIX_HTTPDEFAULTCLIENT_TYPE]; + + PKIX_ENTER(HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_RegisterSelf"); + + entry->description = "HttpDefaultClient"; + entry->typeObjectSize = sizeof(PKIX_PL_HttpDefaultClient); + entry->destructor = pkix_pl_HttpDefaultClient_Destroy; + + httpClient.version = 1; + httpClient.fcnTable.ftable1 = vtable; + (void)SEC_RegisterDefaultHttpClient(&httpClient); + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* --Private-HttpDefaultClient-I/O-Functions---------------------------- */ +/* + * FUNCTION: pkix_pl_HttpDefaultClient_ConnectContinue + * DESCRIPTION: + * + * This function determines whether a socket Connect initiated earlier for the + * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag + * indicating whether processing can continue without further input. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_ConnectContinue( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plCtx) +{ + PRErrorCode status; + PKIX_Boolean keepGoing = PKIX_FALSE; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_ConnectContinue"); + PKIX_NULLCHECK_ONE(client); + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + PKIX_CHECK(callbackList->connectcontinueCallback + (client->socket, &status, plCtx), + PKIX_SOCKETCONNECTCONTINUEFAILED); + + if (status == 0) { + client->connectStatus = HTTP_CONNECTED; + keepGoing = PKIX_TRUE; + } else if (status != PR_IN_PROGRESS_ERROR) { + PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION); + } + + *pKeepGoing = keepGoing; + +cleanup: + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_Send + * DESCRIPTION: + * + * This function creates and sends HTTP-protocol headers and, if applicable, + * data, for the HttpDefaultClient "client", and stores in "pKeepGoing" a flag + * indicating whether processing can continue without further input, and at + * "pBytesTransferred" the number of bytes sent. + * + * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use + * and that transmission has not completed. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "pBytesTransferred" + * The address at which the number of bytes sent is stored. Must be + * non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_Send( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + PKIX_UInt32 *pBytesTransferred, + void *plCtx) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_Int32 lenToWrite = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + char *dataToWrite = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Send"); + PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); + + *pKeepGoing = PKIX_FALSE; + + /* Do we have anything waiting to go? */ + if ((client->GETBuf) || (client->POSTBuf)) { + + if (client->GETBuf) { + dataToWrite = client->GETBuf; + lenToWrite = client->GETLen; + } else { + dataToWrite = client->POSTBuf; + lenToWrite = client->POSTLen; + } + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + PKIX_CHECK(callbackList->sendCallback + (client->socket, + dataToWrite, + lenToWrite, + &bytesWritten, + plCtx), + PKIX_SOCKETSENDFAILED); + + client->rcvBuf = NULL; + client->capacity = 0; + client->filledupBytes = 0; + + /* + * If the send completed we can proceed to try for the + * response. If the send did not complete we will have + * to poll for completion later. + */ + if (bytesWritten >= 0) { + client->connectStatus = HTTP_RECV_HDR; + *pKeepGoing = PKIX_TRUE; + } else { + client->connectStatus = HTTP_SEND_PENDING; + *pKeepGoing = PKIX_FALSE; + } + + } + + *pBytesTransferred = bytesWritten; + +cleanup: + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_SendContinue + * DESCRIPTION: + * + * This function determines whether the sending of the HTTP message for the + * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a + * flag indicating whether processing can continue without further input, and + * at "pBytesTransferred" the number of bytes sent. + * + * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use + * and that transmission has not completed. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "pBytesTransferred" + * The address at which the number of bytes sent is stored. Must be + * non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_SendContinue( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + PKIX_UInt32 *pBytesTransferred, + void *plCtx) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_SendContinue"); + PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); + + *pKeepGoing = PKIX_FALSE; + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + PKIX_CHECK(callbackList->pollCallback + (client->socket, &bytesWritten, NULL, plCtx), + PKIX_SOCKETPOLLFAILED); + + /* + * If the send completed we can proceed to try for the + * response. If the send did not complete we will have + * continue to poll. + */ + if (bytesWritten >= 0) { + client->connectStatus = HTTP_RECV_HDR; + *pKeepGoing = PKIX_TRUE; + } + + *pBytesTransferred = bytesWritten; + +cleanup: + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdr + * DESCRIPTION: + * + * This function receives HTTP headers for the HttpDefaultClient "client", and + * stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_RecvHdr( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plCtx) +{ + PKIX_UInt32 bytesToRead = 0; + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvHdr"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + /* + * rcvbuf, capacity, and filledupBytes were + * initialized when we wrote the headers. We begin by reading + * HTTP_HEADER_BUFSIZE bytes, repeatedly increasing the buffersize and + * reading again if necessary, until we have read the end-of-header + * marker, "\r\n\r\n", or have reached our maximum. + */ + client->capacity += HTTP_HEADER_BUFSIZE; + PKIX_CHECK(PKIX_PL_Realloc + (client->rcvBuf, + client->capacity, + (void **)&(client->rcvBuf), + plCtx), + PKIX_REALLOCFAILED); + + bytesToRead = client->capacity - client->filledupBytes; + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + PKIX_CHECK(callbackList->recvCallback + (client->socket, + (void *)&(client->rcvBuf[client->filledupBytes]), + bytesToRead, + &bytesRead, + plCtx), + PKIX_SOCKETRECVFAILED); + + if (bytesRead > 0) { + /* client->filledupBytes will be adjusted by + * pkix_pl_HttpDefaultClient_HdrCheckComplete */ + PKIX_CHECK( + pkix_pl_HttpDefaultClient_HdrCheckComplete(client, bytesRead, + pKeepGoing, + plCtx), + PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); + } else { + client->connectStatus = HTTP_RECV_HDR_PENDING; + *pKeepGoing = PKIX_FALSE; + } + +cleanup: + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdrContinue + * DESCRIPTION: + * + * This function determines whether the receiving of the HTTP headers for the + * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag + * indicating whether processing can continue without further input. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_RecvHdrContinue( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plCtx) +{ + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_RecvHdrContinue"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + PKIX_CHECK(callbackList->pollCallback + (client->socket, NULL, &bytesRead, plCtx), + PKIX_SOCKETPOLLFAILED); + + if (bytesRead > 0) { + client->filledupBytes += bytesRead; + + PKIX_CHECK(pkix_pl_HttpDefaultClient_HdrCheckComplete + (client, bytesRead, pKeepGoing, plCtx), + PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED); + + } else { + + *pKeepGoing = PKIX_FALSE; + + } + +cleanup: + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_RecvBody + * DESCRIPTION: + * + * This function processes the contents of the first buffer of a received + * HTTP-protocol message for the HttpDefaultClient "client", and stores in + * "pKeepGoing" a flag indicating whether processing can continue without + * further input. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_RecvBody( + PKIX_PL_HttpDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plCtx) +{ + PKIX_Int32 bytesRead = 0; + PKIX_Int32 bytesToRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvBody"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + callbackList = (PKIX_PL_Socket_Callback *)client->callbackList; + + if (client->rcv_http_data_len != HTTP_UNKNOWN_CONTENT_LENGTH) { + bytesToRead = client->rcv_http_data_len - + client->filledupBytes; + } else { + /* Reading till the EOF. Context length is not known.*/ + /* Check the buffer capacity: increase and + * reallocate if it is low. */ + int freeBuffSize = client->capacity - client->filledupBytes; + if (freeBuffSize < HTTP_MIN_AVAILABLE_BUFFER_SIZE) { + /* New length will be consist of available(downloaded) bytes, + * plus remaining capacity, plus new expansion. */ + int currBuffSize = client->capacity; + /* Try to increase the buffer by 4K */ + unsigned int newLength = currBuffSize + HTTP_DATA_BUFSIZE; + if (client->maxResponseLen > 0 && + newLength > client->maxResponseLen) { + newLength = client->maxResponseLen; + } + /* Check if we can grow the buffer and report an error if + * new size is not larger than the current size of the buffer.*/ + if (newLength <= client->filledupBytes) { + client->rcv_http_data_len = client->filledupBytes; + client->connectStatus = HTTP_ERROR; + *pKeepGoing = PKIX_FALSE; + goto cleanup; + } + if (client->capacity < newLength) { + client->capacity = newLength; + PKIX_CHECK( + PKIX_PL_Realloc(client->rcvBuf, newLength, + (void**)&client->rcvBuf, plCtx), + PKIX_REALLOCFAILED); + freeBuffSize = client->capacity - + client->filledupBytes; + } + } + bytesToRead = freeBuffSize; + } + + /* Use poll callback if waiting on non-blocking IO */ + if (client->connectStatus == HTTP_RECV_BODY_PENDING) { + PKIX_CHECK(callbackList->pollCallback + (client->socket, NULL, &bytesRead, plCtx), + PKIX_SOCKETPOLLFAILED); + } else { + PKIX_CHECK(callbackList->recvCallback + (client->socket, + (void *)&(client->rcvBuf[client->filledupBytes]), + bytesToRead, + &bytesRead, + plCtx), + PKIX_SOCKETRECVFAILED); + } + + /* If bytesRead < 0, an error will be thrown by recvCallback, so + * need to handle >= 0 cases. */ + + /* bytesRead == 0 - IO was blocked. */ + if (bytesRead == 0) { + client->connectStatus = HTTP_RECV_BODY_PENDING; + *pKeepGoing = PKIX_TRUE; + goto cleanup; + } + + /* We got something. Did we get it all? */ + client->filledupBytes += bytesRead; + + /* continue if not enough bytes read or if complete size of + * transfer is unknown */ + if (bytesToRead > bytesRead || + client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { + *pKeepGoing = PKIX_TRUE; + goto cleanup; + } + client->connectStatus = HTTP_COMPLETE; + *pKeepGoing = PKIX_FALSE; + +cleanup: + if (pkixErrorResult && pkixErrorResult->errCode == + PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED) { + if (client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) { + client->rcv_http_data_len = client->filledupBytes; + client->connectStatus = HTTP_COMPLETE; + *pKeepGoing = PKIX_FALSE; + PKIX_DECREF(pkixErrorResult); + } else { + client->connectStatus = HTTP_ERROR; + } + } + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_HttpDefaultClient_Dispatch + * DESCRIPTION: + * + * This function is the state machine dispatcher for the HttpDefaultClient + * pointed to by "client". Results are returned by changes to various fields + * in the context. + * + * PARAMETERS: + * "client" + * The address of the HttpDefaultClient object. Must be non-NULL. + * "plCtx" + * 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 HttpDefaultClient 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_pl_HttpDefaultClient_Dispatch( + PKIX_PL_HttpDefaultClient *client, + void *plCtx) +{ + PKIX_UInt32 bytesTransferred = 0; + PKIX_Boolean keepGoing = PKIX_TRUE; + + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Dispatch"); + PKIX_NULLCHECK_ONE(client); + + while (keepGoing) { + switch (client->connectStatus) { + case HTTP_CONNECT_PENDING: + PKIX_CHECK(pkix_pl_HttpDefaultClient_ConnectContinue + (client, &keepGoing, plCtx), + PKIX_HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED); + break; + case HTTP_CONNECTED: + PKIX_CHECK(pkix_pl_HttpDefaultClient_Send + (client, &keepGoing, &bytesTransferred, plCtx), + PKIX_HTTPDEFAULTCLIENTSENDFAILED); + break; + case HTTP_SEND_PENDING: + PKIX_CHECK(pkix_pl_HttpDefaultClient_SendContinue + (client, &keepGoing, &bytesTransferred, plCtx), + PKIX_HTTPDEFAULTCLIENTSENDCONTINUEFAILED); + break; + case HTTP_RECV_HDR: + PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdr + (client, &keepGoing, plCtx), + PKIX_HTTPDEFAULTCLIENTRECVHDRFAILED); + break; + case HTTP_RECV_HDR_PENDING: + PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdrContinue + (client, &keepGoing, plCtx), + PKIX_HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED); + break; + case HTTP_RECV_BODY: + case HTTP_RECV_BODY_PENDING: + PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvBody + (client, &keepGoing, plCtx), + PKIX_HTTPDEFAULTCLIENTRECVBODYFAILED); + break; + case HTTP_ERROR: + case HTTP_COMPLETE: + keepGoing = PKIX_FALSE; + break; + case HTTP_NOT_CONNECTED: + default: + PKIX_ERROR(PKIX_HTTPDEFAULTCLIENTINILLEGALSTATE); + } + } + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); +} + +/* + * --HttpClient vtable functions + * See comments in ocspt.h for the function (wrappers) that return SECStatus. + * The functions that return PKIX_Error* are the libpkix implementations. + */ + +PKIX_Error * +pkix_pl_HttpDefaultClient_CreateSession( + const char *host, + PRUint16 portnum, + SEC_HTTP_SERVER_SESSION *pSession, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_CreateSession"); + PKIX_NULLCHECK_TWO(host, pSession); + + PKIX_CHECK(pkix_pl_HttpDefaultClient_Create + (host, portnum, &client, plCtx), + PKIX_HTTPDEFAULTCLIENTCREATEFAILED); + + *pSession = (SEC_HTTP_SERVER_SESSION)client; + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +PKIX_Error * +pkix_pl_HttpDefaultClient_KeepAliveSession( + SEC_HTTP_SERVER_SESSION session, + PRPollDesc **pPollDesc, + void *plCtx) +{ + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_KeepAliveSession"); + PKIX_NULLCHECK_TWO(session, pPollDesc); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)session, + PKIX_HTTPDEFAULTCLIENT_TYPE, + plCtx), + PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); + + /* XXX Not implemented */ + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +PKIX_Error * +pkix_pl_HttpDefaultClient_RequestCreate( + SEC_HTTP_SERVER_SESSION session, + const char *http_protocol_variant, /* usually "http" */ + const char *path_and_query_string, + const char *http_request_method, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION *pRequest, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + PKIX_PL_Socket *socket = NULL; + PKIX_PL_Socket_Callback *callbackList = NULL; + PRFileDesc *fileDesc = NULL; + PRErrorCode status = 0; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RequestCreate"); + PKIX_NULLCHECK_TWO(session, pRequest); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)session, + PKIX_HTTPDEFAULTCLIENT_TYPE, + plCtx), + PKIX_SESSIONNOTANHTTPDEFAULTCLIENT); + + client = (PKIX_PL_HttpDefaultClient *)session; + + /* We only know how to do http */ + if (PORT_Strncasecmp(http_protocol_variant, "http", 4) != 0) { + PKIX_ERROR(PKIX_UNRECOGNIZEDPROTOCOLREQUESTED); + } + + if (PORT_Strncasecmp(http_request_method, "POST", 4) == 0) { + client->send_http_method = HTTP_POST_METHOD; + } else if (PORT_Strncasecmp(http_request_method, "GET", 3) == 0) { + client->send_http_method = HTTP_GET_METHOD; + } else { + /* We only know how to do POST and GET */ + PKIX_ERROR(PKIX_UNRECOGNIZEDREQUESTMETHOD); + } + + if (path_and_query_string) { + /* "path_and_query_string" is a parsing result by CERT_GetURL + * function that adds "end of line" to the value. OK to dup + * the string. */ + client->path = PORT_Strdup(path_and_query_string); + if (!client->path) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + } + + client->timeout = timeout; + +#if 0 + PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection + (timeout, + "variation.red.iplanet.com", /* (char *)client->host, */ + 2001, /* client->portnum, */ + &status, + &socket, + plCtx), + PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); +#else + PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection + (timeout, + (char *)client->host, + client->portnum, + &status, + &socket, + plCtx), + PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED); +#endif + + client->socket = socket; + + PKIX_CHECK(pkix_pl_Socket_GetCallbackList + (socket, &callbackList, plCtx), + PKIX_SOCKETGETCALLBACKLISTFAILED); + + client->callbackList = (void *)callbackList; + + PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc + (socket, &fileDesc, plCtx), + PKIX_SOCKETGETPRFILEDESCFAILED); + + client->pollDesc.fd = fileDesc; + client->pollDesc.in_flags = 0; + client->pollDesc.out_flags = 0; + + client->send_http_data = NULL; + client->send_http_data_len = 0; + client->send_http_content_type = NULL; + + client->connectStatus = + ((status == 0) ? HTTP_CONNECTED : HTTP_CONNECT_PENDING); + + /* Request object is the same object as Session object */ + PKIX_INCREF(client); + *pRequest = client; + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +PKIX_Error * +pkix_pl_HttpDefaultClient_SetPostData( + SEC_HTTP_REQUEST_SESSION request, + const char *http_data, + const PRUint32 http_data_len, + const char *http_content_type, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_SetPostData"); + PKIX_NULLCHECK_ONE(request); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)request, + PKIX_HTTPDEFAULTCLIENT_TYPE, + plCtx), + PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); + + client = (PKIX_PL_HttpDefaultClient *)request; + + client->send_http_data = http_data; + client->send_http_data_len = http_data_len; + client->send_http_content_type = http_content_type; + + /* Caller is allowed to give NULL or empty string for content_type */ + if ((client->send_http_content_type == NULL) || + (*(client->send_http_content_type) == '\0')) { + client->send_http_content_type = "application/ocsp-request"; + } + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +PKIX_Error * +pkix_pl_HttpDefaultClient_TrySendAndReceive( + SEC_HTTP_REQUEST_SESSION request, + PRUint16 *http_response_code, + const char **http_response_content_type, + const char **http_response_headers, + const char **http_response_data, + PRUint32 *http_response_data_len, + PRPollDesc **pPollDesc, + SECStatus *pSECReturn, + void *plCtx) +{ + PKIX_PL_HttpDefaultClient *client = NULL; + PKIX_UInt32 postLen = 0; + PRPollDesc *pollDesc = NULL; + char *sendbuf = NULL; + char portstr[16]; + + PKIX_ENTER + (HTTPDEFAULTCLIENT, + "pkix_pl_HttpDefaultClient_TrySendAndReceive"); + + PKIX_NULLCHECK_ONE(request); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)request, + PKIX_HTTPDEFAULTCLIENT_TYPE, + plCtx), + PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); + + client = (PKIX_PL_HttpDefaultClient *)request; + + if (!pPollDesc && client->timeout == 0) { + PKIX_ERROR_FATAL(PKIX_NULLARGUMENT); + } + + if (pPollDesc) { + pollDesc = *pPollDesc; + } + + /* if not continuing from an earlier WOULDBLOCK return... */ + if (pollDesc == NULL) { + + if (!((client->connectStatus == HTTP_CONNECTED) || + (client->connectStatus == HTTP_CONNECT_PENDING))) { + PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); + } + + /* Did caller provide a value for response length? */ + if (http_response_data_len != NULL) { + client->pRcv_http_data_len = http_response_data_len; + client->maxResponseLen = *http_response_data_len; + } + + client->rcv_http_response_code = http_response_code; + client->rcv_http_content_type = http_response_content_type; + client->rcv_http_headers = http_response_headers; + client->rcv_http_data = http_response_data; + + /* prepare the message */ + portstr[0] = '\0'; + if (client->portnum != 80) { + PR_snprintf(portstr, sizeof(portstr), ":%d", + client->portnum); + } + + if (client->send_http_method == HTTP_POST_METHOD) { + sendbuf = PR_smprintf + ("POST %s HTTP/1.0\r\nHost: %s%s\r\n" + "Content-Type: %s\r\nContent-Length: %u\r\n\r\n", + client->path, + client->host, + portstr, + client->send_http_content_type, + client->send_http_data_len); + postLen = PORT_Strlen(sendbuf); + + client->POSTLen = postLen + client->send_http_data_len; + + /* allocate postBuffer big enough for header + data */ + PKIX_CHECK(PKIX_PL_Malloc + (client->POSTLen, + (void **)&(client->POSTBuf), + plCtx), + PKIX_MALLOCFAILED); + + /* copy header into postBuffer */ + PORT_Memcpy(client->POSTBuf, sendbuf, postLen); + + /* append data after header */ + PORT_Memcpy(&client->POSTBuf[postLen], + client->send_http_data, + client->send_http_data_len); + + /* PR_smprintf_free original header buffer */ + PR_smprintf_free(sendbuf); + sendbuf = NULL; + + } else if (client->send_http_method == HTTP_GET_METHOD) { + client->GETBuf = PR_smprintf + ("GET %s HTTP/1.0\r\nHost: %s%s\r\n\r\n", + client->path, + client->host, + portstr); + client->GETLen = PORT_Strlen(client->GETBuf); + } + + } + + /* continue according to state */ + PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plCtx), + PKIX_HTTPDEFAULTCLIENTDISPATCHFAILED); + + switch (client->connectStatus) { + case HTTP_CONNECT_PENDING: + case HTTP_SEND_PENDING: + case HTTP_RECV_HDR_PENDING: + case HTTP_RECV_BODY_PENDING: + pollDesc = &(client->pollDesc); + *pSECReturn = SECWouldBlock; + break; + case HTTP_ERROR: + /* Did caller provide a pointer for length? */ + if (client->pRcv_http_data_len != NULL) { + /* Was error "response too big?" */ + if (client->rcv_http_data_len != + HTTP_UNKNOWN_CONTENT_LENGTH && + client->maxResponseLen >= + client->rcv_http_data_len) { + /* Yes, report needed space */ + *(client->pRcv_http_data_len) = + client->rcv_http_data_len; + } else { + /* No, report problem other than size */ + *(client->pRcv_http_data_len) = 0; + } + } + + pollDesc = NULL; + *pSECReturn = SECFailure; + break; + case HTTP_COMPLETE: + *(client->rcv_http_response_code) = + client->responseCode; + if (client->pRcv_http_data_len != NULL) { + *http_response_data_len = + client->rcv_http_data_len; + } + if (client->rcv_http_data != NULL) { + *(client->rcv_http_data) = client->rcvBuf; + } + pollDesc = NULL; + *pSECReturn = SECSuccess; + break; + case HTTP_NOT_CONNECTED: + case HTTP_CONNECTED: + case HTTP_RECV_HDR: + case HTTP_RECV_BODY: + default: + pollDesc = NULL; + *pSECReturn = SECFailure; + PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE); + break; + } + + if (pPollDesc) { + *pPollDesc = pollDesc; + } + +cleanup: + if (sendbuf) { + PR_smprintf_free(sendbuf); + } + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +PKIX_Error * +pkix_pl_HttpDefaultClient_Cancel( + SEC_HTTP_REQUEST_SESSION request, + void *plCtx) +{ + PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Cancel"); + PKIX_NULLCHECK_ONE(request); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)request, + PKIX_HTTPDEFAULTCLIENT_TYPE, + plCtx), + PKIX_REQUESTNOTANHTTPDEFAULTCLIENT); + + /* XXX Not implemented */ + +cleanup: + + PKIX_RETURN(HTTPDEFAULTCLIENT); + +} + +SECStatus +pkix_pl_HttpDefaultClient_CreateSessionFcn( + const char *host, + PRUint16 portnum, + SEC_HTTP_SERVER_SESSION *pSession) +{ + PKIX_Error *err = pkix_pl_HttpDefaultClient_CreateSession + (host, portnum, pSession, plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_KeepAliveSessionFcn( + SEC_HTTP_SERVER_SESSION session, + PRPollDesc **pPollDesc) +{ + PKIX_Error *err = pkix_pl_HttpDefaultClient_KeepAliveSession + (session, pPollDesc, plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_FreeSessionFcn( + SEC_HTTP_SERVER_SESSION session) +{ + PKIX_Error *err = + PKIX_PL_Object_DecRef((PKIX_PL_Object *)(session), plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_RequestCreateFcn( + SEC_HTTP_SERVER_SESSION session, + const char *http_protocol_variant, /* usually "http" */ + const char *path_and_query_string, + const char *http_request_method, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION *pRequest) +{ + PKIX_Error *err = pkix_pl_HttpDefaultClient_RequestCreate + (session, + http_protocol_variant, + path_and_query_string, + http_request_method, + timeout, + pRequest, + plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_SetPostDataFcn( + SEC_HTTP_REQUEST_SESSION request, + const char *http_data, + const PRUint32 http_data_len, + const char *http_content_type) +{ + PKIX_Error *err = + pkix_pl_HttpDefaultClient_SetPostData(request, http_data, + http_data_len, + http_content_type, + plContext); + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_AddHeaderFcn( + SEC_HTTP_REQUEST_SESSION request, + const char *http_header_name, + const char *http_header_value) +{ + /* Not supported */ + return SECFailure; +} + +SECStatus +pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn( + SEC_HTTP_REQUEST_SESSION request, + PRPollDesc **pPollDesc, + PRUint16 *http_response_code, + const char **http_response_content_type, + const char **http_response_headers, + const char **http_response_data, + PRUint32 *http_response_data_len) +{ + SECStatus rv = SECFailure; + + PKIX_Error *err = pkix_pl_HttpDefaultClient_TrySendAndReceive + (request, + http_response_code, + http_response_content_type, + http_response_headers, + http_response_data, + http_response_data_len, + pPollDesc, + &rv, + plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return rv; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_CancelFcn( + SEC_HTTP_REQUEST_SESSION request) +{ + PKIX_Error *err = pkix_pl_HttpDefaultClient_Cancel(request, plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} + +SECStatus +pkix_pl_HttpDefaultClient_FreeFcn( + SEC_HTTP_REQUEST_SESSION request) +{ + PKIX_Error *err = + PKIX_PL_Object_DecRef((PKIX_PL_Object *)(request), plContext); + + if (err) { + PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext); + return SECFailure; + } + return SECSuccess; +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h new file mode 100644 index 0000000000..91916a0ab4 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h @@ -0,0 +1,139 @@ +/* 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_pl_httpdefaultclient.h + * + * HTTPDefaultClient Object Type Definition + * + */ + +#ifndef _PKIX_PL_HTTPDEFAULTCLIENT_H +#define _PKIX_PL_HTTPDEFAULTCLIENT_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HTTP_DATA_BUFSIZE 4096 +#define HTTP_HEADER_BUFSIZE 1024 +#define HTTP_MIN_AVAILABLE_BUFFER_SIZE 512 + +typedef enum { + HTTP_NOT_CONNECTED, + HTTP_CONNECT_PENDING, + HTTP_CONNECTED, + HTTP_SEND_PENDING, + HTTP_RECV_HDR, + HTTP_RECV_HDR_PENDING, + HTTP_RECV_BODY, + HTTP_RECV_BODY_PENDING, + HTTP_COMPLETE, + HTTP_ERROR +} HttpConnectStatus; + +typedef enum { + HTTP_POST_METHOD, + HTTP_GET_METHOD +} HttpMethod; + +struct PKIX_PL_HttpDefaultClientStruct { + HttpConnectStatus connectStatus; + PRUint16 portnum; + PRIntervalTime timeout; + PKIX_UInt32 bytesToWrite; + PKIX_UInt32 send_http_data_len; + PKIX_UInt32 rcv_http_data_len; + PKIX_UInt32 capacity; + PKIX_UInt32 filledupBytes; + PKIX_UInt32 responseCode; + PKIX_UInt32 maxResponseLen; + PKIX_UInt32 GETLen; + PKIX_UInt32 POSTLen; + PRUint32 *pRcv_http_data_len; + PRPollDesc pollDesc; + void *callbackList; /* cast this to (PKIX_PL_Socket_Callback *) */ + char *GETBuf; + char *POSTBuf; + char *rcvBuf; + char *host; + char *path; + char *rcvContentType; + void *rcvHeaders; + HttpMethod send_http_method; + const char *send_http_content_type; + const char *send_http_data; + PRUint16 *rcv_http_response_code; + const char **rcv_http_content_type; + const char **rcv_http_headers; + const char **rcv_http_data; + PKIX_PL_Socket *socket; + void *plContext; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext); + +SECStatus +pkix_pl_HttpDefaultClient_CreateSessionFcn( + const char *host, + PRUint16 portnum, + SEC_HTTP_SERVER_SESSION *pSession); + +SECStatus +pkix_pl_HttpDefaultClient_KeepAliveSessionFcn( + SEC_HTTP_SERVER_SESSION session, + PRPollDesc **pPollDesc); + +SECStatus +pkix_pl_HttpDefaultClient_FreeSessionFcn( + SEC_HTTP_SERVER_SESSION session); + +SECStatus +pkix_pl_HttpDefaultClient_RequestCreateFcn( + SEC_HTTP_SERVER_SESSION session, + const char *http_protocol_variant, /* usually "http" */ + const char *path_and_query_string, + const char *http_request_method, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION *pRequest); + +SECStatus +pkix_pl_HttpDefaultClient_SetPostDataFcn( + SEC_HTTP_REQUEST_SESSION request, + const char *http_data, + const PRUint32 http_data_len, + const char *http_content_type); + +SECStatus +pkix_pl_HttpDefaultClient_AddHeaderFcn( + SEC_HTTP_REQUEST_SESSION request, + const char *http_header_name, + const char *http_header_value); + +SECStatus +pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn( + SEC_HTTP_REQUEST_SESSION request, + PRPollDesc **pPollDesc, + PRUint16 *http_response_code, + const char **http_response_content_type, + const char **http_response_headers, + const char **http_response_data, + PRUint32 *http_response_data_len); + +SECStatus +pkix_pl_HttpDefaultClient_CancelFcn( + SEC_HTTP_REQUEST_SESSION request); + +SECStatus +pkix_pl_HttpDefaultClient_FreeFcn( + SEC_HTTP_REQUEST_SESSION request); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_HTTPDEFAULTCLIENT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c new file mode 100644 index 0000000000..dd32334ab3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c @@ -0,0 +1,1113 @@ +/* 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_pl_ldapcertstore.c + * + * LDAPCertStore Function Definitions + * + */ + +/* We can't decode the length of a message without at least this many bytes */ +#define MINIMUM_MSG_LENGTH 5 + +#include "pkix_pl_ldapcertstore.h" + +/* --Private-Ldap-CertStore-Database-Functions----------------------- */ + +/* + * FUNCTION: pkix_pl_LdapCertStore_DecodeCrossCertPair + * DESCRIPTION: + * + * This function decodes a DER-encoded CrossCertPair pointed to by + * "responseList" and extracts and decodes the Certificates in that pair, + * adding the resulting Certs, if the decoding was successful, to the List + * (possibly empty) pointed to by "certList". If none of the objects + * can be decoded into a Cert, the List is returned unchanged. + * + * PARAMETERS: + * "derCCPItem" + * The address of the SECItem containing the DER representation of the + * CrossCertPair. Must be non-NULL. + * "certList" + * The address of the List to which the decoded Certs are added. May be + * empty, but 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 CertStore 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_pl_LdapCertStore_DecodeCrossCertPair( + SECItem *derCCPItem, + PKIX_List *certList, + void *plContext) +{ + LDAPCertPair certPair = {{ siBuffer, NULL, 0 }, { siBuffer, NULL, 0 }}; + SECStatus rv = SECFailure; + + PLArenaPool *tempArena = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DecodeCrossCertPair"); + PKIX_NULLCHECK_TWO(derCCPItem, certList); + + tempArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!tempArena) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + rv = SEC_ASN1DecodeItem(tempArena, &certPair, PKIX_PL_LDAPCrossCertPairTemplate, + derCCPItem); + if (rv != SECSuccess) { + goto cleanup; + } + + if (certPair.forward.data != NULL) { + + PKIX_CHECK( + pkix_pl_Cert_CreateToList(&certPair.forward, certList, + plContext), + PKIX_CERTCREATETOLISTFAILED); + } + + if (certPair.reverse.data != NULL) { + + PKIX_CHECK( + pkix_pl_Cert_CreateToList(&certPair.reverse, certList, + plContext), + PKIX_CERTCREATETOLISTFAILED); + } + +cleanup: + if (tempArena) { + PORT_FreeArena(tempArena, PR_FALSE); + } + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_BuildCertList + * DESCRIPTION: + * + * This function takes a List of LdapResponse objects pointed to by + * "responseList" and extracts and decodes the Certificates in those responses, + * storing the List of those Certificates at "pCerts". If none of the objects + * can be decoded into a Cert, the returned List is empty. + * + * PARAMETERS: + * "responseList" + * The address of the List of LdapResponses. Must be non-NULL. + * "pCerts" + * 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 CertStore 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_pl_LdapCertStore_BuildCertList( + PKIX_List *responseList, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_UInt32 numResponses = 0; + PKIX_UInt32 respIx = 0; + LdapAttrMask attrBits = 0; + PKIX_PL_LdapResponse *response = NULL; + PKIX_List *certList = NULL; + LDAPMessage *message = NULL; + LDAPSearchResponseEntry *sre = NULL; + LDAPSearchResponseAttr **sreAttrArray = NULL; + LDAPSearchResponseAttr *sreAttr = NULL; + SECItem *attrType = NULL; + SECItem **attrVal = NULL; + SECItem *derCertItem = NULL; + + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCertList"); + PKIX_NULLCHECK_TWO(responseList, pCerts); + + PKIX_CHECK(PKIX_List_Create(&certList, plContext), + PKIX_LISTCREATEFAILED); + + /* extract certs from response */ + PKIX_CHECK(PKIX_List_GetLength + (responseList, &numResponses, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (respIx = 0; respIx < numResponses; respIx++) { + PKIX_CHECK(PKIX_List_GetItem + (responseList, + respIx, + (PKIX_PL_Object **)&response, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_pl_LdapResponse_GetMessage + (response, &message, plContext), + PKIX_LDAPRESPONSEGETMESSAGEFAILED); + + sre = &(message->protocolOp.op.searchResponseEntryMsg); + sreAttrArray = sre->attributes; + + /* Get next element of null-terminated array */ + sreAttr = *sreAttrArray++; + while (sreAttr != NULL) { + attrType = &(sreAttr->attrType); + PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit + (attrType, &attrBits, plContext), + PKIX_LDAPREQUESTATTRTYPETOBITFAILED); + /* Is this attrVal a Certificate? */ + if (((LDAPATTR_CACERT | LDAPATTR_USERCERT) & + attrBits) == attrBits) { + attrVal = sreAttr->val; + derCertItem = *attrVal++; + while (derCertItem != 0) { + /* create a PKIX_PL_Cert from derCert */ + PKIX_CHECK(pkix_pl_Cert_CreateToList + (derCertItem, certList, plContext), + PKIX_CERTCREATETOLISTFAILED); + derCertItem = *attrVal++; + } + } else if ((LDAPATTR_CROSSPAIRCERT & attrBits) == attrBits){ + /* Is this attrVal a CrossPairCertificate? */ + attrVal = sreAttr->val; + derCertItem = *attrVal++; + while (derCertItem != 0) { + /* create PKIX_PL_Certs from derCert */ + PKIX_CHECK(pkix_pl_LdapCertStore_DecodeCrossCertPair + (derCertItem, certList, plContext), + PKIX_LDAPCERTSTOREDECODECROSSCERTPAIRFAILED); + derCertItem = *attrVal++; + } + } + sreAttr = *sreAttrArray++; + } + PKIX_DECREF(response); + } + + *pCerts = certList; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(certList); + } + + PKIX_DECREF(response); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_BuildCrlList + * DESCRIPTION: + * + * This function takes a List of LdapResponse objects pointed to by + * "responseList" and extracts and decodes the CRLs in those responses, storing + * the List of those CRLs at "pCrls". If none of the objects can be decoded + * into a CRL, the returned List is empty. + * + * PARAMETERS: + * "responseList" + * The address of the List of LdapResponses. Must be non-NULL. + * "pCrls" + * 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 CertStore 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_pl_LdapCertStore_BuildCrlList( + PKIX_List *responseList, + PKIX_List **pCrls, + void *plContext) +{ + PKIX_UInt32 numResponses = 0; + PKIX_UInt32 respIx = 0; + LdapAttrMask attrBits = 0; + CERTSignedCrl *nssCrl = NULL; + PKIX_PL_LdapResponse *response = NULL; + PKIX_List *crlList = NULL; + PKIX_PL_CRL *crl = NULL; + LDAPMessage *message = NULL; + LDAPSearchResponseEntry *sre = NULL; + LDAPSearchResponseAttr **sreAttrArray = NULL; + LDAPSearchResponseAttr *sreAttr = NULL; + SECItem *attrType = NULL; + SECItem **attrVal = NULL; + SECItem *derCrlCopy = NULL; + SECItem *derCrlItem = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCrlList"); + PKIX_NULLCHECK_TWO(responseList, pCrls); + + PKIX_CHECK(PKIX_List_Create(&crlList, plContext), + PKIX_LISTCREATEFAILED); + + /* extract crls from response */ + PKIX_CHECK(PKIX_List_GetLength + (responseList, &numResponses, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (respIx = 0; respIx < numResponses; respIx++) { + PKIX_CHECK(PKIX_List_GetItem + (responseList, + respIx, + (PKIX_PL_Object **)&response, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_pl_LdapResponse_GetMessage + (response, &message, plContext), + PKIX_LDAPRESPONSEGETMESSAGEFAILED); + + sre = &(message->protocolOp.op.searchResponseEntryMsg); + sreAttrArray = sre->attributes; + + /* Get next element of null-terminated array */ + sreAttr = *sreAttrArray++; + while (sreAttr != NULL) { + attrType = &(sreAttr->attrType); + PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit + (attrType, &attrBits, plContext), + PKIX_LDAPREQUESTATTRTYPETOBITFAILED); + /* Is this attrVal a Revocation List? */ + if (((LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST) & + attrBits) == attrBits) { + attrVal = sreAttr->val; + derCrlItem = *attrVal++; + while (derCrlItem != 0) { + /* create a PKIX_PL_Crl from derCrl */ + derCrlCopy = SECITEM_DupItem(derCrlItem); + if (!derCrlCopy) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + /* crl will be based on derCrlCopy, but wont + * own the der. */ + nssCrl = + CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, + SEC_CRL_TYPE, + CRL_DECODE_DONT_COPY_DER | + CRL_DECODE_SKIP_ENTRIES); + if (!nssCrl) { + SECITEM_FreeItem(derCrlCopy, PKIX_TRUE); + continue; + } + /* pkix crl own the der. */ + PKIX_CHECK( + pkix_pl_CRL_CreateWithSignedCRL(nssCrl, + derCrlCopy, NULL, &crl, plContext), + PKIX_CRLCREATEWITHSIGNEDCRLFAILED); + /* Left control over memory pointed by derCrlCopy and + * nssCrl to pkix crl. */ + derCrlCopy = NULL; + nssCrl = NULL; + PKIX_CHECK(PKIX_List_AppendItem + (crlList, (PKIX_PL_Object *) crl, plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(crl); + derCrlItem = *attrVal++; + } + /* Clean up after PKIX_CHECK_ONLY_FATAL */ + pkixTempErrorReceived = PKIX_FALSE; + } + sreAttr = *sreAttrArray++; + } + PKIX_DECREF(response); + } + + *pCrls = crlList; + crlList = NULL; +cleanup: + if (derCrlCopy) { + SECITEM_FreeItem(derCrlCopy, PKIX_TRUE); + } + if (nssCrl) { + SEC_DestroyCrl(nssCrl); + } + PKIX_DECREF(crl); + PKIX_DECREF(crlList); + PKIX_DECREF(response); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_DestroyAVAList + * DESCRIPTION: + * + * This function frees the space allocated for the components of the + * equalFilters that make up the andFilter pointed to by "filter". + * + * PARAMETERS: + * "requestParams" + * The address of the andFilter whose components are to be freed. 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 CertStore 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_pl_LdapCertStore_DestroyAVAList( + LDAPNameComponent **nameComponents, + void *plContext) +{ + LDAPNameComponent **currentNC = NULL; + unsigned char *component = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DestroyAVAList"); + PKIX_NULLCHECK_ONE(nameComponents); + + /* Set currentNC to point to first AVA pointer */ + currentNC = nameComponents; + + while ((*currentNC) != NULL) { + component = (*currentNC)->attrValue; + if (component != NULL) { + PORT_Free(component); + } + currentNC++; + } + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_MakeNameAVAList + * DESCRIPTION: + * + * This function allocates space from the arena pointed to by "arena" to + * construct a filter that will match components of the X500Name pointed to + * by "name", and stores the resulting filter at "pFilter". + * + * "name" is checked for commonName and organizationName components (cn=, + * and o=). The component strings are extracted using the family of + * CERT_Get* functions, and each must be freed with PORT_Free. + * + * It is not clear which components should be in a request, so, for now, + * we stop adding components after we have found one. + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool used in creating the filter. Must be + * non-NULL. + * "name" + * The address of the X500Name whose components define the desired + * matches. Must be non-NULL. + * "pList" + * The address at which the result 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 CertStore 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_pl_LdapCertStore_MakeNameAVAList( + PLArenaPool *arena, + PKIX_PL_X500Name *subjectName, + LDAPNameComponent ***pList, + void *plContext) +{ + LDAPNameComponent **setOfNameComponents; + LDAPNameComponent *currentNameComponent = NULL; + PKIX_UInt32 componentsPresent = 0; + void *v = NULL; + unsigned char *component = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_MakeNameAVAList"); + PKIX_NULLCHECK_THREE(arena, subjectName, pList); + + /* Increase this if additional components may be extracted */ +#define MAX_NUM_COMPONENTS 3 + + /* Space for (MAX_NUM_COMPONENTS + 1) pointers to LDAPNameComponents */ + PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc, + (arena, (MAX_NUM_COMPONENTS + 1)*sizeof(LDAPNameComponent *))); + setOfNameComponents = (LDAPNameComponent **)v; + + /* Space for MAX_NUM_COMPONENTS LDAPNameComponents */ + PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray, + (arena, LDAPNameComponent, MAX_NUM_COMPONENTS)); + + currentNameComponent = (LDAPNameComponent *)v; + + /* Try for commonName */ + PKIX_CHECK(pkix_pl_X500Name_GetCommonName + (subjectName, &component, plContext), + PKIX_X500NAMEGETCOMMONNAMEFAILED); + if (component) { + setOfNameComponents[componentsPresent] = currentNameComponent; + currentNameComponent->attrType = (unsigned char *)"cn"; + currentNameComponent->attrValue = component; + componentsPresent++; + currentNameComponent++; + } + + /* + * The LDAP specification says we can send multiple name components + * in an "AND" filter, but the LDAP Servers don't seem to be able to + * handle such requests. So we'll quit after the cn component. + */ +#if 0 + /* Try for orgName */ + PKIX_CHECK(pkix_pl_X500Name_GetOrgName + (subjectName, &component, plContext), + PKIX_X500NAMEGETORGNAMEFAILED); + if (component) { + setOfNameComponents[componentsPresent] = currentNameComponent; + currentNameComponent->attrType = (unsigned char *)"o"; + currentNameComponent->attrValue = component; + componentsPresent++; + currentNameComponent++; + } + + /* Try for countryName */ + PKIX_CHECK(pkix_pl_X500Name_GetCountryName + (subjectName, &component, plContext), + PKIX_X500NAMEGETCOUNTRYNAMEFAILED); + if (component) { + setOfNameComponents[componentsPresent] = currentNameComponent; + currentNameComponent->attrType = (unsigned char *)"c"; + currentNameComponent->attrValue = component; + componentsPresent++; + currentNameComponent++; + } +#endif + + setOfNameComponents[componentsPresent] = NULL; + + *pList = setOfNameComponents; + +cleanup: + + PKIX_RETURN(CERTSTORE); + +} + +#if 0 +/* + * FUNCTION: pkix_pl_LdapCertstore_ConvertCertResponses + * DESCRIPTION: + * + * This function processes the List of LDAPResponses pointed to by "responses" + * into a List of resulting Certs, storing the result at "pCerts". If there + * are no responses converted successfully, a NULL may be stored. + * + * PARAMETERS: + * "responses" + * The LDAPResponses whose contents are to be converted. Must be non-NULL. + * "pCerts" + * Address at which the returned 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 CertStore 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_pl_LdapCertStore_ConvertCertResponses( + PKIX_List *responses, + PKIX_List **pCerts, + void *plContext) +{ + PKIX_List *unfiltered = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_ConvertCertResponses"); + PKIX_NULLCHECK_TWO(responses, pCerts); + + /* + * We have a List of LdapResponse objects that have to be + * turned into Certs. + */ + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList + (responses, &unfiltered, plContext), + PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); + + *pCerts = unfiltered; + +cleanup: + + PKIX_RETURN(CERTSTORE); +} +#endif + +/* + * FUNCTION: pkix_pl_LdapCertStore_GetCert + * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_LdapCertStore_GetCert( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + PLArenaPool *requestArena = NULL; + LDAPRequestParams requestParams; + void *pollDesc = NULL; + PKIX_Int32 minPathLen = 0; + PKIX_Boolean cacheFlag = PKIX_FALSE; + PKIX_ComCertSelParams *params = NULL; + PKIX_PL_LdapCertStoreContext *lcs = NULL; + PKIX_List *responses = NULL; + PKIX_List *unfilteredCerts = NULL; + PKIX_List *filteredCerts = NULL; + PKIX_PL_X500Name *subjectName = 0; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert"); + PKIX_NULLCHECK_THREE(store, selector, pCertList); + + requestParams.baseObject = "c=US"; + requestParams.scope = WHOLE_SUBTREE; + requestParams.derefAliases = NEVER_DEREF; + requestParams.sizeLimit = 0; + requestParams.timeLimit = 0; + + /* Prepare elements for request filter */ + + /* + * Get a short-lived arena. We'll be done with this space once + * the request is encoded. + */ + requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!requestArena) { + PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); + } + + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams + (selector, ¶ms, plContext), + PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED); + + /* + * If we have the subject name for the desired subject, + * ask the server for Certs with that subject. + */ + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (params, &subjectName, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints + (params, &minPathLen, plContext), + PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED); + + if (subjectName) { + PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList + (requestArena, + subjectName, + &(requestParams.nc), + plContext), + PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED); + + if (*requestParams.nc == NULL) { + /* + * The subjectName may not include any components + * that we know how to encode. We do not return + * an error, because the caller did not necessarily + * do anything wrong, but we return an empty List. + */ + PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, + (requestArena, PR_FALSE)); + + PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_SetImmutable + (filteredCerts, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pNBIOContext = NULL; + *pCertList = filteredCerts; + filteredCerts = NULL; + goto cleanup; + } + } else { + PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY); + } + + /* Prepare attribute field of request */ + + requestParams.attributes = 0; + + if (minPathLen < 0) { + requestParams.attributes |= LDAPATTR_USERCERT; + } + + if (minPathLen > -2) { + requestParams.attributes |= + LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT; + } + + /* All request fields are done */ + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&lcs, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest + ((PKIX_PL_LdapClient *)lcs, + &requestParams, + &pollDesc, + &responses, + plContext), + PKIX_LDAPCLIENTINITIATEREQUESTFAILED); + + PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList + (requestParams.nc, plContext), + PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED); + + if (requestArena) { + PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, + (requestArena, PR_FALSE)); + requestArena = NULL; + } + + if (pollDesc != NULL) { + /* client is waiting for non-blocking I/O to complete */ + *pNBIOContext = (void *)pollDesc; + *pCertList = NULL; + goto cleanup; + } + /* LdapClient has given us a response! */ + + if (responses) { + PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag + (store, &cacheFlag, plContext), + PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); + + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList + (responses, &unfilteredCerts, plContext), + PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); + + PKIX_CHECK(pkix_CertSelector_Select + (selector, unfilteredCerts, &filteredCerts, plContext), + PKIX_CERTSELECTORSELECTFAILED); + } + + *pNBIOContext = NULL; + *pCertList = filteredCerts; + filteredCerts = NULL; + +cleanup: + + PKIX_DECREF(params); + PKIX_DECREF(subjectName); + PKIX_DECREF(responses); + PKIX_DECREF(unfilteredCerts); + PKIX_DECREF(filteredCerts); + PKIX_DECREF(lcs); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_GetCertContinue + * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_LdapCertStore_GetCertContinue( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *verifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + PKIX_Boolean cacheFlag = PKIX_FALSE; + PKIX_PL_LdapCertStoreContext *lcs = NULL; + void *pollDesc = NULL; + PKIX_List *responses = NULL; + PKIX_List *unfilteredCerts = NULL; + PKIX_List *filteredCerts = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCertContinue"); + PKIX_NULLCHECK_THREE(store, selector, pCertList); + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&lcs, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest + ((PKIX_PL_LdapClient *)lcs, &pollDesc, &responses, plContext), + PKIX_LDAPCLIENTRESUMEREQUESTFAILED); + + if (pollDesc != NULL) { + /* client is waiting for non-blocking I/O to complete */ + *pNBIOContext = (void *)pollDesc; + *pCertList = NULL; + goto cleanup; + } + /* LdapClient has given us a response! */ + + if (responses) { + PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag + (store, &cacheFlag, plContext), + PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); + + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList + (responses, &unfilteredCerts, plContext), + PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); + + PKIX_CHECK(pkix_CertSelector_Select + (selector, unfilteredCerts, &filteredCerts, plContext), + PKIX_CERTSELECTORSELECTFAILED); + } + + *pNBIOContext = NULL; + *pCertList = filteredCerts; + +cleanup: + + PKIX_DECREF(responses); + PKIX_DECREF(unfilteredCerts); + PKIX_DECREF(lcs); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_GetCRL + * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_LdapCertStore_GetCRL( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + LDAPRequestParams requestParams; + void *pollDesc = NULL; + PLArenaPool *requestArena = NULL; + PKIX_UInt32 numNames = 0; + PKIX_UInt32 thisName = 0; + PKIX_PL_CRL *candidate = NULL; + PKIX_List *responses = NULL; + PKIX_List *issuerNames = NULL; + PKIX_List *filteredCRLs = NULL; + PKIX_List *unfilteredCRLs = NULL; + PKIX_PL_X500Name *issuer = NULL; + PKIX_PL_LdapCertStoreContext *lcs = NULL; + PKIX_ComCRLSelParams *params = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRL"); + PKIX_NULLCHECK_THREE(store, selector, pCrlList); + + requestParams.baseObject = "c=US"; + requestParams.scope = WHOLE_SUBTREE; + requestParams.derefAliases = NEVER_DEREF; + requestParams.sizeLimit = 0; + requestParams.timeLimit = 0; + requestParams.attributes = LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST; + /* Prepare elements for request filter */ + + /* XXX Place CRLDP code here. Handle the case when */ + /* RFC 5280. Paragraph: 4.2.1.13: */ + /* If the distributionPoint field contains a directoryName, the entry */ + /* for that directoryName contains the current CRL for the associated */ + /* reasons and the CRL is issued by the associated cRLIssuer. The CRL */ + /* may be stored in either the certificateRevocationList or */ + /* authorityRevocationList attribute. The CRL is to be obtained by the */ + /* application from whatever directory server is locally configured. */ + /* The protocol the application uses to access the directory (e.g., DAP */ + /* or LDAP) is a local matter. */ + + + + /* + * Get a short-lived arena. We'll be done with this space once + * the request is encoded. + */ + PKIX_PL_NSSCALLRV + (CERTSTORE, requestArena, PORT_NewArena, (DER_DEFAULT_CHUNKSIZE)); + + if (!requestArena) { + PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); + } + + PKIX_CHECK(PKIX_CRLSelector_GetCommonCRLSelectorParams + (selector, ¶ms, plContext), + PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED); + + PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames + (params, &issuerNames, plContext), + PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED); + + /* + * The specification for PKIX_ComCRLSelParams_GetIssuerNames in + * pkix_crlsel.h says that if the criterion is not set we get a null + * pointer. If we get an empty List the criterion is impossible to + * meet ("must match at least one of the names in the List"). + */ + if (issuerNames) { + + PKIX_CHECK(PKIX_List_GetLength + (issuerNames, &numNames, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numNames > 0) { + /* + * LDAP Servers don't seem to be able to handle + * requests with more than more than one name. + * So only use first name. + */ + PKIX_CHECK(PKIX_List_GetItem + (issuerNames, + thisName, + (PKIX_PL_Object **)&issuer, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK + (pkix_pl_LdapCertStore_MakeNameAVAList + (requestArena, + issuer, + &(requestParams.nc), + plContext), + PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED); + + PKIX_DECREF(issuer); + + if (*requestParams.nc == NULL) { + /* + * The issuer may not include any + * components that we know how to + * encode. We do not return an error, + * because the caller did not + * necessarily do anything wrong, but + * we return an empty List. + */ + PKIX_PL_NSSCALL + (CERTSTORE, PORT_FreeArena, + (requestArena, PR_FALSE)); + + PKIX_CHECK(PKIX_List_Create + (&filteredCRLs, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_SetImmutable + (filteredCRLs, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pNBIOContext = NULL; + *pCrlList = filteredCRLs; + goto cleanup; + } + } else { + PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY); + } + } else { + PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY); + } + + /* All request fields are done */ + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&lcs, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest + ((PKIX_PL_LdapClient *)lcs, + &requestParams, + &pollDesc, + &responses, + plContext), + PKIX_LDAPCLIENTINITIATEREQUESTFAILED); + + PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList + (requestParams.nc, plContext), + PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED); + + if (requestArena) { + PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, + (requestArena, PR_FALSE)); + } + + if (pollDesc != NULL) { + /* client is waiting for non-blocking I/O to complete */ + *pNBIOContext = (void *)pollDesc; + *pCrlList = NULL; + goto cleanup; + } + /* client has finished! */ + + if (responses) { + + /* + * We have a List of LdapResponse objects that still have to be + * turned into Crls. + */ + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList + (responses, &unfilteredCRLs, plContext), + PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED); + + PKIX_CHECK(pkix_CRLSelector_Select + (selector, unfilteredCRLs, &filteredCRLs, plContext), + PKIX_CRLSELECTORSELECTFAILED); + + } + + /* Don't throw away the list if one CRL was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pNBIOContext = NULL; + *pCrlList = filteredCRLs; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(filteredCRLs); + } + + PKIX_DECREF(params); + PKIX_DECREF(issuerNames); + PKIX_DECREF(issuer); + PKIX_DECREF(candidate); + PKIX_DECREF(responses); + PKIX_DECREF(unfilteredCRLs); + PKIX_DECREF(lcs); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_LdapCertStore_GetCRLContinue + * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_LdapCertStore_GetCRLContinue( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + void *nbio = NULL; + PKIX_PL_CRL *candidate = NULL; + PKIX_List *responses = NULL; + PKIX_PL_LdapCertStoreContext *lcs = NULL; + PKIX_List *filteredCRLs = NULL; + PKIX_List *unfilteredCRLs = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRLContinue"); + PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList); + + PKIX_CHECK(PKIX_CertStore_GetCertStoreContext + (store, (PKIX_PL_Object **)&lcs, plContext), + PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); + + PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest + ((PKIX_PL_LdapClient *)lcs, &nbio, &responses, plContext), + PKIX_LDAPCLIENTRESUMEREQUESTFAILED); + + if (nbio != NULL) { + /* client is waiting for non-blocking I/O to complete */ + *pNBIOContext = (void *)nbio; + *pCrlList = NULL; + goto cleanup; + } + /* client has finished! */ + + if (responses) { + + /* + * We have a List of LdapResponse objects that still have to be + * turned into Crls. + */ + PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList + (responses, &unfilteredCRLs, plContext), + PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED); + + PKIX_CHECK(pkix_CRLSelector_Select + (selector, unfilteredCRLs, &filteredCRLs, plContext), + PKIX_CRLSELECTORSELECTFAILED); + + PKIX_CHECK(PKIX_List_SetImmutable(filteredCRLs, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + } + + /* Don't throw away the list if one CRL was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pCrlList = filteredCRLs; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(filteredCRLs); + } + + PKIX_DECREF(candidate); + PKIX_DECREF(responses); + PKIX_DECREF(unfilteredCRLs); + PKIX_DECREF(lcs); + + PKIX_RETURN(CERTSTORE); +} + +/* --Public-LdapCertStore-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_PL_LdapCertStore_Create + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_LdapCertStore_Create( + PKIX_PL_LdapClient *client, + PKIX_CertStore **pCertStore, + void *plContext) +{ + PKIX_CertStore *certStore = NULL; + + PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapCertStore_Create"); + PKIX_NULLCHECK_TWO(client, pCertStore); + + PKIX_CHECK(PKIX_CertStore_Create + (pkix_pl_LdapCertStore_GetCert, + pkix_pl_LdapCertStore_GetCRL, + pkix_pl_LdapCertStore_GetCertContinue, + pkix_pl_LdapCertStore_GetCRLContinue, + NULL, /* don't support trust */ + NULL, /* can not store crls */ + NULL, /* can not do revocation check */ + (PKIX_PL_Object *)client, + PKIX_TRUE, /* cache flag */ + PKIX_FALSE, /* not local */ + &certStore, + plContext), + PKIX_CERTSTORECREATEFAILED); + + *pCertStore = certStore; + +cleanup: + + PKIX_RETURN(CERTSTORE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h new file mode 100644 index 0000000000..5bbe5385ca --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.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_pl_ldapcertstore.h + * + * LDAPCertstore Object Type Definition + * + */ + +#ifndef _PKIX_PL_LDAPCERTSTORE_H +#define _PKIX_PL_LDAPCERTSTORE_H + +#include "pkix_pl_ldapt.h" +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * At the time of this version, there are unresolved questions about the LDAP + * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not + * clear whether they are appropriate to this application. We have tested only + * using servers that do not expect authentication, and that reject BIND + * messages. It is not clear what values might be appropriate for the bindname + * and authentication fields, which are currently implemented as char strings + * supplied by the caller. (If this changes, the API and possibly the templates + * will have to change.) Therefore the CertStore_Create API contains a BindAPI + * structure, a union, which will have to be revised and extended when this + * area of the protocol is better understood. + * + * It is further assumed that a given LdapCertStore will connect only to a + * single server, and that the creation of the socket will initiate the + * CONNECT. Therefore the LdapCertStore handles only the case of continuing + * the connection, if nonblocking I/O is being used. + */ + +typedef enum { + LDAP_CONNECT_PENDING, + LDAP_CONNECTED, + LDAP_BIND_PENDING, + LDAP_BIND_RESPONSE, + LDAP_BIND_RESPONSE_PENDING, + LDAP_BOUND, + LDAP_SEND_PENDING, + LDAP_RECV, + LDAP_RECV_PENDING, + LDAP_RECV_INITIAL, + LDAP_RECV_NONINITIAL, + LDAP_ABANDON_PENDING +} LDAPConnectStatus; + +#define LDAP_CACHEBUCKETS 128 +#define RCVBUFSIZE 512 + +struct PKIX_PL_LdapCertStoreContext { + PKIX_PL_LdapClient *client; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_LdapCertStoreContext_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_LdapCertStore_BuildCertList( + PKIX_List *responseList, + PKIX_List **pCerts, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_LDAPCERTSTORE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c new file mode 100644 index 0000000000..9b6f8d688d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c @@ -0,0 +1,2494 @@ +/* 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_pl_ldapdefaultclient.c + * + * LDAPDefaultClient Function Definitions + * + */ + +/* We can't decode the length of a message without at least this many bytes */ +#define MINIMUM_MSG_LENGTH 5 + +#include "pkix_pl_ldapdefaultclient.h" + +/* --Private-LdapDefaultClient-Message-Building-Functions---------------- */ + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_MakeBind + * DESCRIPTION: + * + * This function creates and encodes a Bind message, using the arena pointed + * to by "arena", the version number contained in "versionData", the + * LDAPBindAPI pointed to by "bindAPI", and the messageID contained in + * "msgNum", and stores a pointer to the encoded string at "pBindMsg". + * + * See pkix_pl_ldaptemplates.c for the ASN.1 description of a Bind message. + * + * This code is not used if the DefaultClient was created with a NULL pointer + * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be + * expected for anonymous Search requests.) + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool used in encoding the message. Must be + * non-NULL. + * "versionData" + * The Int32 containing the version number to be encoded in the Bind + * message. + * "bindAPI" + * The address of the LDAPBindAPI to be encoded in the Bind message. Must + * be non-NULL. + * "msgNum" + * The Int32 containing the MessageID to be encoded in the Bind message. + * "pBindMsg" + * The address at which the encoded Bind message 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 LdapDefaultClient 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_pl_LdapDefaultClient_MakeBind( + PLArenaPool *arena, + PKIX_Int32 versionData, + LDAPBindAPI *bindAPI, + PKIX_UInt32 msgNum, + SECItem **pBindMsg, + void *plContext) +{ + LDAPMessage msg; + char version = '\0'; + SECItem *encoded = NULL; + PKIX_UInt32 len = 0; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeBind"); + PKIX_NULLCHECK_TWO(arena, pBindMsg); + + PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, + (&msg, 0, sizeof (LDAPMessage))); + + version = (char)versionData; + + msg.messageID.type = siUnsignedInteger; + msg.messageID.data = (void*)&msgNum; + msg.messageID.len = sizeof (msgNum); + + msg.protocolOp.selector = LDAP_BIND_TYPE; + + msg.protocolOp.op.bindMsg.version.type = siUnsignedInteger; + msg.protocolOp.op.bindMsg.version.data = (void *)&version; + msg.protocolOp.op.bindMsg.version.len = sizeof (char); + + /* + * XXX At present we only know how to handle anonymous requests (no + * authentication), and we are guessing how to do simple authentication. + * This section will need to be revised and extended when other + * authentication is needed. + */ + if (bindAPI->selector == SIMPLE_AUTH) { + msg.protocolOp.op.bindMsg.bindName.type = siAsciiString; + msg.protocolOp.op.bindMsg.bindName.data = + (void *)bindAPI->chooser.simple.bindName; + len = PL_strlen(bindAPI->chooser.simple.bindName); + msg.protocolOp.op.bindMsg.bindName.len = len; + + msg.protocolOp.op.bindMsg.authentication.type = siAsciiString; + msg.protocolOp.op.bindMsg.authentication.data = + (void *)bindAPI->chooser.simple.authentication; + len = PL_strlen(bindAPI->chooser.simple.authentication); + msg.protocolOp.op.bindMsg.authentication.len = len; + } + + PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, + (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); + if (!encoded) { + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + *pBindMsg = encoded; +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_MakeUnbind + * DESCRIPTION: + * + * This function creates and encodes a Unbind message, using the arena pointed + * to by "arena" and the messageID contained in "msgNum", and stores a pointer + * to the encoded string at "pUnbindMsg". + * + * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Unbind message. + * + * This code is not used if the DefaultClient was created with a NULL pointer + * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be + * expected for anonymous Search requests.) + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool used in encoding the message. Must be + * non-NULL. + * "msgNum" + * The Int32 containing the MessageID to be encoded in the Unbind message. + * "pUnbindMsg" + * The address at which the encoded Unbind message 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 LdapDefaultClient 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_pl_LdapDefaultClient_MakeUnbind( + PLArenaPool *arena, + PKIX_UInt32 msgNum, + SECItem **pUnbindMsg, + void *plContext) +{ + LDAPMessage msg; + SECItem *encoded = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeUnbind"); + PKIX_NULLCHECK_TWO(arena, pUnbindMsg); + + PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, + (&msg, 0, sizeof (LDAPMessage))); + + msg.messageID.type = siUnsignedInteger; + msg.messageID.data = (void*)&msgNum; + msg.messageID.len = sizeof (msgNum); + + msg.protocolOp.selector = LDAP_UNBIND_TYPE; + + msg.protocolOp.op.unbindMsg.dummy.type = siBuffer; + msg.protocolOp.op.unbindMsg.dummy.data = NULL; + msg.protocolOp.op.unbindMsg.dummy.len = 0; + + PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, + (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); + if (!encoded) { + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + *pUnbindMsg = encoded; +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_MakeAbandon + * DESCRIPTION: + * + * This function creates and encodes a Abandon message, using the arena pointed + * to by "arena" and the messageID contained in "msgNum", and stores a pointer + * to the encoded string at "pAbandonMsg". + * + * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Abandon message. + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool used in encoding the message. Must be + * non-NULL. + * "msgNum" + * The Int32 containing the MessageID to be encoded in the Abandon message. + * "pAbandonMsg" + * The address at which the encoded Abandon message 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 LdapDefaultClient 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_pl_LdapDefaultClient_MakeAbandon( + PLArenaPool *arena, + PKIX_UInt32 msgNum, + SECItem **pAbandonMsg, + void *plContext) +{ + LDAPMessage msg; + SECItem *encoded = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeAbandon"); + PKIX_NULLCHECK_TWO(arena, pAbandonMsg); + + PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, + (&msg, 0, sizeof (LDAPMessage))); + + msg.messageID.type = siUnsignedInteger; + msg.messageID.data = (void*)&msgNum; + msg.messageID.len = sizeof (msgNum); + + msg.protocolOp.selector = LDAP_ABANDONREQUEST_TYPE; + + msg.protocolOp.op.abandonRequestMsg.messageID.type = siBuffer; + msg.protocolOp.op.abandonRequestMsg.messageID.data = (void*)&msgNum; + msg.protocolOp.op.abandonRequestMsg.messageID.len = sizeof (msgNum); + + PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, + (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); + if (!encoded) { + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + *pAbandonMsg = encoded; +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_DecodeBindResponse + * DESCRIPTION: + * + * This function decodes the encoded data pointed to by "src", using the arena + * pointed to by "arena", storing the decoded LDAPMessage at "pBindResponse" + * and the decoding status at "pStatus". + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool to be used in decoding the message. Must + * be non-NULL. + * "src" + * The address of the SECItem containing the DER- (or BER-)encoded string. + * Must be non-NULL. + * "pBindResponse" + * The address at which the LDAPMessage is stored, if the decoding is + * successful (the returned status is SECSuccess). Must be non-NULL. + * "pStatus" + * The address at which the decoding status 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 LdapDefaultClient 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_pl_LdapDefaultClient_DecodeBindResponse( + PLArenaPool *arena, + SECItem *src, + LDAPMessage *pBindResponse, + SECStatus *pStatus, + void *plContext) +{ + SECStatus rv = SECFailure; + LDAPMessage response; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_DecodeBindResponse"); + PKIX_NULLCHECK_FOUR(arena, src, pBindResponse, pStatus); + + PKIX_PL_NSSCALL + (LDAPDEFAULTCLIENT, + PORT_Memset, + (&response, 0, sizeof (LDAPMessage))); + + PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, rv, SEC_ASN1DecodeItem, + (arena, &response, PKIX_PL_LDAPMessageTemplate, src)); + + if (rv == SECSuccess) { + *pBindResponse = response; + } + + *pStatus = rv; + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_VerifyBindResponse + * DESCRIPTION: + * + * This function verifies that the contents of the message in the rcvbuf of + * the LdapDefaultClient object pointed to by "client", and whose length is + * provided by "buflen", is a response to a successful Bind. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "buflen" + * The value of the number of bytes in the receive buffer. + * "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 LdapDefaultClient 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_pl_LdapDefaultClient_VerifyBindResponse( + PKIX_PL_LdapDefaultClient *client, + PKIX_UInt32 bufLen, + void *plContext) +{ + SECItem decode = {siBuffer, NULL, 0}; + SECStatus rv = SECFailure; + LDAPMessage msg; + LDAPBindResponse *ldapBindResponse = &msg.protocolOp.op.bindResponseMsg; + + ldapBindResponse->resultCode.data = NULL; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_VerifyBindResponse"); + PKIX_NULLCHECK_TWO(client, client->rcvBuf); + + decode.data = (unsigned char *)(client->rcvBuf); + decode.len = bufLen; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_DecodeBindResponse + (client->arena, &decode, &msg, &rv, plContext), + PKIX_LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED); + + if (rv == SECSuccess) { + if (*(ldapBindResponse->resultCode.data) == SUCCESS) { + client->connectStatus = BOUND; + } else { + PKIX_ERROR(PKIX_BINDREJECTEDBYSERVER); + } + } else { + PKIX_ERROR(PKIX_CANTDECODEBINDRESPONSEFROMSERVER); + } + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_RecvCheckComplete + * DESCRIPTION: + * + * This function determines whether the current response in the + * LdapDefaultClient pointed to by "client" is complete, in the sense that all + * bytes required to satisfy the message length field in the encoding have been + * received. If so, the pointer to input data is updated to reflect the number + * of bytes consumed, provided by "bytesProcessed". The state machine flag + * pointed to by "pKeepGoing" is updated to indicate whether processing can + * continue without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "bytesProcessed" + * The UInt32 value of the number of bytes consumed from the current + * buffer. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_RecvCheckComplete( + PKIX_PL_LdapDefaultClient *client, + PKIX_UInt32 bytesProcessed, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Boolean complete = PKIX_FALSE; + SECStatus rv = SECFailure; + LDAPMessageType messageType = 0; + LDAPResultCode resultCode = 0; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_RecvCheckComplete"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + PKIX_CHECK(pkix_pl_LdapResponse_IsComplete + (client->currentResponse, &complete, plContext), + PKIX_LDAPRESPONSEISCOMPLETEFAILED); + + if (complete) { + PKIX_CHECK(pkix_pl_LdapResponse_Decode + (client->arena, client->currentResponse, &rv, plContext), + PKIX_LDAPRESPONSEDECODEFAILED); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_CANTDECODESEARCHRESPONSEFROMSERVER); + } + + PKIX_CHECK(pkix_pl_LdapResponse_GetMessageType + (client->currentResponse, &messageType, plContext), + PKIX_LDAPRESPONSEGETMESSAGETYPEFAILED); + + if (messageType == LDAP_SEARCHRESPONSEENTRY_TYPE) { + + if (client->entriesFound == NULL) { + PKIX_CHECK(PKIX_List_Create + (&(client->entriesFound), plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (client->entriesFound, + (PKIX_PL_Object *)client->currentResponse, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(client->currentResponse); + + /* current receive buffer empty? */ + if (client->currentBytesAvailable == 0) { + client->connectStatus = RECV; + *pKeepGoing = PKIX_TRUE; + } else { + client->connectStatus = RECV_INITIAL; + client->currentInPtr = &((char *) + (client->currentInPtr))[bytesProcessed]; + *pKeepGoing = PKIX_TRUE; + } + + } else if (messageType == LDAP_SEARCHRESPONSERESULT_TYPE) { + PKIX_CHECK(pkix_pl_LdapResponse_GetResultCode + (client->currentResponse, + &resultCode, + plContext), + PKIX_LDAPRESPONSEGETRESULTCODEFAILED); + + if ((client->entriesFound == NULL) && + ((resultCode == SUCCESS) || + (resultCode == NOSUCHOBJECT))) { + PKIX_CHECK(PKIX_List_Create + (&(client->entriesFound), plContext), + PKIX_LISTCREATEFAILED); + } else if (resultCode == SUCCESS) { + PKIX_CHECK(PKIX_List_SetImmutable + (client->entriesFound, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + PKIX_CHECK(PKIX_PL_HashTable_Add + (client->cachePtr, + (PKIX_PL_Object *)client->currentRequest, + (PKIX_PL_Object *)client->entriesFound, + plContext), + PKIX_HASHTABLEADDFAILED); + } else { + PKIX_ERROR(PKIX_UNEXPECTEDRESULTCODEINRESPONSE); + } + + client->connectStatus = BOUND; + *pKeepGoing = PKIX_FALSE; + PKIX_DECREF(client->currentResponse); + + } else { + PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE); + } + } else { + client->connectStatus = RECV; + *pKeepGoing = PKIX_TRUE; + } + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* --Private-LdapDefaultClient-Object-Functions------------------------- */ + +static PKIX_Error * +pkix_pl_LdapDefaultClient_InitiateRequest( + PKIX_PL_LdapClient *client, + LDAPRequestParams *requestParams, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext); + +static PKIX_Error * +pkix_pl_LdapDefaultClient_ResumeRequest( + PKIX_PL_LdapClient *client, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext); + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_CreateHelper + * DESCRIPTION: + * + * This function creates a new LdapDefaultClient using the Socket pointed to + * by "socket", the PRIntervalTime pointed to by "timeout", and the + * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". + * + * A value of zero for "timeout" means the LDAPClient will use non-blocking + * I/O. + * + * PARAMETERS: + * "socket" + * Address of the Socket to be used for the client. Must be non-NULL. + * "bindAPI" + * The address of the LDAPBindAPI containing the Bind information to be + * encoded in the Bind message. + * "pClient" + * The address at which the created LdapDefaultClient is to 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 LdapDefaultClient 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_pl_LdapDefaultClient_CreateHelper( + PKIX_PL_Socket *socket, + LDAPBindAPI *bindAPI, + PKIX_PL_LdapDefaultClient **pClient, + void *plContext) +{ + PKIX_PL_HashTable *ht; + PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL; + PKIX_PL_Socket_Callback *callbackList; + PRFileDesc *fileDesc = NULL; + PLArenaPool *arena = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_CreateHelper"); + PKIX_NULLCHECK_TWO(socket, pClient); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LDAPDEFAULTCLIENT_TYPE, + sizeof (PKIX_PL_LdapDefaultClient), + (PKIX_PL_Object **)&ldapDefaultClient, + plContext), + PKIX_COULDNOTCREATELDAPDEFAULTCLIENTOBJECT); + + ldapDefaultClient->vtable.initiateFcn = + pkix_pl_LdapDefaultClient_InitiateRequest; + ldapDefaultClient->vtable.resumeFcn = + pkix_pl_LdapDefaultClient_ResumeRequest; + + PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc + (socket, &fileDesc, plContext), + PKIX_SOCKETGETPRFILEDESCFAILED); + + ldapDefaultClient->pollDesc.fd = fileDesc; + ldapDefaultClient->pollDesc.in_flags = 0; + ldapDefaultClient->pollDesc.out_flags = 0; + + ldapDefaultClient->bindAPI = bindAPI; + + PKIX_CHECK(PKIX_PL_HashTable_Create + (LDAP_CACHEBUCKETS, 0, &ht, plContext), + PKIX_HASHTABLECREATEFAILED); + + ldapDefaultClient->cachePtr = ht; + + PKIX_CHECK(pkix_pl_Socket_GetCallbackList + (socket, &callbackList, plContext), + PKIX_SOCKETGETCALLBACKLISTFAILED); + + ldapDefaultClient->callbackList = callbackList; + + PKIX_INCREF(socket); + ldapDefaultClient->clientSocket = socket; + + ldapDefaultClient->messageID = 0; + + ldapDefaultClient->bindAPI = bindAPI; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); + } + ldapDefaultClient->arena = arena; + + ldapDefaultClient->sendBuf = NULL; + ldapDefaultClient->bytesToWrite = 0; + + PKIX_CHECK(PKIX_PL_Malloc + (RCVBUFSIZE, &ldapDefaultClient->rcvBuf, plContext), + PKIX_MALLOCFAILED); + ldapDefaultClient->capacity = RCVBUFSIZE; + + ldapDefaultClient->bindMsg = NULL; + ldapDefaultClient->bindMsgLen = 0; + + ldapDefaultClient->entriesFound = NULL; + ldapDefaultClient->currentRequest = NULL; + ldapDefaultClient->currentResponse = NULL; + + *pClient = ldapDefaultClient; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(ldapDefaultClient); + } + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: PKIX_PL_LdapDefaultClient_Create + * DESCRIPTION: + * + * This function creates a new LdapDefaultClient using the PRNetAddr pointed to + * by "sockaddr", the PRIntervalTime pointed to by "timeout", and the + * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". + * + * A value of zero for "timeout" means the LDAPClient will use non-blocking + * I/O. + * + * PARAMETERS: + * "sockaddr" + * Address of the PRNetAddr to be used for the socket connection. Must be + * non-NULL. + * "timeout" + * The PRIntervalTime to be used in I/O requests for this client. + * "bindAPI" + * The address of the LDAPBindAPI containing the Bind information to be + * encoded in the Bind message. + * "pClient" + * The address at which the created LdapDefaultClient is to 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 LdapDefaultClient 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_PL_LdapDefaultClient_Create( + PRNetAddr *sockaddr, + PRIntervalTime timeout, + LDAPBindAPI *bindAPI, + PKIX_PL_LdapDefaultClient **pClient, + void *plContext) +{ + PRErrorCode status = 0; + PKIX_PL_Socket *socket = NULL; + PKIX_PL_LdapDefaultClient *client = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_Create"); + PKIX_NULLCHECK_TWO(sockaddr, pClient); + + PKIX_CHECK(pkix_pl_Socket_Create + (PKIX_FALSE, timeout, sockaddr, &status, &socket, plContext), + PKIX_SOCKETCREATEFAILED); + + PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper + (socket, bindAPI, &client, plContext), + PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED); + + /* Did Socket_Create say the connection was made? */ + if (status == 0) { + if (client->bindAPI != NULL) { + client->connectStatus = CONNECTED; + } else { + client->connectStatus = BOUND; + } + } else { + client->connectStatus = CONNECT_PENDING; + } + + *pClient = client; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(client); + } + + PKIX_DECREF(socket); + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName + * DESCRIPTION: + * + * This function creates a new LdapDefaultClient using the hostname pointed to + * by "hostname", the PRIntervalTime pointed to by "timeout", and the + * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". + * + * A value of zero for "timeout" means the LDAPClient will use non-blocking + * I/O. + * + * PARAMETERS: + * "hostname" + * Address of the hostname to be used for the socket connection. Must be + * non-NULL. + * "timeout" + * The PRIntervalTime to be used in I/O requests for this client. + * "bindAPI" + * The address of the LDAPBindAPI containing the Bind information to be + * encoded in the Bind message. + * "pClient" + * The address at which the created LdapDefaultClient is to 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 LdapDefaultClient 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_PL_LdapDefaultClient_CreateByName( + char *hostname, + PRIntervalTime timeout, + LDAPBindAPI *bindAPI, + PKIX_PL_LdapDefaultClient **pClient, + void *plContext) +{ + PRErrorCode status = 0; + PKIX_PL_Socket *socket = NULL; + PKIX_PL_LdapDefaultClient *client = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_CreateByName"); + PKIX_NULLCHECK_TWO(hostname, pClient); + + PKIX_CHECK(pkix_pl_Socket_CreateByName + (PKIX_FALSE, timeout, hostname, &status, &socket, plContext), + PKIX_SOCKETCREATEBYNAMEFAILED); + + PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper + (socket, bindAPI, &client, plContext), + PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED); + + /* Did Socket_Create say the connection was made? */ + if (status == 0) { + if (client->bindAPI != NULL) { + client->connectStatus = CONNECTED; + } else { + client->connectStatus = BOUND; + } + } else { + client->connectStatus = CONNECT_PENDING; + } + + *pClient = client; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(client); + } + + PKIX_DECREF(socket); + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapDefaultClient_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_LdapDefaultClient *client = NULL; + PKIX_PL_Socket_Callback *callbackList = NULL; + SECItem *encoded = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext), + PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); + + client = (PKIX_PL_LdapDefaultClient *)object; + + switch (client->connectStatus) { + case CONNECT_PENDING: + break; + case CONNECTED: + case BIND_PENDING: + case BIND_RESPONSE: + case BIND_RESPONSE_PENDING: + case BOUND: + case SEND_PENDING: + case RECV: + case RECV_PENDING: + case RECV_INITIAL: + case RECV_NONINITIAL: + case ABANDON_PENDING: + if (client->bindAPI != NULL) { + PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeUnbind + (client->arena, + ++(client->messageID), + &encoded, + plContext), + PKIX_LDAPDEFAULTCLIENTMAKEUNBINDFAILED); + + callbackList = + (PKIX_PL_Socket_Callback *)(client->callbackList); + PKIX_CHECK(callbackList->sendCallback + (client->clientSocket, + encoded->data, + encoded->len, + &bytesWritten, + plContext), + PKIX_SOCKETSENDFAILED); + } + break; + default: + PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTINILLEGALSTATE); + } + + PKIX_DECREF(client->cachePtr); + PKIX_DECREF(client->clientSocket); + PKIX_DECREF(client->entriesFound); + PKIX_DECREF(client->currentRequest); + PKIX_DECREF(client->currentResponse); + + PKIX_CHECK(PKIX_PL_Free + (client->rcvBuf, plContext), PKIX_FREEFAILED); + + PKIX_PL_NSSCALL + (LDAPDEFAULTCLIENT, + PORT_FreeArena, + (client->arena, PR_FALSE)); + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapDefaultClient_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL; + PKIX_UInt32 tempHash = 0; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext), + PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); + + ldapDefaultClient = (PKIX_PL_LdapDefaultClient *)object; + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)ldapDefaultClient->clientSocket, + &tempHash, + plContext), + PKIX_SOCKETHASHCODEFAILED); + + if (ldapDefaultClient->bindAPI != NULL) { + tempHash = (tempHash << 7) + + ldapDefaultClient->bindAPI->selector; + } + + *pHashcode = tempHash; + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapDefaultClient_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_LdapDefaultClient *firstClientContext = NULL; + PKIX_PL_LdapDefaultClient *secondClientContext = NULL; + PKIX_Int32 compare = 0; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + *pResult = PKIX_FALSE; + + PKIX_CHECK(pkix_CheckTypes + (firstObject, + secondObject, + PKIX_LDAPDEFAULTCLIENT_TYPE, + plContext), + PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); + + firstClientContext = (PKIX_PL_LdapDefaultClient *)firstObject; + secondClientContext = (PKIX_PL_LdapDefaultClient *)secondObject; + + if (firstClientContext == secondClientContext) { + *pResult = PKIX_TRUE; + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstClientContext->clientSocket, + (PKIX_PL_Object *)secondClientContext->clientSocket, + &compare, + plContext), + PKIX_SOCKETEQUALSFAILED); + + if (!compare) { + goto cleanup; + } + + if (PKIX_EXACTLY_ONE_NULL + (firstClientContext->bindAPI, secondClientContext->bindAPI)) { + goto cleanup; + } + + if (firstClientContext->bindAPI) { + if (firstClientContext->bindAPI->selector != + secondClientContext->bindAPI->selector) { + goto cleanup; + } + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_PL_LDAPDEFAULTCLIENT_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_pl_LdapDefaultClient_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_RegisterSelf"); + + entry.description = "LdapDefaultClient"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_LdapDefaultClient); + entry.destructor = pkix_pl_LdapDefaultClient_Destroy; + entry.equalsFunction = pkix_pl_LdapDefaultClient_Equals; + entry.hashcodeFunction = pkix_pl_LdapDefaultClient_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_LDAPDEFAULTCLIENT_TYPE] = entry; + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_GetPollDesc + * DESCRIPTION: + * + * This function retrieves the PRPollDesc from the LdapDefaultClient + * pointed to by "context" and stores the address at "pPollDesc". + * + * PARAMETERS: + * "context" + * The LdapDefaultClient whose PRPollDesc is desired. Must be non-NULL. + * "pPollDesc" + * Address where PRPollDesc 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_pl_LdapDefaultClient_GetPollDesc( + PKIX_PL_LdapDefaultClient *context, + PRPollDesc **pPollDesc, + void *plContext) +{ + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_GetPollDesc"); + PKIX_NULLCHECK_TWO(context, pPollDesc); + + *pPollDesc = &(context->pollDesc); + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* --Private-Ldap-CertStore-I/O-Functions---------------------------- */ +/* + * FUNCTION: pkix_pl_LdapDefaultClient_ConnectContinue + * DESCRIPTION: + * + * This function determines whether a socket Connect initiated earlier for the + * CertStore embodied in the LdapDefaultClient "client" has completed, and + * stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_ConnectContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_PL_Socket_Callback *callbackList; + PRErrorCode status; + PKIX_Boolean keepGoing = PKIX_FALSE; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_ConnectContinue"); + PKIX_NULLCHECK_ONE(client); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->connectcontinueCallback + (client->clientSocket, &status, plContext), + PKIX_SOCKETCONNECTCONTINUEFAILED); + + if (status == 0) { + if (client->bindAPI != NULL) { + client->connectStatus = CONNECTED; + } else { + client->connectStatus = BOUND; + } + keepGoing = PKIX_FALSE; + } else if (status != PR_IN_PROGRESS_ERROR) { + PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pKeepGoing = keepGoing; + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Bind + * DESCRIPTION: + * + * This function creates and sends the LDAP-protocol Bind message for the + * CertStore embodied in the LdapDefaultClient "client", and stores in + * "pKeepGoing" a flag indicating whether processing can continue without + * further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_Bind( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + SECItem *encoded = NULL; + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Bind"); + PKIX_NULLCHECK_ONE(client); + + /* if we have not yet constructed the BIND message, build it now */ + if (!(client->bindMsg)) { + PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeBind + (client->arena, + 3, + client->bindAPI, + client->messageID, + &encoded, + plContext), + PKIX_LDAPDEFAULTCLIENTMAKEBINDFAILED); + client->bindMsg = encoded->data; + client->bindMsgLen = encoded->len; + } + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->sendCallback + (client->clientSocket, + client->bindMsg, + client->bindMsgLen, + &bytesWritten, + plContext), + PKIX_SOCKETSENDFAILED); + + client->lastIO = PR_Now(); + + if (bytesWritten < 0) { + client->connectStatus = BIND_PENDING; + *pKeepGoing = PKIX_FALSE; + } else { + client->connectStatus = BIND_RESPONSE; + *pKeepGoing = PKIX_TRUE; + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_BindContinue + * DESCRIPTION: + * + * This function determines whether the LDAP-protocol Bind message for the + * CertStore embodied in the LdapDefaultClient "client" has completed, and + * stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_BindContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindContinue"); + PKIX_NULLCHECK_ONE(client); + + *pKeepGoing = PKIX_FALSE; + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->pollCallback + (client->clientSocket, &bytesWritten, NULL, plContext), + PKIX_SOCKETPOLLFAILED); + + /* + * If the send completed we can proceed to try for the + * response. If the send did not complete we will have + * continue to poll. + */ + if (bytesWritten >= 0) { + + client->connectStatus = BIND_RESPONSE; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pKeepGoing = PKIX_TRUE; + } + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_BindResponse + * DESCRIPTION: + * + * This function attempts to read the LDAP-protocol BindResponse message for + * the CertStore embodied in the LdapDefaultClient "client", and stores in + * "pKeepGoing" a flag indicating whether processing can continue without + * further input. + * + * If a BindResponse is received with a Result code of 0 (success), we + * continue with the connection. If a non-zero Result code is received, + * we throw an Error. Some more sophisticated handling of that condition + * might be in order in the future. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_BindResponse( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindResponse"); + PKIX_NULLCHECK_TWO(client, client->rcvBuf); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->recvCallback + (client->clientSocket, + client->rcvBuf, + client->capacity, + &bytesRead, + plContext), + PKIX_SOCKETRECVFAILED); + + client->lastIO = PR_Now(); + + if (bytesRead > 0) { + PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse + (client, bytesRead, plContext), + PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED); + /* + * XXX What should we do if failure? At present if + * VerifyBindResponse throws an Error, we do too. + */ + client->connectStatus = BOUND; + } else { + client->connectStatus = BIND_RESPONSE_PENDING; + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pKeepGoing = PKIX_TRUE; + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_BindResponseContinue + * DESCRIPTION: + * + * This function determines whether the LDAP-protocol BindResponse message for + * the CertStore embodied in the LdapDefaultClient "client" has completed, and + * stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_BindResponseContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_BindResponseContinue"); + PKIX_NULLCHECK_ONE(client); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->pollCallback + (client->clientSocket, NULL, &bytesRead, plContext), + PKIX_SOCKETPOLLFAILED); + + if (bytesRead > 0) { + PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse + (client, bytesRead, plContext), + PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED); + client->connectStatus = BOUND; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pKeepGoing = PKIX_TRUE; + } else { + *pKeepGoing = PKIX_FALSE; + } + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Send + * DESCRIPTION: + * + * This function creates and sends an LDAP-protocol message for the + * CertStore embodied in the LdapDefaultClient "client", and stores in + * "pKeepGoing" a flag indicating whether processing can continue without + * further input, and at "pBytesTransferred" the number of bytes sent. + * + * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use + * and that transmission has not completed. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "pBytesTransferred" + * The address at which the number of bytes sent 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 LdapDefaultClient 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_pl_LdapDefaultClient_Send( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + PKIX_UInt32 *pBytesTransferred, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Send"); + PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); + + *pKeepGoing = PKIX_FALSE; + + /* Do we have anything waiting to go? */ + if (client->sendBuf) { + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->sendCallback + (client->clientSocket, + client->sendBuf, + client->bytesToWrite, + &bytesWritten, + plContext), + PKIX_SOCKETSENDFAILED); + + client->lastIO = PR_Now(); + + /* + * If the send completed we can proceed to try for the + * response. If the send did not complete we will have + * to poll for completion later. + */ + if (bytesWritten >= 0) { + client->sendBuf = NULL; + client->connectStatus = RECV; + *pKeepGoing = PKIX_TRUE; + + } else { + *pKeepGoing = PKIX_FALSE; + client->connectStatus = SEND_PENDING; + } + + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pBytesTransferred = bytesWritten; + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_SendContinue + * DESCRIPTION: + * + * This function determines whether the sending of the LDAP-protocol message + * for the CertStore embodied in the LdapDefaultClient "client" has completed, + * and stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input, and at "pBytesTransferred" the number of bytes sent. + * + * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use + * and that transmission has not completed. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * Must be non-NULL. + * "pBytesTransferred" + * The address at which the number of bytes sent 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 LdapDefaultClient 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_pl_LdapDefaultClient_SendContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + PKIX_UInt32 *pBytesTransferred, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_SendContinue"); + PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); + + *pKeepGoing = PKIX_FALSE; + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->pollCallback + (client->clientSocket, &bytesWritten, NULL, plContext), + PKIX_SOCKETPOLLFAILED); + + /* + * If the send completed we can proceed to try for the + * response. If the send did not complete we will have + * continue to poll. + */ + if (bytesWritten >= 0) { + client->sendBuf = NULL; + client->connectStatus = RECV; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + *pKeepGoing = PKIX_TRUE; + } + + *pBytesTransferred = bytesWritten; + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Recv + * DESCRIPTION: + * + * This function receives an LDAP-protocol message for the CertStore embodied + * in the LdapDefaultClient "client", and stores in "pKeepGoing" a flag + * indicating whether processing can continue without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_Recv( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesRead = 0; + PKIX_UInt32 bytesToRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Recv"); + PKIX_NULLCHECK_THREE(client, pKeepGoing, client->rcvBuf); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + /* + * If we attempt to fill our buffer with every read, we increase + * the risk of an ugly situation: one or two bytes of a new message + * left over at the end of processing one message. With such a + * fragment, we can't decode a byte count and so won't know how much + * space to allocate for the next LdapResponse. We try to avoid that + * case by reading just enough to complete the current message, unless + * there will be at least MINIMUM_MSG_LENGTH bytes left over. + */ + if (client->currentResponse) { + PKIX_CHECK(pkix_pl_LdapResponse_GetCapacity + (client->currentResponse, &bytesToRead, plContext), + PKIX_LDAPRESPONSEGETCAPACITYFAILED); + if ((bytesToRead > client->capacity) || + ((bytesToRead + MINIMUM_MSG_LENGTH) < client->capacity)) { + bytesToRead = client->capacity; + } + } else { + bytesToRead = client->capacity; + } + + client->currentBytesAvailable = 0; + + PKIX_CHECK(callbackList->recvCallback + (client->clientSocket, + (void *)client->rcvBuf, + bytesToRead, + &bytesRead, + plContext), + PKIX_SOCKETRECVFAILED); + + client->currentInPtr = client->rcvBuf; + client->lastIO = PR_Now(); + + if (bytesRead > 0) { + client->currentBytesAvailable = bytesRead; + client->connectStatus = RECV_INITIAL; + *pKeepGoing = PKIX_TRUE; + } else { + client->connectStatus = RECV_PENDING; + *pKeepGoing = PKIX_FALSE; + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_RecvContinue + * DESCRIPTION: + * + * This function determines whether the receiving of the LDAP-protocol message + * for the CertStore embodied in the LdapDefaultClient "client" has completed, + * and stores in "pKeepGoing" a flag indicating whether processing can continue + * without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_RecvContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvContinue"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->pollCallback + (client->clientSocket, NULL, &bytesRead, plContext), + PKIX_SOCKETPOLLFAILED); + + if (bytesRead > 0) { + client->currentBytesAvailable += bytesRead; + client->connectStatus = RECV_INITIAL; + *pKeepGoing = PKIX_TRUE; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } else { + *pKeepGoing = PKIX_FALSE; + } + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_AbandonContinue + * DESCRIPTION: + * + * This function determines whether the abandon-message request of the + * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient + * "client" has completed, and stores in "pKeepGoing" a flag indicating whether + * processing can continue without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_AbandonContinue( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_AbandonContinue"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + + PKIX_CHECK(callbackList->pollCallback + (client->clientSocket, &bytesWritten, NULL, plContext), + PKIX_SOCKETPOLLFAILED); + + if (bytesWritten > 0) { + client->connectStatus = BOUND; + *pKeepGoing = PKIX_TRUE; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)client, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + } else { + *pKeepGoing = PKIX_FALSE; + } + +cleanup: + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_RecvInitial + * DESCRIPTION: + * + * This function processes the contents of the first buffer of a received + * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient + * "client", and stores in "pKeepGoing" a flag indicating whether processing can + * continue without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_RecvInitial( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + unsigned char *msgBuf = NULL; + unsigned char *to = NULL; + unsigned char *from = NULL; + PKIX_UInt32 dataIndex = 0; + PKIX_UInt32 messageIdLen = 0; + PKIX_UInt32 messageLength = 0; + PKIX_UInt32 sizeofLength = 0; + PKIX_UInt32 bytesProcessed = 0; + unsigned char messageChar = 0; + LDAPMessageType messageType = 0; + PKIX_Int32 bytesRead = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvInitial"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + /* + * Is there an LDAPResponse in progress? I.e., have we + * already processed the tag and length at the beginning of + * the message? + */ + if (client->currentResponse) { + client->connectStatus = RECV_NONINITIAL; + *pKeepGoing = PKIX_TRUE; + goto cleanup; + } + msgBuf = client->currentInPtr; + + /* Do we have enough of the message to decode the message length? */ + if (client->currentBytesAvailable < MINIMUM_MSG_LENGTH) { + /* + * No! Move these few bytes to the beginning of rcvBuf + * and hang another read. + */ + + to = (unsigned char *)client->rcvBuf; + from = client->currentInPtr; + for (dataIndex = 0; + dataIndex < client->currentBytesAvailable; + dataIndex++) { + *to++ = *from++; + } + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + PKIX_CHECK(callbackList->recvCallback + (client->clientSocket, + (void *)to, + client->capacity - client->currentBytesAvailable, + &bytesRead, + plContext), + PKIX_SOCKETRECVFAILED); + + client->currentInPtr = client->rcvBuf; + client->lastIO = PR_Now(); + + if (bytesRead <= 0) { + client->connectStatus = RECV_PENDING; + *pKeepGoing = PKIX_FALSE; + goto cleanup; + } else { + client->currentBytesAvailable += bytesRead; + } + } + + /* + * We have to determine whether the response is an entry, with + * application-specific tag LDAP_SEARCHRESPONSEENTRY_TYPE, or a + * resultCode, with application tag LDAP_SEARCHRESPONSERESULT_TYPE. + * First, we have to figure out where to look for the tag. + */ + + /* Is the message length short form (one octet) or long form? */ + if ((msgBuf[1] & 0x80) != 0) { + sizeofLength = msgBuf[1] & 0x7F; + for (dataIndex = 0; dataIndex < sizeofLength; dataIndex++) { + messageLength = + (messageLength << 8) + msgBuf[dataIndex + 2]; + } + } else { + messageLength = msgBuf[1]; + } + + /* How many bytes did the messageID require? */ + messageIdLen = msgBuf[dataIndex + 3]; + + messageChar = msgBuf[dataIndex + messageIdLen + 4]; + + /* Are we looking at an Entry message or a ResultCode message? */ + if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | + LDAP_SEARCHRESPONSEENTRY_TYPE) == messageChar) { + + messageType = LDAP_SEARCHRESPONSEENTRY_TYPE; + + } else if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | + LDAP_SEARCHRESPONSERESULT_TYPE) == messageChar) { + + messageType = LDAP_SEARCHRESPONSERESULT_TYPE; + + } else { + + PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE); + + } + + /* + * messageLength is the length from (tag, length, value). + * We have to allocate space for the tag and length bits too. + */ + PKIX_CHECK(pkix_pl_LdapResponse_Create + (messageType, + messageLength + dataIndex + 2, + client->currentBytesAvailable, + msgBuf, + &bytesProcessed, + &(client->currentResponse), + plContext), + PKIX_LDAPRESPONSECREATEFAILED); + + client->currentBytesAvailable -= bytesProcessed; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete + (client, bytesProcessed, pKeepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED); + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_RecvNonInitial + * DESCRIPTION: + * + * This function processes the contents of buffers, after the first, of a + * received LDAP-protocol message for the CertStore embodied in the + * LdapDefaultClient "client", and stores in "pKeepGoing" a flag indicating + * whether processing can continue without further input. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pKeepGoing" + * The address at which the Boolean state machine flag is stored to + * indicate whether processing can continue without further input. + * 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 LdapDefaultClient 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_pl_LdapDefaultClient_RecvNonInitial( + PKIX_PL_LdapDefaultClient *client, + PKIX_Boolean *pKeepGoing, + void *plContext) +{ + + PKIX_UInt32 bytesProcessed = 0; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvNonInitial"); + PKIX_NULLCHECK_TWO(client, pKeepGoing); + + PKIX_CHECK(pkix_pl_LdapResponse_Append + (client->currentResponse, + client->currentBytesAvailable, + client->currentInPtr, + &bytesProcessed, + plContext), + PKIX_LDAPRESPONSEAPPENDFAILED); + + client->currentBytesAvailable -= bytesProcessed; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete + (client, bytesProcessed, pKeepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED); + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_Dispatch + * DESCRIPTION: + * + * This function is the state machine dispatcher for the CertStore embodied in + * the LdapDefaultClient pointed to by "client". Results are returned by + * changes to various fields in the context. + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. 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 LdapDefaultClient 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_pl_LdapDefaultClient_Dispatch( + PKIX_PL_LdapDefaultClient *client, + void *plContext) +{ + PKIX_UInt32 bytesTransferred = 0; + PKIX_Boolean keepGoing = PKIX_TRUE; + + PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Dispatch"); + PKIX_NULLCHECK_ONE(client); + + while (keepGoing) { + switch (client->connectStatus) { + case CONNECT_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_ConnectContinue + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED); + break; + case CONNECTED: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_Bind + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTBINDFAILED); + break; + case BIND_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_BindContinue + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTBINDCONTINUEFAILED); + break; + case BIND_RESPONSE: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_BindResponse + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTBINDRESPONSEFAILED); + break; + case BIND_RESPONSE_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_BindResponseContinue + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED); + break; + case BOUND: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_Send + (client, &keepGoing, &bytesTransferred, plContext), + PKIX_LDAPDEFAULTCLIENTSENDFAILED); + break; + case SEND_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_SendContinue + (client, &keepGoing, &bytesTransferred, plContext), + PKIX_LDAPDEFAULTCLIENTSENDCONTINUEFAILED); + break; + case RECV: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_Recv + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVFAILED); + break; + case RECV_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_RecvContinue + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVCONTINUEFAILED); + break; + case RECV_INITIAL: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_RecvInitial + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVINITIALFAILED); + break; + case RECV_NONINITIAL: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_RecvNonInitial + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTRECVNONINITIALFAILED); + break; + case ABANDON_PENDING: + PKIX_CHECK + (pkix_pl_LdapDefaultClient_AbandonContinue + (client, &keepGoing, plContext), + PKIX_LDAPDEFAULTCLIENTABANDONCONTINUEFAILED); + break; + default: + PKIX_ERROR(PKIX_LDAPCERTSTOREINILLEGALSTATE); + } + } + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_MakeAndFilter + * DESCRIPTION: + * + * This function allocates space from the arena pointed to by "arena" to + * construct a filter that will match components of the X500Name pointed to by + * XXX... + * + * PARAMETERS: + * "arena" + * The address of the PLArenaPool used in creating the filter. Must be + * non-NULL. + * "nameComponent" + * The address of a NULL-terminated list of LDAPNameComponents + * Must be non-NULL. + * "pFilter" + * The address at which the result 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 CertStore 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_pl_LdapDefaultClient_MakeAndFilter( + PLArenaPool *arena, + LDAPNameComponent **nameComponents, + LDAPFilter **pFilter, + void *plContext) +{ + LDAPFilter **setOfFilter; + LDAPFilter *andFilter = NULL; + LDAPFilter *currentFilter = NULL; + PKIX_UInt32 componentsPresent = 0; + void *v = NULL; + unsigned char *component = NULL; + LDAPNameComponent **componentP = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_LdapDefaultClient_MakeAndFilter"); + PKIX_NULLCHECK_THREE(arena, nameComponents, pFilter); + + /* count how many components we were provided */ + for (componentP = nameComponents, componentsPresent = 0; + *(componentP++) != NULL; + componentsPresent++) {} + + /* Space for (componentsPresent + 1) pointers to LDAPFilter */ + PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc, + (arena, (componentsPresent + 1)*sizeof(LDAPFilter *))); + setOfFilter = (LDAPFilter **)v; + + /* Space for AndFilter and <componentsPresent> EqualFilters */ + PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray, + (arena, LDAPFilter, componentsPresent + 1)); + setOfFilter[0] = (LDAPFilter *)v; + + /* Claim the first array element for the ANDFilter */ + andFilter = setOfFilter[0]; + + /* Set ANDFilter to point to the first EqualFilter pointer */ + andFilter->selector = LDAP_ANDFILTER_TYPE; + andFilter->filter.andFilter.filters = setOfFilter; + + currentFilter = andFilter + 1; + + for (componentP = nameComponents, componentsPresent = 0; + *(componentP) != NULL; componentP++) { + setOfFilter[componentsPresent++] = currentFilter; + currentFilter->selector = LDAP_EQUALFILTER_TYPE; + component = (*componentP)->attrType; + currentFilter->filter.equalFilter.attrType.data = component; + currentFilter->filter.equalFilter.attrType.len = + PL_strlen((const char *)component); + component = (*componentP)->attrValue; + currentFilter->filter.equalFilter.attrValue.data = component; + currentFilter->filter.equalFilter.attrValue.len = + PL_strlen((const char *)component); + currentFilter++; + } + + setOfFilter[componentsPresent] = NULL; + + *pFilter = andFilter; + + PKIX_RETURN(CERTSTORE); + +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_InitiateRequest + * DESCRIPTION: + * + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "requestParams" + * The address of an LdapClientParams object. Must be non-NULL. + * "pPollDesc" + * The location where the address of the PRPollDesc is stored, if the + * client returns with I/O pending. + * "pResponse" + * The address where the List of LDAPResponses, or NULL for an + * unfinished request, 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 LdapDefaultClient 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_pl_LdapDefaultClient_InitiateRequest( + PKIX_PL_LdapClient *genericClient, + LDAPRequestParams *requestParams, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext) +{ + PKIX_List *searchResponseList = NULL; + SECItem *encoded = NULL; + LDAPFilter *filter = NULL; + PKIX_PL_LdapDefaultClient *client = 0; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, + "pkix_pl_LdapDefaultClient_InitiateRequest"); + PKIX_NULLCHECK_FOUR(genericClient, requestParams, pPollDesc, pResponse); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)genericClient, + PKIX_LDAPDEFAULTCLIENT_TYPE, + plContext), + PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT); + + client = (PKIX_PL_LdapDefaultClient *)genericClient; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAndFilter + (client->arena, requestParams->nc, &filter, plContext), + PKIX_LDAPDEFAULTCLIENTMAKEANDFILTERFAILED); + + PKIX_CHECK(pkix_pl_LdapRequest_Create + (client->arena, + client->messageID++, + requestParams->baseObject, + requestParams->scope, + requestParams->derefAliases, + requestParams->sizeLimit, + requestParams->timeLimit, + PKIX_FALSE, /* attrs only */ + filter, + requestParams->attributes, + &client->currentRequest, + plContext), + PKIX_LDAPREQUESTCREATEFAILED); + + /* check hashtable for matching request */ + PKIX_CHECK(PKIX_PL_HashTable_Lookup + (client->cachePtr, + (PKIX_PL_Object *)(client->currentRequest), + (PKIX_PL_Object **)&searchResponseList, + plContext), + PKIX_HASHTABLELOOKUPFAILED); + + if (searchResponseList != NULL) { + *pPollDesc = NULL; + *pResponse = searchResponseList; + PKIX_DECREF(client->currentRequest); + goto cleanup; + } + + /* It wasn't cached. We'll have to actually send it. */ + + PKIX_CHECK(pkix_pl_LdapRequest_GetEncoded + (client->currentRequest, &encoded, plContext), + PKIX_LDAPREQUESTGETENCODEDFAILED); + + client->sendBuf = encoded->data; + client->bytesToWrite = encoded->len; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext), + PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED); + + /* + * It's not enough that we may be done with a particular read. + * We're still processing the transaction until we've gotten the + * SearchResponseResult message and returned to the BOUND state. + * Otherwise we must still have a read pending, and must hold off + * on returning results. + */ + if ((client->connectStatus == BOUND) && + (client->entriesFound != NULL)) { + *pPollDesc = NULL; + *pResponse = client->entriesFound; + client->entriesFound = NULL; + PKIX_DECREF(client->currentRequest); + } else { + *pPollDesc = &client->pollDesc; + *pResponse = NULL; + } + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); + +} + +/* + * FUNCTION: pkix_pl_LdapDefaultClient_ResumeRequest + * DESCRIPTION: + * + * + * PARAMETERS: + * "client" + * The address of the LdapDefaultClient object. Must be non-NULL. + * "pPollDesc" + * The location where the address of the PRPollDesc is stored, if the + * client returns with I/O pending. + * "pResponse" + * The address where the List of LDAPResponses, or NULL for an + * unfinished request, 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 LdapDefaultClient 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_pl_LdapDefaultClient_ResumeRequest( + PKIX_PL_LdapClient *genericClient, + void **pPollDesc, + PKIX_List **pResponse, + void *plContext) +{ + PKIX_PL_LdapDefaultClient *client = 0; + + PKIX_ENTER + (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_ResumeRequest"); + PKIX_NULLCHECK_THREE(genericClient, pPollDesc, pResponse); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)genericClient, + PKIX_LDAPDEFAULTCLIENT_TYPE, + plContext), + PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT); + + client = (PKIX_PL_LdapDefaultClient *)genericClient; + + PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext), + PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED); + + /* + * It's not enough that we may be done with a particular read. + * We're still processing the transaction until we've gotten the + * SearchResponseResult message and returned to the BOUND state. + * Otherwise we must still have a read pending, and must hold off + * on returning results. + */ + if ((client->connectStatus == BOUND) && + (client->entriesFound != NULL)) { + *pPollDesc = NULL; + *pResponse = client->entriesFound; + client->entriesFound = NULL; + PKIX_DECREF(client->currentRequest); + } else { + *pPollDesc = &client->pollDesc; + *pResponse = NULL; + } + +cleanup: + + PKIX_RETURN(LDAPDEFAULTCLIENT); + +} + +/* --Public-LdapDefaultClient-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_PL_LdapDefaultClient_AbandonRequest + * DESCRIPTION: + * + * This function creates and sends an LDAP-protocol "Abandon" message to the + * server connected to the LdapDefaultClient pointed to by "client". + * + * PARAMETERS: + * "client" + * The LdapDefaultClient whose connection is to be abandoned. 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_PL_LdapDefaultClient_AbandonRequest( + PKIX_PL_LdapDefaultClient *client, + void *plContext) +{ + PKIX_Int32 bytesWritten = 0; + PKIX_PL_Socket_Callback *callbackList = NULL; + SECItem *encoded = NULL; + + PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapDefaultClient_AbandonRequest"); + PKIX_NULLCHECK_ONE(client); + + if (client->connectStatus == RECV_PENDING) { + PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAbandon + (client->arena, + (client->messageID) - 1, + &encoded, + plContext), + PKIX_LDAPDEFAULTCLIENTMAKEABANDONFAILED); + + callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); + PKIX_CHECK(callbackList->sendCallback + (client->clientSocket, + encoded->data, + encoded->len, + &bytesWritten, + plContext), + PKIX_SOCKETSENDFAILED); + + if (bytesWritten < 0) { + client->connectStatus = ABANDON_PENDING; + } else { + client->connectStatus = BOUND; + } + } + + PKIX_DECREF(client->entriesFound); + PKIX_DECREF(client->currentRequest); + PKIX_DECREF(client->currentResponse); + +cleanup: + + PKIX_DECREF(client); + + PKIX_RETURN(CERTSTORE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h new file mode 100644 index 0000000000..4abe043281 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h @@ -0,0 +1,82 @@ +/* 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_pl_ldapdefaultclient.h + * + * LDAPDefaultClient Object Type Definition + * + */ + +#ifndef _PKIX_PL_LDAPDEFAULTCLIENT_H +#define _PKIX_PL_LDAPDEFAULTCLIENT_H + +#include "pkix_pl_ldapt.h" +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * At the time of this version, there are unresolved questions about the LDAP + * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not + * clear whether they are appropriate to this application. We have tested only + * using servers that do not expect authentication, and that reject BIND + * messages. It is not clear what values might be appropriate for the bindname + * and authentication fields, which are currently implemented as char strings + * supplied by the caller. (If this changes, the API and possibly the templates + * will have to change.) Therefore the LDAPClient_Create API contains a + * BindAPI structure, a union, which will have to be revised and extended when + * this area of the protocol is better understood. + * + */ + +typedef enum { + CONNECT_PENDING, + CONNECTED, + BIND_PENDING, + BIND_RESPONSE, + BIND_RESPONSE_PENDING, + BOUND, + SEND_PENDING, + RECV, + RECV_PENDING, + RECV_INITIAL, + RECV_NONINITIAL, + ABANDON_PENDING +} LdapClientConnectStatus; + +struct PKIX_PL_LdapDefaultClientStruct { + PKIX_PL_LdapClient vtable; + LdapClientConnectStatus connectStatus; + PKIX_UInt32 messageID; + PKIX_PL_HashTable *cachePtr; + PKIX_PL_Socket *clientSocket; + PRPollDesc pollDesc; + void *callbackList; /* cast this to (PKIX_PL_Socket_Callback *) */ + LDAPBindAPI *bindAPI; + PLArenaPool *arena; + PRTime lastIO; + void *sendBuf; + PKIX_UInt32 bytesToWrite; + void *rcvBuf; + PKIX_UInt32 capacity; + void *currentInPtr; + PKIX_UInt32 currentBytesAvailable; + void *bindMsg; + PKIX_UInt32 bindMsgLen; + PKIX_List *entriesFound; + PKIX_PL_LdapRequest *currentRequest; + PKIX_PL_LdapResponse *currentResponse; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_LdapDefaultClient_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_LDAPDEFAULTCLIENT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c new file mode 100644 index 0000000000..4546e339a5 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c @@ -0,0 +1,757 @@ +/* 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_pl_ldaprequest.c + * + */ + +#include "pkix_pl_ldaprequest.h" + +/* --Private-LdapRequest-Functions------------------------------------- */ + +/* Note: lengths do not include the NULL terminator */ +static const char caAttr[] = "caCertificate;binary"; +static unsigned int caAttrLen = sizeof(caAttr) - 1; +static const char uAttr[] = "userCertificate;binary"; +static unsigned int uAttrLen = sizeof(uAttr) - 1; +static const char ccpAttr[] = "crossCertificatePair;binary"; +static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1; +static const char crlAttr[] = "certificateRevocationList;binary"; +static unsigned int crlAttrLen = sizeof(crlAttr) - 1; +static const char arlAttr[] = "authorityRevocationList;binary"; +static unsigned int arlAttrLen = sizeof(arlAttr) - 1; + +/* + * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of + * LdapRequest and LdapResponse could be considered part of the LDAP client. + * But the constants, above, would have to be copied as well, and they are + * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be + * two copies. + */ + +/* + * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit + * DESCRIPTION: + * + * This function creates an attribute mask bit corresponding to the SECItem + * pointed to by "attrType", storing the result at "pAttrBit". The comparison + * is case-insensitive. If "attrType" does not match any of the known types, + * zero is stored at "pAttrBit". + * + * PARAMETERS + * "attrType" + * The address of the SECItem whose string contents are to be compared to + * the various known attribute types. Must be non-NULL. + * "pAttrBit" + * The address where 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 an LdapRequest 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_pl_LdapRequest_AttrTypeToBit( + SECItem *attrType, + LdapAttrMask *pAttrBit, + void *plContext) +{ + LdapAttrMask attrBit = 0; + unsigned int attrLen = 0; + const char *s = NULL; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit"); + PKIX_NULLCHECK_TWO(attrType, pAttrBit); + + s = (const char *)attrType->data; + attrLen = attrType->len; + + /* + * Taking note of the fact that all of the comparand strings are + * different lengths, we do a slight optimization. If a string + * length matches but the string does not match, we skip comparing + * to the other strings. If new strings are added to the comparand + * list, and any are of equal length, be careful to change the + * grouping of tests accordingly. + */ + if (attrLen == caAttrLen) { + if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) { + attrBit = LDAPATTR_CACERT; + } + } else if (attrLen == uAttrLen) { + if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) { + attrBit = LDAPATTR_USERCERT; + } + } else if (attrLen == ccpAttrLen) { + if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) { + attrBit = LDAPATTR_CROSSPAIRCERT; + } + } else if (attrLen == crlAttrLen) { + if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) { + attrBit = LDAPATTR_CERTREVLIST; + } + } else if (attrLen == arlAttrLen) { + if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) { + attrBit = LDAPATTR_AUTHREVLIST; + } + } + + *pAttrBit = attrBit; + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit + * DESCRIPTION: + * + * This function creates an attribute mask bit corresponding to the null- + * terminated string pointed to by "attrString", storing the result at + * "pAttrBit". The comparison is case-insensitive. If "attrString" does not + * match any of the known types, zero is stored at "pAttrBit". + * + * PARAMETERS + * "attrString" + * The address of the null-terminated string whose contents are to be compared to + * the various known attribute types. Must be non-NULL. + * "pAttrBit" + * The address where 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 an LdapRequest 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_pl_LdapRequest_AttrStringToBit( + char *attrString, + LdapAttrMask *pAttrBit, + void *plContext) +{ + LdapAttrMask attrBit = 0; + unsigned int attrLen = 0; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit"); + PKIX_NULLCHECK_TWO(attrString, pAttrBit); + + attrLen = PL_strlen(attrString); + + /* + * Taking note of the fact that all of the comparand strings are + * different lengths, we do a slight optimization. If a string + * length matches but the string does not match, we skip comparing + * to the other strings. If new strings are added to the comparand + * list, and any are of equal length, be careful to change the + * grouping of tests accordingly. + */ + if (attrLen == caAttrLen) { + if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) { + attrBit = LDAPATTR_CACERT; + } + } else if (attrLen == uAttrLen) { + if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) { + attrBit = LDAPATTR_USERCERT; + } + } else if (attrLen == ccpAttrLen) { + if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) { + attrBit = LDAPATTR_CROSSPAIRCERT; + } + } else if (attrLen == crlAttrLen) { + if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) { + attrBit = LDAPATTR_CERTREVLIST; + } + } else if (attrLen == arlAttrLen) { + if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) { + attrBit = LDAPATTR_AUTHREVLIST; + } + } + + *pAttrBit = attrBit; + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs + * DESCRIPTION: + * + * This function obtains the attribute mask bits from the LdapRequest pointed + * to by "request", creates the corresponding array of AttributeTypes for the + * encoding of the SearchRequest message. + * + * PARAMETERS + * "request" + * The address of the LdapRequest whose attributes are to be encoded. 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 LdapRequest 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_pl_LdapRequest_EncodeAttrs( + PKIX_PL_LdapRequest *request, + void *plContext) +{ + SECItem **attrArray = NULL; + PKIX_UInt32 attrIndex = 0; + LdapAttrMask attrBits; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs"); + PKIX_NULLCHECK_ONE(request); + + /* construct "attrs" according to bits in request->attrBits */ + attrBits = request->attrBits; + attrArray = request->attrArray; + if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) { + attrArray[attrIndex] = &(request->attributes[attrIndex]); + request->attributes[attrIndex].type = siAsciiString; + request->attributes[attrIndex].data = (unsigned char *)caAttr; + request->attributes[attrIndex].len = caAttrLen; + attrIndex++; + } + if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) { + attrArray[attrIndex] = &(request->attributes[attrIndex]); + request->attributes[attrIndex].type = siAsciiString; + request->attributes[attrIndex].data = (unsigned char *)uAttr; + request->attributes[attrIndex].len = uAttrLen; + attrIndex++; + } + if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) { + attrArray[attrIndex] = &(request->attributes[attrIndex]); + request->attributes[attrIndex].type = siAsciiString; + request->attributes[attrIndex].data = (unsigned char *)ccpAttr; + request->attributes[attrIndex].len = ccpAttrLen; + attrIndex++; + } + if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) { + attrArray[attrIndex] = &(request->attributes[attrIndex]); + request->attributes[attrIndex].type = siAsciiString; + request->attributes[attrIndex].data = (unsigned char *)crlAttr; + request->attributes[attrIndex].len = crlAttrLen; + attrIndex++; + } + if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) { + attrArray[attrIndex] = &(request->attributes[attrIndex]); + request->attributes[attrIndex].type = siAsciiString; + request->attributes[attrIndex].data = (unsigned char *)arlAttr; + request->attributes[attrIndex].len = arlAttrLen; + attrIndex++; + } + attrArray[attrIndex] = (SECItem *)NULL; + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapRequest_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext), + PKIX_OBJECTNOTLDAPREQUEST); + + /* + * All dynamic fields in an LDAPRequest are allocated + * in an arena, and will be freed when the arena is destroyed. + */ + +cleanup: + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapRequest_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 dataLen = 0; + PKIX_UInt32 dindex = 0; + PKIX_UInt32 sizeOfLength = 0; + PKIX_UInt32 idLen = 0; + const unsigned char *msgBuf = NULL; + PKIX_PL_LdapRequest *ldapRq = NULL; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext), + PKIX_OBJECTNOTLDAPREQUEST); + + ldapRq = (PKIX_PL_LdapRequest *)object; + + *pHashcode = 0; + + /* + * Two requests that differ only in msgnum are a match! Therefore, + * start hashcoding beyond the encoded messageID field. + */ + if (ldapRq->encoded) { + msgBuf = (const unsigned char *)ldapRq->encoded->data; + /* Is message length short form (one octet) or long form? */ + if ((msgBuf[1] & 0x80) != 0) { + sizeOfLength = msgBuf[1] & 0x7F; + for (dindex = 0; dindex < sizeOfLength; dindex++) { + dataLen = (dataLen << 8) + msgBuf[dindex + 2]; + } + } else { + dataLen = msgBuf[1]; + } + + /* How many bytes for the messageID? (Assume short form) */ + idLen = msgBuf[dindex + 3] + 2; + dindex += idLen; + dataLen -= idLen; + msgBuf = &msgBuf[dindex + 2]; + + PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext), + PKIX_HASHFAILED); + } + +cleanup: + + PKIX_RETURN(LDAPREQUEST); + +} + +/* + * FUNCTION: pkix_pl_LdapRequest_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapRequest_Equals( + PKIX_PL_Object *firstObj, + PKIX_PL_Object *secondObj, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_LdapRequest *firstReq = NULL; + PKIX_PL_LdapRequest *secondReq = NULL; + PKIX_UInt32 secondType = 0; + PKIX_UInt32 firstLen = 0; + const unsigned char *firstData = NULL; + const unsigned char *secondData = NULL; + PKIX_UInt32 sizeOfLength = 0; + PKIX_UInt32 dindex = 0; + PKIX_UInt32 i = 0; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals"); + PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); + + /* test that firstObj is a LdapRequest */ + PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext), + PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST); + + /* + * Since we know firstObj is a LdapRequest, if both references are + * identical, they must be equal + */ + if (firstObj == secondObj){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObj isn't a LdapRequest, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObj, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LDAPREQUEST_TYPE) { + goto cleanup; + } + + firstReq = (PKIX_PL_LdapRequest *)firstObj; + secondReq = (PKIX_PL_LdapRequest *)secondObj; + + /* If either lacks an encoded string, they cannot be compared */ + if (!(firstReq->encoded) || !(secondReq->encoded)) { + goto cleanup; + } + + if (firstReq->encoded->len != secondReq->encoded->len) { + goto cleanup; + } + + firstData = (const unsigned char *)firstReq->encoded->data; + secondData = (const unsigned char *)secondReq->encoded->data; + + /* + * Two requests that differ only in msgnum are equal! Therefore, + * start the byte comparison beyond the encoded messageID field. + */ + + /* Is message length short form (one octet) or long form? */ + if ((firstData[1] & 0x80) != 0) { + sizeOfLength = firstData[1] & 0x7F; + for (dindex = 0; dindex < sizeOfLength; dindex++) { + firstLen = (firstLen << 8) + firstData[dindex + 2]; + } + } else { + firstLen = firstData[1]; + } + + /* How many bytes for the messageID? (Assume short form) */ + i = firstData[dindex + 3] + 2; + dindex += i; + firstLen -= i; + firstData = &firstData[dindex + 2]; + + /* + * In theory, we have to calculate where the second message data + * begins by checking its length encodings. But if these messages + * are equal, we can re-use the calculation we already did. If they + * are not equal, the byte comparisons will surely fail. + */ + + secondData = &secondData[dindex + 2]; + + for (i = 0; i < firstLen; i++) { + if (firstData[i] != secondData[i]) { + goto cleanup; + } + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LDAPREQUEST_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_pl_LdapRequest_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf"); + + entry.description = "LdapRequest"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest); + entry.destructor = pkix_pl_LdapRequest_Destroy; + entry.equalsFunction = pkix_pl_LdapRequest_Equals; + entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_LDAPREQUEST_TYPE] = entry; + + PKIX_RETURN(LDAPREQUEST); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_LdapRequest_Create + * DESCRIPTION: + * + * This function creates an LdapRequest using the PLArenaPool pointed to by + * "arena", a message number whose value is "msgnum", a base object pointed to + * by "issuerDN", a scope whose value is "scope", a derefAliases flag whose + * value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit + * whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a + * filter whose value is "filter", and attribute bits whose value is + * "attrBits"; storing the result at "pRequestMsg". + * + * See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of + * message components, and see pkix_pl_ldapt.h for data types. + * + * PARAMETERS + * "arena" + * The address of the PLArenaPool to be used in the encoding. Must be + * non-NULL. + * "msgnum" + * The UInt32 message number to be used for the messageID component of the + * LDAP message exchange. + * "issuerDN" + * The address of the string to be used for the baseObject component of the + * LDAP SearchRequest message. Must be non-NULL. + * "scope" + * The (enumerated) ScopeType to be used for the scope component of the + * LDAP SearchRequest message + * "derefAliases" + * The (enumerated) DerefType to be used for the derefAliases component of + * the LDAP SearchRequest message + * "sizeLimit" + * The UInt32 value to be used for the sizeLimit component of the LDAP + * SearchRequest message + * "timeLimit" + * The UInt32 value to be used for the timeLimit component of the LDAP + * SearchRequest message + * "attrsOnly" + * The Boolean value to be used for the attrsOnly component of the LDAP + * SearchRequest message + * "filter" + * The filter to be used for the filter component of the LDAP + * SearchRequest message + * "attrBits" + * The LdapAttrMask bits indicating the attributes to be included in the + * attributes sequence of the LDAP SearchRequest message + * "pRequestMsg" + * The address at which the address of the LdapRequest 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 an LdapRequest Error if the function fails in a non-fatal way. + * Returns a Fatal Error if the function fails in an unrecoverable way. + */ +/* + * SearchRequest ::= + * [APPLICATION 3] SEQUENCE { + * baseObject LDAPDN, + * scope ENUMERATED { + * baseObject (0), + * singleLevel (1), + * wholeSubtree (2) + * }, + * derefAliases ENUMERATED { + * neverDerefAliases (0), + * derefInSearching (1), + * derefFindingBaseObj (2), + * alwaysDerefAliases (3) + * }, + * sizeLimit INTEGER (0 .. MAXINT), + * -- value of 0 implies no sizeLimit + * timeLimit INTEGER (0 .. MAXINT), + * -- value of 0 implies no timeLimit + * attrsOnly BOOLEAN, + * -- TRUE, if only attributes (without values) + * -- to be returned + * filter Filter, + * attributes SEQUENCE OF AttributeType + * } + * + * Filter ::= + * CHOICE { + * and [0] SET OF Filter, + * or [1] SET OF Filter, + * not [2] Filter, + * equalityMatch [3] AttributeValueAssertion, + * substrings [4] SubstringFilter, + * greaterOrEqual [5] AttributeValueAssertion, + * lessOrEqual [6] AttributeValueAssertion, + * present [7] AttributeType, + * approxMatch [8] AttributeValueAssertion + * } + * + * SubstringFilter ::= + * SEQUENCE { + * type AttributeType, + * SEQUENCE OF CHOICE { + * initial [0] LDAPString, + * any [1] LDAPString, + * final [2] LDAPString, + * } + * } + * + * AttributeValueAssertion ::= + * SEQUENCE { + * attributeType AttributeType, + * attributeValue AttributeValue, + * } + * + * AttributeValue ::= OCTET STRING + * + * AttributeType ::= LDAPString + * -- text name of the attribute, or dotted + * -- OID representation + * + * LDAPDN ::= LDAPString + * + * LDAPString ::= OCTET STRING + * + */ +PKIX_Error * +pkix_pl_LdapRequest_Create( + PLArenaPool *arena, + PKIX_UInt32 msgnum, + char *issuerDN, + ScopeType scope, + DerefType derefAliases, + PKIX_UInt32 sizeLimit, + PKIX_UInt32 timeLimit, + char attrsOnly, + LDAPFilter *filter, + LdapAttrMask attrBits, + PKIX_PL_LdapRequest **pRequestMsg, + void *plContext) +{ + LDAPMessage msg; + LDAPSearch *search; + PKIX_PL_LdapRequest *ldapRequest = NULL; + char scopeTypeAsChar; + char derefAliasesTypeAsChar; + SECItem *attrArray[MAX_LDAPATTRS + 1]; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create"); + PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg); + + /* create a PKIX_PL_LdapRequest object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LDAPREQUEST_TYPE, + sizeof (PKIX_PL_LdapRequest), + (PKIX_PL_Object **)&ldapRequest, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + ldapRequest->arena = arena; + ldapRequest->msgnum = msgnum; + ldapRequest->issuerDN = issuerDN; + ldapRequest->scope = scope; + ldapRequest->derefAliases = derefAliases; + ldapRequest->sizeLimit = sizeLimit; + ldapRequest->timeLimit = timeLimit; + ldapRequest->attrsOnly = attrsOnly; + ldapRequest->filter = filter; + ldapRequest->attrBits = attrBits; + + ldapRequest->attrArray = attrArray; + + PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs + (ldapRequest, plContext), + PKIX_LDAPREQUESTENCODEATTRSFAILED); + + PKIX_PL_NSSCALL + (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage))); + + msg.messageID.type = siUnsignedInteger; + msg.messageID.data = (void*)&msgnum; + msg.messageID.len = sizeof (msgnum); + + msg.protocolOp.selector = LDAP_SEARCH_TYPE; + + search = &(msg.protocolOp.op.searchMsg); + + search->baseObject.type = siAsciiString; + search->baseObject.data = (void *)issuerDN; + search->baseObject.len = PL_strlen(issuerDN); + scopeTypeAsChar = (char)scope; + search->scope.type = siUnsignedInteger; + search->scope.data = (void *)&scopeTypeAsChar; + search->scope.len = sizeof (scopeTypeAsChar); + derefAliasesTypeAsChar = (char)derefAliases; + search->derefAliases.type = siUnsignedInteger; + search->derefAliases.data = + (void *)&derefAliasesTypeAsChar; + search->derefAliases.len = + sizeof (derefAliasesTypeAsChar); + search->sizeLimit.type = siUnsignedInteger; + search->sizeLimit.data = (void *)&sizeLimit; + search->sizeLimit.len = sizeof (PKIX_UInt32); + search->timeLimit.type = siUnsignedInteger; + search->timeLimit.data = (void *)&timeLimit; + search->timeLimit.len = sizeof (PKIX_UInt32); + search->attrsOnly.type = siBuffer; + search->attrsOnly.data = (void *)&attrsOnly; + search->attrsOnly.len = sizeof (attrsOnly); + + PKIX_PL_NSSCALL + (LDAPREQUEST, + PORT_Memcpy, + (&search->filter, filter, sizeof (LDAPFilter))); + + search->attributes = attrArray; + + PKIX_PL_NSSCALLRV + (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem, + (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); + + if (!(ldapRequest->encoded)) { + PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST); + } + + *pRequestMsg = ldapRequest; + +cleanup: + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(ldapRequest); + } + + PKIX_RETURN(LDAPREQUEST); +} + +/* + * FUNCTION: pkix_pl_LdapRequest_GetEncoded + * DESCRIPTION: + * + * This function obtains the encoded message from the LdapRequest pointed to + * by "request", storing the result at "pRequestBuf". + * + * PARAMETERS + * "request" + * The address of the LdapRequest whose encoded message is to be + * retrieved. Must be non-NULL. + * "pRequestBuf" + * The address at which is stored the address of the encoded message. 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 LdapRequest 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_pl_LdapRequest_GetEncoded( + PKIX_PL_LdapRequest *request, + SECItem **pRequestBuf, + void *plContext) +{ + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded"); + PKIX_NULLCHECK_TWO(request, pRequestBuf); + + *pRequestBuf = request->encoded; + + PKIX_RETURN(LDAPREQUEST); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h new file mode 100644 index 0000000000..1d05a9447e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h @@ -0,0 +1,86 @@ +/* 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_pl_ldaprequest.h + * + * LdapRequest Object Definitions + * + */ + +#ifndef _PKIX_PL_LDAPREQUEST_H +#define _PKIX_PL_LDAPREQUEST_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + USER_CERT, + CA_CERT, + CROSS_CERT, + CRL, + ARL, + DELTA_CRL +} PKIX_PL_LdapAttr; + +struct PKIX_PL_LdapRequestStruct{ + PLArenaPool *arena; + PKIX_UInt32 msgnum; + char *issuerDN; + ScopeType scope; + DerefType derefAliases; + PKIX_UInt32 sizeLimit; + PKIX_UInt32 timeLimit; + char attrsOnly; + LDAPFilter *filter; + LdapAttrMask attrBits; + SECItem attributes[MAX_LDAPATTRS]; + SECItem **attrArray; + SECItem *encoded; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_LdapRequest_Create( + PLArenaPool *arena, + PKIX_UInt32 msgnum, + char *issuerDN, + ScopeType scope, + DerefType derefAliases, + PKIX_UInt32 sizeLimit, + PKIX_UInt32 timeLimit, + char attrsOnly, + LDAPFilter *filter, + LdapAttrMask attrBits, + PKIX_PL_LdapRequest **pRequestMsg, + void *plContext); + +PKIX_Error * +pkix_pl_LdapRequest_AttrTypeToBit( + SECItem *attrType, + LdapAttrMask *pAttrBit, + void *plContext); + +PKIX_Error * +pkix_pl_LdapRequest_AttrStringToBit( + char *attrString, + LdapAttrMask *pAttrBit, + void *plContext); + +PKIX_Error * +pkix_pl_LdapRequest_GetEncoded( + PKIX_PL_LdapRequest *request, + SECItem **pRequestBuf, + void *plContext); + +PKIX_Error *pkix_pl_LdapRequest_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_LDAPREQUEST_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c new file mode 100644 index 0000000000..cd2543f3be --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c @@ -0,0 +1,786 @@ +/* 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_pl_ldapresponse.c + * + */ + +#include <fcntl.h> +#include "pkix_pl_ldapresponse.h" + +/* --Private-LdapResponse-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_LdapResponse_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapResponse_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_LdapResponse *ldapRsp = NULL; + LDAPMessage *m = NULL; + LDAPSearchResponseEntry *entry = NULL; + LDAPSearchResponseResult *result = NULL; + LDAPSearchResponseAttr **attributes = NULL; + LDAPSearchResponseAttr *attr = NULL; + SECItem **valp = NULL; + SECItem *val = NULL; + + PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext), + PKIX_OBJECTNOTLDAPRESPONSE); + + ldapRsp = (PKIX_PL_LdapResponse *)object; + + m = &ldapRsp->decoded; + + if (m->messageID.data != NULL) { + PR_Free(m->messageID.data); + } + + if (m->protocolOp.selector == + LDAP_SEARCHRESPONSEENTRY_TYPE) { + entry = &m->protocolOp.op.searchResponseEntryMsg; + if (entry->objectName.data != NULL) { + PR_Free(entry->objectName.data); + } + if (entry->attributes != NULL) { + for (attributes = entry->attributes; + *attributes != NULL; + attributes++) { + attr = *attributes; + PR_Free(attr->attrType.data); + for (valp = attr->val; *valp != NULL; valp++) { + val = *valp; + if (val->data != NULL) { + PR_Free(val->data); + } + PR_Free(val); + } + PR_Free(attr->val); + PR_Free(attr); + } + PR_Free(entry->attributes); + } + } else if (m->protocolOp.selector == + LDAP_SEARCHRESPONSERESULT_TYPE) { + result = &m->protocolOp.op.searchResponseResultMsg; + if (result->resultCode.data != NULL) { + PR_Free(result->resultCode.data); + } + } + + PKIX_FREE(ldapRsp->derEncoded.data); + +cleanup: + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapResponse_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 dataLen = 0; + PKIX_UInt32 dindex = 0; + PKIX_UInt32 sizeOfLength = 0; + PKIX_UInt32 idLen = 0; + const unsigned char *msgBuf = NULL; + PKIX_PL_LdapResponse *ldapRsp = NULL; + + PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext), + PKIX_OBJECTNOTLDAPRESPONSE); + + ldapRsp = (PKIX_PL_LdapResponse *)object; + + *pHashcode = 0; + + /* + * Two responses that differ only in msgnum are a match! Therefore, + * start hashcoding beyond the encoded messageID field. + */ + if (ldapRsp->derEncoded.data) { + msgBuf = (const unsigned char *)ldapRsp->derEncoded.data; + /* Is message length short form (one octet) or long form? */ + if ((msgBuf[1] & 0x80) != 0) { + sizeOfLength = msgBuf[1] & 0x7F; + for (dindex = 0; dindex < sizeOfLength; dindex++) { + dataLen = (dataLen << 8) + msgBuf[dindex + 2]; + } + } else { + dataLen = msgBuf[1]; + } + + /* How many bytes for the messageID? (Assume short form) */ + idLen = msgBuf[dindex + 3] + 2; + dindex += idLen; + dataLen -= idLen; + msgBuf = &msgBuf[dindex + 2]; + + PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext), + PKIX_HASHFAILED); + } + +cleanup: + + PKIX_RETURN(LDAPRESPONSE); + +} + +/* + * FUNCTION: pkix_pl_LdapResponse_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_LdapResponse_Equals( + PKIX_PL_Object *firstObj, + PKIX_PL_Object *secondObj, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_LdapResponse *rsp1 = NULL; + PKIX_PL_LdapResponse *rsp2 = NULL; + PKIX_UInt32 secondType = 0; + PKIX_UInt32 firstLen = 0; + const unsigned char *firstData = NULL; + const unsigned char *secondData = NULL; + PKIX_UInt32 sizeOfLength = 0; + PKIX_UInt32 dindex = 0; + PKIX_UInt32 i = 0; + + PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Equals"); + PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); + + /* test that firstObj is a LdapResponse */ + PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPRESPONSE_TYPE, plContext), + PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE); + + /* + * Since we know firstObj is a LdapResponse, if both references are + * identical, they must be equal + */ + if (firstObj == secondObj){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObj isn't a LdapResponse, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LDAPRESPONSE_TYPE) { + goto cleanup; + } + + rsp1 = (PKIX_PL_LdapResponse *)firstObj; + rsp2 = (PKIX_PL_LdapResponse *)secondObj; + + /* If either lacks an encoded string, they cannot be compared */ + if (!(rsp1->derEncoded.data) || !(rsp2->derEncoded.data)) { + goto cleanup; + } + + if (rsp1->derEncoded.len != rsp2->derEncoded.len) { + goto cleanup; + } + + firstData = (const unsigned char *)rsp1->derEncoded.data; + secondData = (const unsigned char *)rsp2->derEncoded.data; + + /* + * Two responses that differ only in msgnum are equal! Therefore, + * start the byte comparison beyond the encoded messageID field. + */ + + /* Is message length short form (one octet) or long form? */ + if ((firstData[1] & 0x80) != 0) { + sizeOfLength = firstData[1] & 0x7F; + for (dindex = 0; dindex < sizeOfLength; dindex++) { + firstLen = (firstLen << 8) + firstData[dindex + 2]; + } + } else { + firstLen = firstData[1]; + } + + /* How many bytes for the messageID? (Assume short form) */ + i = firstData[dindex + 3] + 2; + dindex += i; + firstLen -= i; + firstData = &firstData[dindex + 2]; + + /* + * In theory, we have to calculate where the second message data + * begins by checking its length encodings. But if these messages + * are equal, we can re-use the calculation we already did. If they + * are not equal, the byte comparisons will surely fail. + */ + + secondData = &secondData[dindex + 2]; + + for (i = 0; i < firstLen; i++) { + if (firstData[i] != secondData[i]) { + goto cleanup; + } + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LDAPRESPONSE_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_pl_LdapResponse_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_RegisterSelf"); + + entry.description = "LdapResponse"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_LdapResponse); + entry.destructor = pkix_pl_LdapResponse_Destroy; + entry.equalsFunction = pkix_pl_LdapResponse_Equals; + entry.hashcodeFunction = pkix_pl_LdapResponse_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_LDAPRESPONSE_TYPE] = entry; + + PKIX_RETURN(LDAPRESPONSE); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_LdapResponse_Create + * DESCRIPTION: + * + * This function creates an LdapResponse for the LDAPMessageType provided in + * "responseType" and a buffer capacity provided by "totalLength". It copies + * into its buffer either "totalLength" or "bytesAvailable" bytes, whichever + * is less, from the buffer pointed to by "partialData", storing the number of + * bytes copied at "pBytesConsumed" and storing the address of the LdapResponse + * at "pLdapResponse". + * + * If a message is complete in a single I/O buffer, the LdapResponse will be + * complete when this function returns. If the message carries over into + * additional buffers, their contents will be added to the LdapResponse by + * susequent calls to pkix_pl_LdapResponse_Append. + * + * PARAMETERS + * "responseType" + * The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or + * LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created + * "totalLength" + * The UInt32 value for the total length of the encoded message to be + * stored in the LdapResponse + * "bytesAvailable" + * The UInt32 value for the number of bytes of data available in the + * current buffer. + * "partialData" + * The address from which data is to be copied. + * "pBytesConsumed" + * The address at which is stored the UInt32 number of bytes taken from the + * current buffer. If this number is less than "bytesAvailable", then bytes + * remain in the buffer for the next LdapResponse. Must be non-NULL. + * "pLdapResponse" + * The address where the created LdapResponse 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 an LdapResponse 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_pl_LdapResponse_Create( + LDAPMessageType responseType, + PKIX_UInt32 totalLength, + PKIX_UInt32 bytesAvailable, + void *partialData, + PKIX_UInt32 *pBytesConsumed, + PKIX_PL_LdapResponse **pLdapResponse, + void *plContext) +{ + PKIX_UInt32 bytesConsumed = 0; + PKIX_PL_LdapResponse *ldapResponse = NULL; + void *data = NULL; + + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Create"); + PKIX_NULLCHECK_ONE(pLdapResponse); + + if (bytesAvailable <= totalLength) { + bytesConsumed = bytesAvailable; + } else { + bytesConsumed = totalLength; + } + + /* create a PKIX_PL_LdapResponse object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LDAPRESPONSE_TYPE, + sizeof (PKIX_PL_LdapResponse), + (PKIX_PL_Object **)&ldapResponse, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + ldapResponse->decoded.protocolOp.selector = responseType; + ldapResponse->totalLength = totalLength; + ldapResponse->partialLength = bytesConsumed; + + if (totalLength != 0){ + /* Alloc space for array */ + PKIX_NULLCHECK_ONE(partialData); + + PKIX_CHECK(PKIX_PL_Malloc + (totalLength, + &data, + plContext), + PKIX_MALLOCFAILED); + + PKIX_PL_NSSCALL + (LDAPRESPONSE, + PORT_Memcpy, + (data, partialData, bytesConsumed)); + } + + ldapResponse->derEncoded.type = siBuffer; + ldapResponse->derEncoded.data = data; + ldapResponse->derEncoded.len = totalLength; + *pBytesConsumed = bytesConsumed; + *pLdapResponse = ldapResponse; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(ldapResponse); + } + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_Append + * DESCRIPTION: + * + * This function updates the LdapResponse pointed to by "response" with up to + * "incrLength" from the buffer pointer to by "incrData", storing the number of + * bytes copied at "pBytesConsumed". + * + * PARAMETERS + * "response" + * The address of the LdapResponse being updated. Must be non-zero. + * "incrLength" + * The UInt32 value for the number of bytes of data available in the + * current buffer. + * "incrData" + * The address from which data is to be copied. + * "pBytesConsumed" + * The address at which is stored the UInt32 number of bytes taken from the + * current buffer. If this number is less than "incrLength", then bytes + * remain in the buffer for the next LdapResponse. 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 LdapResponse 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_pl_LdapResponse_Append( + PKIX_PL_LdapResponse *response, + PKIX_UInt32 incrLength, + void *incrData, + PKIX_UInt32 *pBytesConsumed, + void *plContext) +{ + PKIX_UInt32 newPartialLength = 0; + PKIX_UInt32 bytesConsumed = 0; + void *dest = NULL; + + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Append"); + PKIX_NULLCHECK_TWO(response, pBytesConsumed); + + if (incrLength > 0) { + + /* Calculate how many bytes we have room for. */ + bytesConsumed = + response->totalLength - response->partialLength; + + if (bytesConsumed > incrLength) { + bytesConsumed = incrLength; + } + + newPartialLength = response->partialLength + bytesConsumed; + + PKIX_NULLCHECK_ONE(incrData); + + dest = &(((char *)response->derEncoded.data)[ + response->partialLength]); + + PKIX_PL_NSSCALL + (LDAPRESPONSE, + PORT_Memcpy, + (dest, incrData, bytesConsumed)); + + response->partialLength = newPartialLength; + } + + *pBytesConsumed = bytesConsumed; + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_IsComplete + * DESCRIPTION: + * + * This function determines whether the LdapResponse pointed to by "response" + * contains all the data called for by the "totalLength" parameter provided + * when it was created, storing PKIX_TRUE at "pIsComplete" if so, and + * PKIX_FALSE otherwise. + * + * PARAMETERS + * "response" + * The address of the LdapResponse being evaluaTED. Must be non-zero. + * "incrLength" + * The UInt32 value for the number of bytes of data available in the + * current buffer. + * "incrData" + * The address from which data is to be copied. + * "pIsComplete" + * The address at which is stored the Boolean indication of whether the + * LdapResponse 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 an LdapResponse 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_pl_LdapResponse_IsComplete( + PKIX_PL_LdapResponse *response, + PKIX_Boolean *pIsComplete, + void *plContext) +{ + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_IsComplete"); + PKIX_NULLCHECK_TWO(response, pIsComplete); + + if (response->totalLength == response->partialLength) { + *pIsComplete = PKIX_TRUE; + } else { + *pIsComplete = PKIX_FALSE; + } + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_Decode + * DESCRIPTION: + * + * This function decodes the DER data contained in the LdapResponse pointed to + * by "response", using the arena pointed to by "arena", and storing at + * "pStatus" SECSuccess if the decoding was successful and SECFailure + * otherwise. The decoded message is stored in an element of "response". + * + * PARAMETERS + * "arena" + * The address of the PLArenaPool to be used in the decoding. Must be + * non-NULL. + * "response" + * The address of the LdapResponse whose DER data is to be decoded. Must + * be non-NULL. + * "pStatus" + * The address at which is stored the status from the decoding, SECSuccess + * if successful, SECFailure otherwise. 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 LdapResponse 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_pl_LdapResponse_Decode( + PLArenaPool *arena, + PKIX_PL_LdapResponse *response, + SECStatus *pStatus, + void *plContext) +{ + LDAPMessage *msg; + SECStatus rv = SECFailure; + + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Decode"); + PKIX_NULLCHECK_THREE(arena, response, pStatus); + + if (response->totalLength != response->partialLength) { + PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE); + } + + msg = &(response->decoded); + + PKIX_PL_NSSCALL + (LDAPRESPONSE, PORT_Memset, (msg, 0, sizeof (LDAPMessage))); + + PKIX_PL_NSSCALLRV(LDAPRESPONSE, rv, SEC_ASN1DecodeItem, + (NULL, msg, PKIX_PL_LDAPMessageTemplate, &(response->derEncoded))); + + *pStatus = rv; +cleanup: + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_GetMessage + * DESCRIPTION: + * + * This function obtains the decoded message from the LdapResponse pointed to + * by "response", storing the result at "pMessage". + * + * PARAMETERS + * "response" + * The address of the LdapResponse whose decoded message is to be + * retrieved. Must be non-NULL. + * "pMessage" + * The address at which is stored the address of the decoded message. 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_pl_LdapResponse_GetMessage( + PKIX_PL_LdapResponse *response, + LDAPMessage **pMessage, + void *plContext) +{ + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessage"); + PKIX_NULLCHECK_TWO(response, pMessage); + + *pMessage = &response->decoded; + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_GetCapacity + * DESCRIPTION: + * + * This function obtains from the LdapResponse pointed to by "response" the + * number of bytes remaining to be read, based on the totalLength that was + * provided to LdapResponse_Create and the data subsequently provided to + * LdapResponse_Append, storing the result at "pMessage". + * + * PARAMETERS + * "response" + * The address of the LdapResponse whose remaining capacity is to be + * retrieved. Must be non-NULL. + * "pCapacity" + * The address at which is stored the address of the decoded message. 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 LdapResponse 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_pl_LdapResponse_GetCapacity( + PKIX_PL_LdapResponse *response, + PKIX_UInt32 *pCapacity, + void *plContext) +{ + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetCapacity"); + PKIX_NULLCHECK_TWO(response, pCapacity); + + *pCapacity = response->totalLength - response->partialLength; + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_GetMessageType + * DESCRIPTION: + * + * This function obtains the message type from the LdapResponse pointed to + * by "response", storing the result at "pMessageType". + * + * PARAMETERS + * "response" + * The address of the LdapResponse whose message type is to be + * retrieved. Must be non-NULL. + * "pMessageType" + * The address at which is stored the type of the response message. 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_pl_LdapResponse_GetMessageType( + PKIX_PL_LdapResponse *response, + LDAPMessageType *pMessageType, + void *plContext) +{ + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessageType"); + PKIX_NULLCHECK_TWO(response, pMessageType); + + *pMessageType = response->decoded.protocolOp.selector; + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_GetResultCode + * DESCRIPTION: + * + * This function obtains the result code from the LdapResponse pointed to + * by "response", storing the result at "pResultCode". + * + * PARAMETERS + * "response" + * The address of the LdapResponse whose result code is to be + * retrieved. Must be non-NULL. + * "pResultCode" + * The address at which is stored the address of the decoded message. 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 LdapResponse 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_pl_LdapResponse_GetResultCode( + PKIX_PL_LdapResponse *response, + LDAPResultCode *pResultCode, + void *plContext) +{ + LDAPMessageType messageType = 0; + LDAPSearchResponseResult *resultMsg = NULL; + + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode"); + PKIX_NULLCHECK_TWO(response, pResultCode); + + messageType = response->decoded.protocolOp.selector; + + if (messageType != LDAP_SEARCHRESPONSERESULT_TYPE) { + PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE); + } + + resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg; + + *pResultCode = *(resultMsg->resultCode.data); + +cleanup: + + PKIX_RETURN(LDAPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_LdapResponse_GetAttributes + * DESCRIPTION: + * + * This function obtains the attributes from the LdapResponse pointed to + * by "response", storing the result at "pAttributes". + * + * PARAMETERS + * "response" + * The address of the LdapResponse whose decoded message is to be + * retrieved. Must be non-NULL. + * "pAttributes" + * The address at which is stored the attributes of the message. 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 LdapResponse 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_pl_LdapResponse_GetAttributes( + PKIX_PL_LdapResponse *response, + LDAPSearchResponseAttr ***pAttributes, + void *plContext) +{ + LDAPMessageType messageType = 0; + + PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode"); + PKIX_NULLCHECK_TWO(response, pAttributes); + + messageType = response->decoded.protocolOp.selector; + + if (messageType != LDAP_SEARCHRESPONSEENTRY_TYPE) { + PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE); + } + + *pAttributes = response-> + decoded.protocolOp.op.searchResponseEntryMsg.attributes; + +cleanup: + + PKIX_RETURN(LDAPRESPONSE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h new file mode 100644 index 0000000000..37dc916b1e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h @@ -0,0 +1,96 @@ +/* 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_pl_ldapresponse.h + * + * LdapResponse Object Definitions + * + */ + +#ifndef _PKIX_PL_LDAPRESPONSE_H +#define _PKIX_PL_LDAPRESPONSE_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_LdapResponseStruct{ + LDAPMessage decoded; + PKIX_UInt32 partialLength; + PKIX_UInt32 totalLength; + SECItem derEncoded; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_LdapResponse_Create( + LDAPMessageType responseType, + PKIX_UInt32 totalLength, + PKIX_UInt32 bytesAvailable, + void *partialData, + PKIX_UInt32 *pBytesConsumed, + PKIX_PL_LdapResponse **pResponse, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_Append( + PKIX_PL_LdapResponse *response, + PKIX_UInt32 partialLength, + void *partialData, + PKIX_UInt32 *bytesConsumed, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_IsComplete( + PKIX_PL_LdapResponse *response, + PKIX_Boolean *pIsComplete, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_Decode( + PLArenaPool *arena, + PKIX_PL_LdapResponse *response, + SECStatus *pStatus, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_GetMessage( + PKIX_PL_LdapResponse *response, + LDAPMessage **pMessage, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_GetMessageType( + PKIX_PL_LdapResponse *response, + LDAPMessageType *pMessageType, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_GetCapacity( + PKIX_PL_LdapResponse *response, + PKIX_UInt32 *pCapacity, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_GetResultCode( + PKIX_PL_LdapResponse *response, + LDAPResultCode *pResultCode, + void *plContext); + +PKIX_Error * +pkix_pl_LdapResponse_GetAttributes( + PKIX_PL_LdapResponse *response, + LDAPSearchResponseAttr ***pAttributes, + void *plContext); + +PKIX_Error *pkix_pl_LdapResponse_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_LDAPRESPONSE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h new file mode 100644 index 0000000000..539803638c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h @@ -0,0 +1,314 @@ +/* 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/. */ + +#ifndef _LDAP_H_ +#define _LDAP_H_ + +#include "certt.h" +#include "pkixt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const SEC_ASN1Template PKIX_PL_LDAPCrossCertPairTemplate[]; +SEC_ASN1_CHOOSER_DECLARE(PKIX_PL_LDAPCrossCertPairTemplate) +extern const SEC_ASN1Template PKIX_PL_LDAPMessageTemplate[]; +SEC_ASN1_CHOOSER_DECLARE(PKIX_PL_LDAPMessageTemplate) +extern const SEC_ASN1Template LDAPFilterTemplate[]; +SEC_ASN1_CHOOSER_DECLARE(LDAPFilterTemplate) + +/* ********************************************************************** */ + +#define SEC_ASN1_LDAP_STRING SEC_ASN1_OCTET_STRING + +#define LDAPATTR_CACERT (1<<0) +#define LDAPATTR_USERCERT (1<<1) +#define LDAPATTR_CROSSPAIRCERT (1<<2) +#define LDAPATTR_CERTREVLIST (1<<3) +#define LDAPATTR_AUTHREVLIST (1<<4) +#define MAX_LDAPATTRS 5 +typedef PKIX_UInt32 LdapAttrMask; + +typedef enum { + SIMPLE_AUTH = 0, + KRBV42LDAP_AUTH = 1, + KRBV42DSA_AUTH = 2 +} AuthType; + +typedef enum { + BASE_OBJECT = 0, + SINGLE_LEVEL = 1, + WHOLE_SUBTREE = 2 +} ScopeType; + +typedef enum { + NEVER_DEREF = 0, + DEREF_IN_SEARCHING = 1, + DEREF_FINDING_BASEOBJ = 2, + ALWAYS_DEREF = 3 +} DerefType; + +typedef enum { + LDAP_INITIALSUBSTRING_TYPE = 0, + LDAP_ANYSUBSTRING_TYPE = 1, + LDAP_FINALSUBSTRING_TYPE = 2 +} LDAPSubstringFilterType; + +typedef enum { + LDAP_ANDFILTER_TYPE = 0, + LDAP_ORFILTER_TYPE = 1, + LDAP_NOTFILTER_TYPE = 2, + LDAP_EQUALFILTER_TYPE = 3, + LDAP_SUBSTRINGFILTER_TYPE = 4, + LDAP_GREATEROREQUALFILTER_TYPE = 5, + LDAP_LESSOREQUALFILTER_TYPE = 6, + LDAP_PRESENTFILTER_TYPE = 7, + LDAP_APPROXMATCHFILTER_TYPE = 8 +} LDAPFilterType; + +typedef enum { + LDAP_BIND_TYPE = 0, + LDAP_BINDRESPONSE_TYPE = 1, + LDAP_UNBIND_TYPE = 2, + LDAP_SEARCH_TYPE = 3, + LDAP_SEARCHRESPONSEENTRY_TYPE = 4, + LDAP_SEARCHRESPONSERESULT_TYPE = 5, + LDAP_ABANDONREQUEST_TYPE = 16 +} LDAPMessageType; + +typedef enum { + SUCCESS = 0, + OPERATIONSERROR = 1, + PROTOCOLERROR = 2, + TIMELIMITEXCEEDED = 3, + SIZELIMITEXCEEDED = 4, + COMPAREFALSE = 5, + COMPARETRUE = 6, + AUTHMETHODNOTSUPPORTED = 7, + STRONGAUTHREQUIRED = 8, + NOSUCHATTRIBUTE = 16, + UNDEFINEDATTRIBUTETYPE = 17, + INAPPROPRIATEMATCHING = 18, + CONSTRAINTVIOLATION = 19, + ATTRIBUTEORVALUEEXISTS = 20, + INVALIDATTRIBUTESYNTAX = 21, + NOSUCHOBJECT = 32, + ALIASPROBLEM = 33, + INVALIDDNSYNTAX = 34, + ISLEAF = 35, + ALIASDEREFERENCINGPROBLEM = 36, + INAPPROPRIATEAUTHENTICATION = 48, + INVALIDCREDENTIALS = 49, + INSUFFICIENTACCESSRIGHTS = 50, + BUSY = 51, + UNAVAILABLE = 52, + UNWILLINGTOPERFORM = 53, + LOOPDETECT = 54, + NAMINGVIOLATION = 64, + OBJECTCLASSVIOLATION = 65, + NOTALLOWEDONNONLEAF = 66, + NOTALLOWEDONRDN = 67, + ENTRYALREADYEXISTS = 68, + OBJECTCLASSMODSPROHIBITED = 69, + OTHER = 80 +} LDAPResultCode; + +typedef struct LDAPLocationStruct LDAPLocation; +typedef struct LDAPCertPairStruct LDAPCertPair; +typedef struct LDAPSimpleBindStruct LDAPSimpleBind; +typedef struct LDAPBindAPIStruct LDAPBindAPI; +typedef struct LDAPBindStruct LDAPBind; +typedef struct LDAPResultStruct LDAPBindResponse; +typedef struct LDAPResultStruct LDAPResult; +typedef struct LDAPSearchResponseAttrStruct LDAPSearchResponseAttr; +typedef struct LDAPSearchResponseEntryStruct LDAPSearchResponseEntry; +typedef struct LDAPResultStruct LDAPSearchResponseResult; +typedef struct LDAPUnbindStruct LDAPUnbind; +typedef struct LDAPFilterStruct LDAPFilter; +typedef struct LDAPAndFilterStruct LDAPAndFilter; +typedef struct LDAPNotFilterStruct LDAPNotFilter; +typedef struct LDAPSubstringStruct LDAPSubstring; +typedef struct LDAPSubstringFilterStruct LDAPSubstringFilter; +typedef struct LDAPPresentFilterStruct LDAPPresentFilter; +typedef struct LDAPAttributeValueAssertionStruct LDAPAttributeValueAssertion; +typedef struct LDAPNameComponentStruct LDAPNameComponent; +typedef struct LDAPRequestParamsStruct LDAPRequestParams; +typedef struct LDAPSearchStruct LDAPSearch; +typedef struct LDAPAbandonRequestStruct LDAPAbandonRequest; +typedef struct protocolOpStruct LDAPProtocolOp; +typedef struct LDAPMessageStruct LDAPMessage; +typedef LDAPAndFilter LDAPOrFilter; +typedef LDAPAttributeValueAssertion LDAPEqualFilter; +typedef LDAPAttributeValueAssertion LDAPGreaterOrEqualFilter; +typedef LDAPAttributeValueAssertion LDAPLessOrEqualFilter; +typedef LDAPAttributeValueAssertion LDAPApproxMatchFilter; + +struct LDAPLocationStruct { + PLArenaPool *arena; + void *serverSite; + void **filterString; + void **attrBitString; +}; + +struct LDAPCertPairStruct { + SECItem forward; + SECItem reverse; +}; + +struct LDAPSimpleBindStruct { + char *bindName; + char *authentication; +}; + +struct LDAPBindAPIStruct { + AuthType selector; + union { + LDAPSimpleBind simple; + } chooser; +}; + +struct LDAPBindStruct { + SECItem version; + SECItem bindName; + SECItem authentication; +}; + +struct LDAPResultStruct { + SECItem resultCode; + SECItem matchedDN; + SECItem errorMessage; +}; + +struct LDAPSearchResponseAttrStruct { + SECItem attrType; + SECItem **val; +}; + +struct LDAPSearchResponseEntryStruct { + SECItem objectName; + LDAPSearchResponseAttr **attributes; +}; + +struct LDAPUnbindStruct { + SECItem dummy; +}; + +struct LDAPAndFilterStruct { + LDAPFilter **filters; +}; + +struct LDAPNotFilterStruct { + LDAPFilter *filter; +}; + +struct LDAPSubstringStruct { + LDAPSubstringFilterType selector; + SECItem item; +}; + +struct LDAPSubstringFilterStruct { + SECItem attrType; + LDAPSubstring *strings; +}; + +struct LDAPPresentFilterStruct { + SECItem attrType; +}; + +struct LDAPAttributeValueAssertionStruct { + SECItem attrType; + SECItem attrValue; +}; + +struct LDAPFilterStruct { + LDAPFilterType selector; + union { + LDAPAndFilter andFilter; + LDAPOrFilter orFilter; + LDAPNotFilter notFilter; + LDAPEqualFilter equalFilter; + LDAPSubstringFilter substringFilter; + LDAPGreaterOrEqualFilter greaterOrEqualFilter; + LDAPLessOrEqualFilter lessOrEqualFilter; + LDAPPresentFilter presentFilter; + LDAPApproxMatchFilter approxMatchFilter; + } filter; +}; + +struct LDAPNameComponentStruct { + unsigned char *attrType; + unsigned char *attrValue; +}; + +struct LDAPRequestParamsStruct { + char *baseObject; /* e.g. "c=US" */ + ScopeType scope; + DerefType derefAliases; + PKIX_UInt32 sizeLimit; /* 0 = no limit */ + PRIntervalTime timeLimit; /* 0 = no limit */ + LDAPNameComponent **nc; /* e.g. {{"cn","xxx"},{"o","yyy"},NULL} */ + LdapAttrMask attributes; +}; + +struct LDAPSearchStruct { + SECItem baseObject; + SECItem scope; + SECItem derefAliases; + SECItem sizeLimit; + SECItem timeLimit; + SECItem attrsOnly; + LDAPFilter filter; + SECItem **attributes; +}; + +struct LDAPAbandonRequestStruct { + SECItem messageID; +}; + +struct protocolOpStruct { + LDAPMessageType selector; + union { + LDAPBind bindMsg; + LDAPBindResponse bindResponseMsg; + LDAPUnbind unbindMsg; + LDAPSearch searchMsg; + LDAPSearchResponseEntry searchResponseEntryMsg; + LDAPSearchResponseResult searchResponseResultMsg; + LDAPAbandonRequest abandonRequestMsg; + } op; +}; + +struct LDAPMessageStruct { + SECItem messageID; + LDAPProtocolOp protocolOp; +}; + +typedef struct PKIX_PL_LdapClientStruct PKIX_PL_LdapClient; + +typedef PKIX_Error * +(*PKIX_PL_LdapClient_InitiateFcn)( + PKIX_PL_LdapClient *client, + LDAPRequestParams *requestParams, + void **pNBIO, + PKIX_List **pResponse, + void *plContext); + +typedef PKIX_Error * +(*PKIX_PL_LdapClient_ResumeFcn)( + PKIX_PL_LdapClient *client, + void **pNBIO, + PKIX_List **pResponse, + void *plContext); + +struct PKIX_PL_LdapClientStruct { + PKIX_PL_LdapClient_InitiateFcn initiateFcn; + PKIX_PL_LdapClient_ResumeFcn resumeFcn; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c new file mode 100644 index 0000000000..ecb681929b --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c @@ -0,0 +1,417 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "pkix_pl_ldapt.h" + +SEC_ASN1_MKSUB(SEC_AnyTemplate) +SEC_ASN1_MKSUB(SEC_NullTemplate) +SEC_ASN1_MKSUB(SEC_OctetStringTemplate) + +/* + * CertificatePair ::= SEQUENCE { + * forward [0] Certificate OPTIONAL, + * reverse [1] Certificate OPTIONAL + * -- at least one of the pair shall be present -- + * } + */ + +const SEC_ASN1Template PKIX_PL_LDAPCrossCertPairTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPCertPair) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0, + offsetof(LDAPCertPair, forward), SEC_ASN1_SUB(SEC_AnyTemplate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 1, + offsetof(LDAPCertPair, reverse), SEC_ASN1_SUB(SEC_AnyTemplate) }, + { 0 } +}; + +/* + * BindRequest ::= + * [APPLICATION 0] SEQUENCE { + * version INTEGER (1..127), + * name LDAPDN, + * authentication CHOICE { + * simple [0] OCTET STRING, + * krbv42LDAP [1] OCTET STRING, + * krbv42DSA [2] OCTET STRING + * } + * } + * + * LDAPDN ::= LDAPString + * + * LDAPString ::= OCTET STRING + */ + +#define LDAPStringTemplate SEC_ASN1_SUB(SEC_OctetStringTemplate) + +static const SEC_ASN1Template LDAPBindApplTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL }, + { SEC_ASN1_INTEGER, offsetof(LDAPBind, version) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, bindName) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, authentication) }, + { 0 } +}; + +static const SEC_ASN1Template LDAPBindTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BIND_TYPE, 0, + LDAPBindApplTemplate, sizeof (LDAPBind) } +}; + +/* + * BindResponse ::= [APPLICATION 1] LDAPResult + * + * LDAPResult ::= + * SEQUENCE { + * resultCode ENUMERATED { + * success (0), + * operationsError (1), + * protocolError (2), + * timeLimitExceeded (3), + * sizeLimitExceeded (4), + * compareFalse (5), + * compareTrue (6), + * authMethodNotSupported (7), + * strongAuthRequired (8), + * noSuchAttribute (16), + * undefinedAttributeType (17), + * inappropriateMatching (18), + * constraintViolation (19), + * attributeOrValueExists (20), + * invalidAttributeSyntax (21), + * noSuchObject (32), + * aliasProblem (33), + * invalidDNSyntax (34), + * isLeaf (35), + * aliasDereferencingProblem (36), + * inappropriateAuthentication (48), + * invalidCredentials (49), + * insufficientAccessRights (50), + * busy (51), + * unavailable (52), + * unwillingToPerform (53), + * loopDetect (54), + * namingViolation (64), + * objectClassViolation (65), + * notAllowedOnNonLeaf (66), + * notAllowedOnRDN (67), + * entryAlreadyExists (68), + * objectClassModsProhibited (69), + * other (80) + * }, + * matchedDN LDAPDN, + * errorMessage LDAPString + * } + */ + +static const SEC_ASN1Template LDAPResultTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL }, + { SEC_ASN1_ENUMERATED, offsetof(LDAPResult, resultCode) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, matchedDN) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, errorMessage) }, + { 0 } +}; + +static const SEC_ASN1Template LDAPBindResponseTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BINDRESPONSE_TYPE, 0, + LDAPResultTemplate, sizeof (LDAPBindResponse) } +}; + +/* + * UnbindRequest ::= [APPLICATION 2] NULL + */ + +static const SEC_ASN1Template LDAPUnbindTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | SEC_ASN1_XTRN | + LDAP_UNBIND_TYPE , 0, SEC_ASN1_SUB(SEC_NullTemplate) } +}; + +/* + * AttributeValueAssertion ::= + * SEQUENCE { + * attributeType AttributeType, + * attributeValue AttributeValue, + * } + * + * AttributeType ::= LDAPString + * -- text name of the attribute, or dotted + * -- OID representation + * + * AttributeValue ::= OCTET STRING + */ + +#define LDAPAttributeTypeTemplate LDAPStringTemplate + +/* + * SubstringFilter ::= + * SEQUENCE { + * type AttributeType, + * SEQUENCE OF CHOICE { + * initial [0] LDAPString, + * any [1] LDAPString, + * final [2] LDAPString, + * } + * } + */ + +#define LDAPSubstringFilterInitialTemplate LDAPStringTemplate +#define LDAPSubstringFilterAnyTemplate LDAPStringTemplate +#define LDAPSubstringFilterFinalTemplate LDAPStringTemplate + +static const SEC_ASN1Template LDAPSubstringFilterChoiceTemplate[] = { + { SEC_ASN1_CHOICE, offsetof(LDAPSubstring, selector), 0, + sizeof (LDAPFilter) }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, + offsetof(LDAPSubstring, item), + LDAPSubstringFilterInitialTemplate, + LDAP_INITIALSUBSTRING_TYPE }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, + offsetof(LDAPSubstring, item), + LDAPSubstringFilterAnyTemplate, + LDAP_ANYSUBSTRING_TYPE }, + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, + offsetof(LDAPSubstring, item), + LDAPSubstringFilterFinalTemplate, + LDAP_FINALSUBSTRING_TYPE }, + { 0 } +}; + +/* + * Filter ::= + * CHOICE { + * and [0] SET OF Filter, + * or [1] SET OF Filter, + * not [2] Filter, + * equalityMatch [3] AttributeValueAssertion, + * substrings [4] SubstringFilter, + * greaterOrEqual [5] AttributeValueAssertion, + * lessOrEqual [6] AttributeValueAssertion, + * present [7] AttributeType, + * approxMatch [8] AttributeValueAssertion + } + */ + +static const SEC_ASN1Template LDAPSubstringFilterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPSubstringFilter) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPSubstringFilter, attrType) }, + { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSubstringFilter, strings), + LDAPSubstringFilterChoiceTemplate }, + { 0 } +}; + +const SEC_ASN1Template LDAPFilterTemplate[]; /* forward reference */ + +static const SEC_ASN1Template LDAPSetOfFiltersTemplate[] = { + { SEC_ASN1_SET_OF, 0, LDAPFilterTemplate } +}; + +static const SEC_ASN1Template LDAPAVAFilterTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPAttributeValueAssertion) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPAttributeValueAssertion, attrType) }, + { SEC_ASN1_OCTET_STRING, offsetof(LDAPAttributeValueAssertion, attrValue) }, + { 0 } +}; + +static const SEC_ASN1Template LDAPPresentFilterTemplate[] = { + { SEC_ASN1_LDAP_STRING, offsetof(LDAPPresentFilter, attrType) } +}; + +#define LDAPEqualFilterTemplate LDAPAVAFilterTemplate +#define LDAPGreaterOrEqualFilterTemplate LDAPAVAFilterTemplate +#define LDAPLessOrEqualFilterTemplate LDAPAVAFilterTemplate +#define LDAPApproxMatchFilterTemplate LDAPAVAFilterTemplate + +const SEC_ASN1Template LDAPFilterTemplate[] = { + { SEC_ASN1_CHOICE, offsetof(LDAPFilter, selector), 0, sizeof(LDAPFilter) }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_ANDFILTER_TYPE, + offsetof(LDAPFilter, filter.andFilter.filters), + LDAPSetOfFiltersTemplate, LDAP_ANDFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_ORFILTER_TYPE, + offsetof(LDAPFilter, filter.orFilter.filters), + LDAPSetOfFiltersTemplate, LDAP_ORFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_NOTFILTER_TYPE | SEC_ASN1_POINTER, + offsetof(LDAPFilter, filter.notFilter), + LDAPFilterTemplate, LDAP_NOTFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_EQUALFILTER_TYPE, + offsetof(LDAPFilter, filter.equalFilter), + LDAPEqualFilterTemplate, LDAP_EQUALFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_SUBSTRINGFILTER_TYPE, offsetof(LDAPFilter, filter.substringFilter), + LDAPSubstringFilterTemplate, LDAP_SUBSTRINGFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_GREATEROREQUALFILTER_TYPE, + offsetof(LDAPFilter, filter.greaterOrEqualFilter), + LDAPGreaterOrEqualFilterTemplate, LDAP_GREATEROREQUALFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_LESSOREQUALFILTER_TYPE, + offsetof(LDAPFilter, filter.lessOrEqualFilter), + LDAPLessOrEqualFilterTemplate, LDAP_LESSOREQUALFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_PRESENTFILTER_TYPE, + offsetof(LDAPFilter, filter.presentFilter), + LDAPPresentFilterTemplate, LDAP_PRESENTFILTER_TYPE }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + LDAP_APPROXMATCHFILTER_TYPE, + offsetof(LDAPFilter, filter.approxMatchFilter), + LDAPApproxMatchFilterTemplate, LDAP_APPROXMATCHFILTER_TYPE }, + { 0 } +}; + +/* + * SearchRequest ::= + * [APPLICATION 3] SEQUENCE { + * baseObject LDAPDN, + * scope ENUMERATED { + * baseObject (0), + * singleLevel (1), + * wholeSubtree (2) + * }, + * derefAliases ENUMERATED { + * neverDerefAliases (0), + * derefInSearching (1), + * derefFindingBaseObj (2), + * alwaysDerefAliases (3) + * }, + * sizeLimit INTEGER (0 .. MAXINT), + * -- value of 0 implies no sizeLimit + * timeLimit INTEGER (0 .. MAXINT), + * -- value of 0 implies no timeLimit + * attrsOnly BOOLEAN, + * -- TRUE, if only attributes (without values) + * -- to be returned + * filter Filter, + * attributes SEQUENCE OF AttributeType + * } + */ + +static const SEC_ASN1Template LDAPAttributeTemplate[] = { + { SEC_ASN1_LDAP_STRING, 0, NULL, sizeof (SECItem) } +}; + +static const SEC_ASN1Template LDAPSearchApplTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearch, baseObject) }, + { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, scope) }, + { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, derefAliases) }, + { SEC_ASN1_INTEGER, offsetof(LDAPSearch, sizeLimit) }, + { SEC_ASN1_INTEGER, offsetof(LDAPSearch, timeLimit) }, + { SEC_ASN1_BOOLEAN, offsetof(LDAPSearch, attrsOnly) }, + { SEC_ASN1_INLINE, offsetof(LDAPSearch, filter), LDAPFilterTemplate }, + { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearch, attributes), LDAPAttributeTemplate }, + { 0 } +}; + +static const SEC_ASN1Template LDAPSearchTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCH_TYPE, 0, + LDAPSearchApplTemplate, sizeof (LDAPSearch) } +}; + +/* + * SearchResponse ::= + * CHOICE { + * entry [APPLICATION 4] SEQUENCE { + * objectName LDAPDN, + * attributes SEQUENCE OF SEQUENCE { + * AttributeType, + * SET OF AttributeValue + * } + * } + * resultCode [APPLICATION 5] LDAPResult + * } + */ + +static const SEC_ASN1Template LDAPSearchResponseAttrTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPSearchResponseAttr) }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseAttr, attrType) }, + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(LDAPSearchResponseAttr, val), + LDAPStringTemplate }, + { 0 } +}; + +static const SEC_ASN1Template LDAPEntryTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL }, + { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseEntry, objectName) }, + { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearchResponseEntry, attributes), + LDAPSearchResponseAttrTemplate }, + { 0 } +}; + +static const SEC_ASN1Template LDAPSearchResponseEntryTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSEENTRY_TYPE, 0, + LDAPEntryTemplate, sizeof (LDAPSearchResponseEntry) } +}; + +static const SEC_ASN1Template LDAPSearchResponseResultTemplate[] = { + { SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSERESULT_TYPE, 0, + LDAPResultTemplate, sizeof (LDAPSearchResponseResult) } +}; + +/* + * AbandonRequest ::= + * [APPLICATION 16] MessageID + */ + +static const SEC_ASN1Template LDAPAbandonTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(LDAPAbandonRequest, messageID) } +}; + +static const SEC_ASN1Template LDAPAbandonRequestTemplate[] = { + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_ABANDONREQUEST_TYPE, 0, + LDAPAbandonTemplate, sizeof (LDAPAbandonRequest) } +}; + +/* + * LDAPMessage ::= + * SEQUENCE { + * messageID MessageID, + * protocolOp CHOICE { + * bindRequest BindRequest, + * bindResponse BindResponse, + * unbindRequest UnbindRequest, + * searchRequest SearchRequest, + * searchResponse SearchResponse, + * abandonRequest AbandonRequest + * } + * } + * + * (other choices exist, not shown) + * + * MessageID ::= INTEGER (0 .. maxInt) + */ + +static const SEC_ASN1Template LDAPMessageProtocolOpTemplate[] = { + { SEC_ASN1_CHOICE, offsetof(LDAPProtocolOp, selector), 0, sizeof (LDAPProtocolOp) }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindMsg), + LDAPBindTemplate, LDAP_BIND_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindResponseMsg), + LDAPBindResponseTemplate, LDAP_BINDRESPONSE_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.unbindMsg), + LDAPUnbindTemplate, LDAP_UNBIND_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchMsg), + LDAPSearchTemplate, LDAP_SEARCH_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseEntryMsg), + LDAPSearchResponseEntryTemplate, LDAP_SEARCHRESPONSEENTRY_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseResultMsg), + LDAPSearchResponseResultTemplate, LDAP_SEARCHRESPONSERESULT_TYPE }, + { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.abandonRequestMsg), + LDAPAbandonRequestTemplate, LDAP_ABANDONREQUEST_TYPE }, + { 0 } +}; + +const SEC_ASN1Template PKIX_PL_LDAPMessageTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL }, + { SEC_ASN1_INTEGER, offsetof(LDAPMessage, messageID) }, + { SEC_ASN1_INLINE, offsetof(LDAPMessage, protocolOp), + LDAPMessageProtocolOpTemplate }, + { 0 } +}; + +/* This function simply returns the address of the message template. + * This is necessary for Windows DLLs. + */ +SEC_ASN1_CHOOSER_IMPLEMENT(PKIX_PL_LDAPMessageTemplate) diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c new file mode 100644 index 0000000000..966c6f37e4 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c @@ -0,0 +1,389 @@ +/* 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_pl_nsscontext.c + * + * NSSContext Function Definitions + * + */ + + +#include "pkix_pl_nsscontext.h" + +#define PKIX_DEFAULT_MAX_RESPONSE_LENGTH 64 * 1024 +#define PKIX_DEFAULT_COMM_TIMEOUT_SECONDS 60 + +#define PKIX_DEFAULT_CRL_RELOAD_DELAY_SECONDS 6 * 24 * 60 * 60 +#define PKIX_DEFAULT_BAD_CRL_RELOAD_DELAY_SECONDS 60 * 60 + +/* --Public-NSSContext-Functions--------------------------- */ + +/* + * FUNCTION: PKIX_PL_NssContext_Create + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_NssContext_Create( + PKIX_UInt32 certificateUsage, + PKIX_Boolean useNssArena, + void *wincx, + void **pNssContext) +{ + PKIX_PL_NssContext *context = NULL; + PLArenaPool *arena = NULL; + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_Create"); + PKIX_NULLCHECK_ONE(pNssContext); + + PKIX_CHECK(PKIX_PL_Malloc + (sizeof(PKIX_PL_NssContext), (void **)&context, NULL), + PKIX_MALLOCFAILED); + + if (useNssArena == PKIX_TRUE) { + PKIX_CONTEXT_DEBUG("\t\tCalling PORT_NewArena\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + } + + context->arena = arena; + context->certificateUsage = (SECCertificateUsage)certificateUsage; + context->wincx = wincx; + context->timeoutSeconds = PKIX_DEFAULT_COMM_TIMEOUT_SECONDS; + context->maxResponseLength = PKIX_DEFAULT_MAX_RESPONSE_LENGTH; + context->crlReloadDelay = PKIX_DEFAULT_CRL_RELOAD_DELAY_SECONDS; + context->badDerCrlReloadDelay = + PKIX_DEFAULT_BAD_CRL_RELOAD_DELAY_SECONDS; + context->certSignatureCheck = PKIX_TRUE; + context->chainVerifyCallback.isChainValid = NULL; + context->chainVerifyCallback.isChainValidArg = NULL; + *pNssContext = context; + +cleanup: + + PKIX_RETURN(CONTEXT); +} + + +/* + * FUNCTION: PKIX_PL_NssContext_Destroy + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_NssContext_Destroy( + void *nssContext) +{ + void *plContext = NULL; + PKIX_PL_NssContext *context = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_Destroy"); + PKIX_NULLCHECK_ONE(nssContext); + + context = (PKIX_PL_NssContext*)nssContext; + + if (context->arena != NULL) { + PKIX_CONTEXT_DEBUG("\t\tCalling PORT_FreeArena\n"); + PORT_FreeArena(context->arena, PKIX_FALSE); + } + + PKIX_PL_Free(nssContext, NULL); + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_GetCertUsage + * DESCRIPTION: + * + * This function obtains the platform-dependent SECCertificateUsage parameter + * from the context object pointed to by "nssContext", storing the result at + * "pCertUsage". + * + * PARAMETERS: + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * "pCertUsage" + * The address where the result is stored. Must be non-NULL. + * 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_pl_NssContext_GetCertUsage( + PKIX_PL_NssContext *nssContext, + SECCertificateUsage *pCertUsage) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetCertUsage"); + PKIX_NULLCHECK_TWO(nssContext, pCertUsage); + + *pCertUsage = nssContext->certificateUsage; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_SetCertUsage + * DESCRIPTION: + * + * This function sets the platform-dependent SECCertificateUsage parameter in + * the context object pointed to by "nssContext" to the value provided in + * "certUsage". + * + * PARAMETERS: + * "certUsage" + * Platform-dependent value to be stored. + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * 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_pl_NssContext_SetCertUsage( + SECCertificateUsage certUsage, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetCertUsage"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->certificateUsage = certUsage; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_GetCertSignatureCheck + * DESCRIPTION: + * + * This function obtains the platform-dependent flag to turn on or off + * signature checks. + * + * PARAMETERS: + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * "pCheckSig" + * The address where the result is stored. Must be non-NULL. + * 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_pl_NssContext_GetCertSignatureCheck( + PKIX_PL_NssContext *nssContext, + PKIX_Boolean *pCheckSig) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetCertUsage"); + PKIX_NULLCHECK_TWO(nssContext, pCheckSig); + + *pCheckSig = nssContext->certSignatureCheck; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_SetCertSignatureCheck + * DESCRIPTION: + * + * This function sets the check signature flag in + * the context object pointed to by "nssContext" to the value provided in + * "checkSig". + * + * PARAMETERS: + * "checkSig" + * Boolean that tells whether or not to check the signatues on certs. + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * 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_pl_NssContext_SetCertSignatureCheck( + PKIX_Boolean checkSig, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetCertUsage"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->certSignatureCheck = checkSig; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_GetWincx + * DESCRIPTION: + * + * This function obtains the platform-dependent wincx parameter from the + * context object pointed to by "nssContext", storing the result at "pWincx". + * + * PARAMETERS: + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * "pWincx" + * The address where the result is stored. Must be non-NULL. + * 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_pl_NssContext_GetWincx( + PKIX_PL_NssContext *nssContext, + void **pWincx) +{ + void *plContext = NULL; + PKIX_PL_NssContext *context = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetWincx"); + PKIX_NULLCHECK_TWO(nssContext, pWincx); + + context = (PKIX_PL_NssContext *)nssContext; + + *pWincx = context->wincx; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: pkix_pl_NssContext_SetWincx + * DESCRIPTION: + * + * This function sets the platform-dependent wincx parameter in the context + * object pointed to by "nssContext" to the value provided in "wincx". + * + * PARAMETERS: + * "wincx" + * Platform-dependent value to be stored. + * "nssContext" + * The address of the context object whose wincx parameter is to be + * obtained. Must be non-NULL. + * 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_pl_NssContext_SetWincx( + void *wincx, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetWincx"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->wincx = wincx; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: PKIX_PL_NssContext_SetTimeout + * DESCRIPTION: + * + * Sets user defined socket timeout for the validation + * session. Default is 60 seconds. + * + */ +PKIX_Error * +PKIX_PL_NssContext_SetTimeout(PKIX_UInt32 timeout, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetTimeout"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->timeoutSeconds = timeout; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: PKIX_PL_NssContext_SetMaxResponseLen + * DESCRIPTION: + * + * Sets user defined maximum transmission length of a message. + * + */ +PKIX_Error * +PKIX_PL_NssContext_SetMaxResponseLen(PKIX_UInt32 len, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetMaxResponseLen"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->maxResponseLength = len; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: PKIX_PL_NssContext_SetCrlReloadDelay + * DESCRIPTION: + * + * Sets user defined delay between attempts to load crl using + * CRLDP. + * + */ +PKIX_Error * +PKIX_PL_NssContext_SetCrlReloadDelay(PKIX_UInt32 delay, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetCrlReloadDelay"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->crlReloadDelay = delay; + + PKIX_RETURN(CONTEXT); +} + +/* + * FUNCTION: PKIX_PL_NssContext_SetBadDerCrlReloadDelay + * DESCRIPTION: + * + * Sets user defined delay between attempts to load crl that + * failed to decode. + * + */ +PKIX_Error * +PKIX_PL_NssContext_SetBadDerCrlReloadDelay(PKIX_UInt32 delay, + PKIX_PL_NssContext *nssContext) +{ + void *plContext = NULL; + + PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetBadDerCrlReloadDelay"); + PKIX_NULLCHECK_ONE(nssContext); + + nssContext->badDerCrlReloadDelay = delay; + + PKIX_RETURN(CONTEXT); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h new file mode 100644 index 0000000000..5de44214e5 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h @@ -0,0 +1,61 @@ +/* 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_pl_nsscontext.h + * + * NSSContext Object Type Definition + * + */ + + +#ifndef _PKIX_PL_NSSCONTEXT_H +#define _PKIX_PL_NSSCONTEXT_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_NssContextStruct { + SECCertificateUsage certificateUsage; + PLArenaPool *arena; + void *wincx; + PKIX_UInt32 timeoutSeconds; + PKIX_UInt32 maxResponseLength; + PRTime crlReloadDelay; + PRTime badDerCrlReloadDelay; + CERTChainVerifyCallback chainVerifyCallback; + PKIX_Boolean certSignatureCheck; +}; + +PKIX_Error * +pkix_pl_NssContext_GetCertUsage + (PKIX_PL_NssContext *nssContext, SECCertificateUsage *pCertUsage); + +/* XXX move the setter into the public header. */ +PKIX_Error * +pkix_pl_NssContext_SetCertUsage + (SECCertificateUsage certUsage, PKIX_PL_NssContext *nssContext); + +PKIX_Error * +pkix_pl_NssContext_GetCertSignatureCheck + (PKIX_PL_NssContext *nssContext, PKIX_Boolean *pCheckSig); + +PKIX_Error * +pkix_pl_NssContext_SetCertSignatureCheck + (PKIX_Boolean checkSig, PKIX_PL_NssContext *nssContext); + +PKIX_Error * +pkix_pl_NssContext_GetWincx(PKIX_PL_NssContext *nssContext, void **pWincx); + +/* XXX move the setter into the public header. */ +PKIX_Error * +pkix_pl_NssContext_SetWincx(void *wincx, PKIX_PL_NssContext *nssContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_NSSCONTEXT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c new file mode 100644 index 0000000000..7de614ea68 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c @@ -0,0 +1,1039 @@ +/* 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_pl_pk11certstore.c + * + * PKCS11CertStore Function Definitions + * + */ + +#include "pkix_pl_pk11certstore.h" + +/* + * PKIX_DEFAULT_MAX_RESPONSE_LENGTH (64 * 1024) is too small for downloading + * CRLs. We observed CRLs of sizes 338759 and 439035 in practice. So we + * need to use a higher max response length for CRLs. + */ +#define PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH (512 * 1024) + +/* --Private-Pk11CertStore-Functions---------------------------------- */ + +/* + * FUNCTION: pkix_pl_Pk11CertStore_CheckTrust + * DESCRIPTION: + * This function checks the trust status of this "cert" that was retrieved + * from the CertStore "store" and returns its trust status at "pTrusted". + * + * PARAMETERS: + * "store" + * Address of the CertStore. Must be non-NULL. + * "cert" + * Address of the Cert. Must be non-NULL. + * "pTrusted" + * Address of PKIX_Boolean where the "cert" trust status 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 CertStore 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_pl_Pk11CertStore_CheckTrust( + PKIX_CertStore *store, + PKIX_PL_Cert *cert, + PKIX_Boolean *pTrusted, + void *plContext) +{ + SECStatus rv = SECFailure; + PKIX_Boolean trusted = PKIX_FALSE; + SECCertUsage certUsage = 0; + SECCertificateUsage certificateUsage; + unsigned int requiredFlags; + SECTrustType trustType; + CERTCertTrust trust; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckTrust"); + PKIX_NULLCHECK_THREE(store, cert, pTrusted); + PKIX_NULLCHECK_ONE(cert->nssCert); + + certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; + + /* ensure we obtained a single usage bit only */ + PORT_Assert(!(certificateUsage & (certificateUsage - 1))); + + /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ + while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } + + rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, &trustType); + if (rv == SECSuccess) { + rv = CERT_GetCertTrust(cert->nssCert, &trust); + } + + if (rv == SECSuccess) { + unsigned int certFlags; + + if (certUsage != certUsageAnyCA && + certUsage != certUsageStatusResponder) { + CERTCertificate *nssCert = cert->nssCert; + + if (certUsage == certUsageVerifyCA) { + if (nssCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) { + trustType = trustEmail; + } else if (nssCert->nsCertType & NS_CERT_TYPE_SSL_CA) { + trustType = trustSSL; + } else { + trustType = trustObjectSigning; + } + } + + certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType); + if ((certFlags & requiredFlags) == requiredFlags) { + trusted = PKIX_TRUE; + } + } else { + for (trustType = trustSSL; trustType < trustTypeNone; + trustType++) { + certFlags = + SEC_GET_TRUST_FLAGS((&trust), trustType); + if ((certFlags & requiredFlags) == requiredFlags) { + trusted = PKIX_TRUE; + break; + } + } + } + } + + *pTrusted = trusted; + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_Pk11CertStore_CertQuery + * DESCRIPTION: + * + * This function obtains from the database the Certs specified by the + * ComCertSelParams pointed to by "params" and stores the resulting + * List at "pSelected". If no matching Certs are found, a NULL pointer + * will be stored. + * + * This function uses a "smart" database query if the Subject has been set + * in ComCertSelParams. Otherwise, it uses a very inefficient call to + * retrieve all Certs in the database (and run them through the selector). + * + * PARAMETERS: + * "params" + * Address of the ComCertSelParams. Must be non-NULL. + * "pSelected" + * Address at which 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 CertStore 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_pl_Pk11CertStore_CertQuery( + PKIX_ComCertSelParams *params, + PKIX_List **pSelected, + void *plContext) +{ + PRBool validOnly = PR_FALSE; + PRTime prtime = 0; + PKIX_PL_X500Name *subjectName = NULL; + PKIX_PL_Date *certValid = NULL; + PKIX_List *certList = NULL; + PKIX_PL_Cert *cert = NULL; + CERTCertList *pk11CertList = NULL; + CERTCertListNode *node = NULL; + CERTCertificate *nssCert = NULL; + CERTCertDBHandle *dbHandle = NULL; + + PLArenaPool *arena = NULL; + SECItem *nameItem = NULL; + void *wincx = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CertQuery"); + PKIX_NULLCHECK_TWO(params, pSelected); + + /* avoid multiple calls to retrieve a constant */ + PKIX_PL_NSSCALLRV(CERTSTORE, dbHandle, CERT_GetDefaultCertDB, ()); + + /* + * Any of the ComCertSelParams may be obtained and used to constrain + * the database query, to allow the use of a "smart" query. See + * pkix_certsel.h for a list of the PKIX_ComCertSelParams_Get* + * calls available. No corresponding "smart" queries exist at present, + * except for CERT_CreateSubjectCertList based on Subject. When others + * are added, corresponding code should be added to + * pkix_pl_Pk11CertStore_CertQuery to use them when appropriate + * selector parameters have been set. + */ + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (params, &subjectName, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid + (params, &certValid, plContext), + PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); + + /* If caller specified a Date, convert it to PRTime */ + if (certValid) { + PKIX_CHECK(pkix_pl_Date_GetPRTime + (certValid, &prtime, plContext), + PKIX_DATEGETPRTIMEFAILED); + validOnly = PR_TRUE; + } + + /* + * If we have the subject name for the desired subject, + * ask the database for Certs with that subject. Otherwise + * ask the database for all Certs. + */ + if (subjectName) { + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena) { + + PKIX_CHECK(pkix_pl_X500Name_GetDERName + (subjectName, arena, &nameItem, plContext), + PKIX_X500NAMEGETSECNAMEFAILED); + + if (nameItem) { + + PKIX_PL_NSSCALLRV + (CERTSTORE, + pk11CertList, + CERT_CreateSubjectCertList, + (NULL, dbHandle, nameItem, prtime, validOnly)); + } + PKIX_PL_NSSCALL + (CERTSTORE, PORT_FreeArena, (arena, PR_FALSE)); + arena = NULL; + } + + } else { + + PKIX_CHECK(pkix_pl_NssContext_GetWincx + ((PKIX_PL_NssContext *)plContext, &wincx), + PKIX_NSSCONTEXTGETWINCXFAILED); + + PKIX_PL_NSSCALLRV + (CERTSTORE, + pk11CertList, + PK11_ListCerts, + (PK11CertListAll, wincx)); + } + + if (pk11CertList) { + + PKIX_CHECK(PKIX_List_Create(&certList, plContext), + PKIX_LISTCREATEFAILED); + + for (node = CERT_LIST_HEAD(pk11CertList); + !(CERT_LIST_END(node, pk11CertList)); + node = CERT_LIST_NEXT(node)) { + + PKIX_PL_NSSCALLRV + (CERTSTORE, + nssCert, + CERT_DupCertificate, + (node->cert)); + + if (!nssCert) { + continue; /* just skip bad certs */ + } + + PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert + (nssCert, &cert, plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); + + if (PKIX_ERROR_RECEIVED) { + CERT_DestroyCertificate(nssCert); + nssCert = NULL; + continue; /* just skip bad certs */ + } + + PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem + (certList, (PKIX_PL_Object *)cert, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(cert); + + } + + /* Don't throw away the list if one cert was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + } + + *pSelected = certList; + certList = NULL; + +cleanup: + + if (pk11CertList) { + CERT_DestroyCertList(pk11CertList); + } + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + + PKIX_DECREF(subjectName); + PKIX_DECREF(certValid); + PKIX_DECREF(cert); + PKIX_DECREF(certList); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_Pk11CertStore_ImportCrl + * DESCRIPTION: + * + * PARAMETERS: + * "params" + * Address of the ComCRLSelParams. Must be non-NULL. + * "pSelected" + * Address at which 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 CertStore 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_pl_Pk11CertStore_ImportCrl( + PKIX_CertStore *store, + PKIX_PL_X500Name *issuerName, + PKIX_List *crlList, + void *plContext) +{ + CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); + PKIX_PL_CRL *crl = NULL; + SECItem *derCrl = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ImportCrl"); + PKIX_NULLCHECK_TWO(store, plContext); + + if (!crlList) { + goto cleanup; + } + while (crlList->length > 0) { + PKIX_CHECK( + PKIX_List_GetItem(crlList, 0, (PKIX_PL_Object**)&crl, + plContext), + PKIX_LISTGETITEMFAILED); + + /* Delete crl from the list to keep controll of the + * last reference. crl need to be destroyed right after + * it released the ownership of the crl der. */ + PKIX_CHECK( + PKIX_List_DeleteItem(crlList, 0, plContext), + PKIX_LISTDELETEITEMFAILED); + + /* acquire the crlder ownership */ + pkixErrorResult = + PKIX_PL_CRL_ReleaseDerCrl(crl, &derCrl, plContext); + PORT_Assert(!pkixErrorResult && derCrl); + if (pkixErrorResult || !derCrl) { + /* All pkix delivered crls should be able to + * release their ders. */ + PKIX_DECREF(pkixErrorResult); + PKIX_DECREF(crl); + continue; + } + cert_CacheCRLByGeneralName(certHandle, derCrl, + crl->derGenName); + /* Do not check the status. If it is a SECFailure, + * derCrl is already destroyed. */ + derCrl = NULL; + PKIX_DECREF(crl); + } + +cleanup: + PKIX_DECREF(crl); + + PKIX_RETURN(CERTSTORE); +} + +static PKIX_Error * +NameCacheHasFetchedCrlInfo(PKIX_PL_Cert *pkixCert, + PRTime time, + PKIX_Boolean *pHasFetchedCrlInCache, + void *plContext) +{ + /* Returning true result in this case will mean, that case info + * is currect and should used as is. */ + NamedCRLCache* nameCrlCache = NULL; + PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE; + PKIX_List *dpList = NULL; + pkix_pl_CrlDp *dp = NULL; + PKIX_UInt32 dpIndex = 0; + SECStatus rv = SECSuccess; + PRTime reloadDelay = 0, badCrlInvalDelay = 0; + + PKIX_ENTER(CERTSTORE, "ChechCacheHasFetchedCrl"); + + reloadDelay = + ((PKIX_PL_NssContext*)plContext)->crlReloadDelay * + PR_USEC_PER_SEC; + badCrlInvalDelay = + ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay * + PR_USEC_PER_SEC; + if (!time) { + time = PR_Now(); + } + /* If we already download the crl and inserted into the cache, then + * there is no need to check for fetched crl. We have what we have. */ + PKIX_CHECK( + PKIX_PL_Cert_GetCrlDp(pkixCert, &dpList, plContext), + PKIX_CERTGETCRLDPFAILED); + if (dpList && dpList->length) { + hasFetchedCrlInCache = PKIX_FALSE; + rv = cert_AcquireNamedCRLCache(&nameCrlCache); + if (rv != SECSuccess) { + PKIX_DECREF(dpList); + } + } else { + /* If no dp then treat it as if we already have + * a fetched crl. */ + PKIX_DECREF(dpList); + } + for (;!hasFetchedCrlInCache && + dpList && dpIndex < dpList->length;dpIndex++) { + SECItem **derDpNames = NULL; + pkixErrorResult = + PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp, + plContext); + if (pkixErrorResult) { + PKIX_DECREF(pkixErrorResult); + continue; + } + if (dp->nssdp->distPointType == generalName) { + /* dp can only be created from nssdp. */ + derDpNames = dp->nssdp->derFullName; + } + while (derDpNames && *derDpNames != NULL) { + NamedCRLCacheEntry* cacheEntry = NULL; + const SECItem *derDpName = *derDpNames++; + rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName, + &cacheEntry); + if (rv == SECSuccess && cacheEntry) { + if ((cacheEntry->inCRLCache && + (cacheEntry->successfulInsertionTime + reloadDelay > time || + (cacheEntry->dupe && + cacheEntry->lastAttemptTime + reloadDelay > time))) || + (cacheEntry->badDER && + cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) { + hasFetchedCrlInCache = PKIX_TRUE; + break; + } + } + } + PKIX_DECREF(dp); + } +cleanup: + *pHasFetchedCrlInCache = hasFetchedCrlInCache; + if (nameCrlCache) { + cert_ReleaseNamedCRLCache(nameCrlCache); + } + PKIX_DECREF(dpList); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_Pk11CertStore_CheckCrl + * DESCRIPTION: + * + * PARAMETERS: + * "params" + * Address of the ComCRLSelParams. Must be non-NULL. + * "pSelected" + * Address at which 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 CertStore 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_pl_Pk11CertStore_CheckRevByCrl( + PKIX_CertStore *store, + PKIX_PL_Cert *pkixCert, + PKIX_PL_Cert *pkixIssuer, + PKIX_PL_Date *date, + PKIX_Boolean crlDownloadDone, + CERTCRLEntryReasonCode *pReasonCode, + PKIX_RevocationStatus *pStatus, + void *plContext) +{ + PKIX_RevocationStatus pkixRevStatus = PKIX_RevStatus_NoInfo; + CERTRevocationStatus revStatus = certRevocationStatusUnknown; + PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE; + CERTCertificate *cert = NULL, *issuer = NULL; + SECStatus rv = SECSuccess; + void *wincx = NULL; + PRTime time = 0; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckRevByCrl"); + PKIX_NULLCHECK_FOUR(store, pkixCert, pkixIssuer, plContext); + + cert = pkixCert->nssCert; + issuer = pkixIssuer->nssCert; + if (date) { + PKIX_CHECK( + pkix_pl_Date_GetPRTime(date, &time, plContext), + PKIX_DATEGETPRTIMEFAILED); + } + PKIX_CHECK( + pkix_pl_NssContext_GetWincx((PKIX_PL_NssContext*)plContext, + &wincx), + PKIX_NSSCONTEXTGETWINCXFAILED); + /* No need to check any cDPs, since partitioned crls are not + * supported. If a ds does not point to partitioned crl, then + * the crl should be in issuer cache that is unrelated to any + * dp. Using NULL as a dp pointer to check it.*/ + rv = cert_CheckCertRevocationStatus(cert, issuer, NULL, + /* Will not validate the signature + * on the crl if time is not specified.*/ + time, wincx, &revStatus, pReasonCode); + if (rv == SECFailure) { + pkixRevStatus = PKIX_RevStatus_Revoked; + goto cleanup; + } + if (crlDownloadDone) { + if (revStatus == certRevocationStatusRevoked) { + pkixRevStatus = PKIX_RevStatus_Revoked; + } else if (revStatus == certRevocationStatusValid) { + pkixRevStatus = PKIX_RevStatus_Success; + } + } else { + pkixErrorResult = + NameCacheHasFetchedCrlInfo(pkixCert, time, &hasFetchedCrlInCache, + plContext); + if (pkixErrorResult) { + goto cleanup; + } + if (revStatus == certRevocationStatusRevoked && + (hasFetchedCrlInCache || + *pReasonCode != crlEntryReasoncertificatedHold)) { + pkixRevStatus = PKIX_RevStatus_Revoked; + } else if (revStatus == certRevocationStatusValid && + hasFetchedCrlInCache) { + pkixRevStatus = PKIX_RevStatus_Success; + } + } +cleanup: + *pStatus = pkixRevStatus; + + PKIX_RETURN(CERTSTORE); +} + + +/* + * FUNCTION: pkix_pl_Pk11CertStore_GetCert + * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) + */ +PKIX_Error * +pkix_pl_Pk11CertStore_GetCert( + PKIX_CertStore *store, + PKIX_CertSelector *selector, + PKIX_VerifyNode *parentVerifyNode, + void **pNBIOContext, + PKIX_List **pCertList, + void *plContext) +{ + PKIX_UInt32 i = 0; + PKIX_UInt32 numFound = 0; + PKIX_PL_Cert *candidate = NULL; + PKIX_List *selected = NULL; + PKIX_List *filtered = NULL; + PKIX_CertSelector_MatchCallback selectorCallback = NULL; + PKIX_CertStore_CheckTrustCallback trustCallback = NULL; + PKIX_ComCertSelParams *params = NULL; + PKIX_Boolean cacheFlag = PKIX_FALSE; + PKIX_VerifyNode *verifyNode = NULL; + PKIX_Error *selectorError = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCert"); + PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList); + + *pNBIOContext = NULL; /* We don't use non-blocking I/O */ + + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (selector, &selectorCallback, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams + (selector, ¶ms, plContext), + PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED); + + PKIX_CHECK(pkix_pl_Pk11CertStore_CertQuery + (params, &selected, plContext), + PKIX_PK11CERTSTORECERTQUERYFAILED); + + if (selected) { + PKIX_CHECK(PKIX_List_GetLength(selected, &numFound, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag + (store, &cacheFlag, plContext), + PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); + + PKIX_CHECK(PKIX_CertStore_GetTrustCallback + (store, &trustCallback, plContext), + PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); + + PKIX_CHECK(PKIX_List_Create(&filtered, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; i < numFound; i++) { + PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem + (selected, + i, + (PKIX_PL_Object **)&candidate, + plContext), + PKIX_LISTGETITEMFAILED); + + if (PKIX_ERROR_RECEIVED) { + continue; /* just skip bad certs */ + } + + selectorError = + selectorCallback(selector, candidate, plContext); + if (!selectorError) { + PKIX_CHECK(PKIX_PL_Cert_SetCacheFlag + (candidate, cacheFlag, plContext), + PKIX_CERTSETCACHEFLAGFAILED); + + if (trustCallback) { + PKIX_CHECK(PKIX_PL_Cert_SetTrustCertStore + (candidate, store, plContext), + PKIX_CERTSETTRUSTCERTSTOREFAILED); + } + + PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem + (filtered, + (PKIX_PL_Object *)candidate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } else if (parentVerifyNode) { + PKIX_CHECK_FATAL( + pkix_VerifyNode_Create(candidate, 0, selectorError, + &verifyNode, plContext), + PKIX_VERIFYNODECREATEFAILED); + PKIX_CHECK_FATAL( + pkix_VerifyNode_AddToTree(parentVerifyNode, + verifyNode, + plContext), + PKIX_VERIFYNODEADDTOTREEFAILED); + PKIX_DECREF(verifyNode); + } + PKIX_DECREF(selectorError); + PKIX_DECREF(candidate); + } + + /* Don't throw away the list if one cert was bad! */ + pkixTempErrorReceived = PKIX_FALSE; + + *pCertList = filtered; + filtered = NULL; + +cleanup: +fatal: + PKIX_DECREF(filtered); + PKIX_DECREF(candidate); + PKIX_DECREF(selected); + PKIX_DECREF(params); + PKIX_DECREF(verifyNode); + PKIX_DECREF(selectorError); + + PKIX_RETURN(CERTSTORE); +} + +static PKIX_Error * +RemovePartitionedDpsFromList(PKIX_List *dpList, PKIX_PL_Date *date, + void *plContext) +{ + NamedCRLCache* nameCrlCache = NULL; + pkix_pl_CrlDp *dp = NULL; + unsigned int dpIndex = 0; + PRTime time; + PRTime reloadDelay = 0, badCrlInvalDelay = 0; + SECStatus rv; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ListRemovePrtDp"); + + if (!dpList || !dpList->length) { + PKIX_RETURN(CERTSTORE); + } + reloadDelay = + ((PKIX_PL_NssContext*)plContext)->crlReloadDelay * + PR_USEC_PER_SEC; + badCrlInvalDelay = + ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay * + PR_USEC_PER_SEC; + PKIX_CHECK(pkix_pl_Date_GetPRTime(date, &time, plContext), + PKIX_DATEGETPRTIMEFAILED); + rv = cert_AcquireNamedCRLCache(&nameCrlCache); + if (rv == SECFailure) { + /* Baling out. Wont find out any thing useful. */ + PKIX_RETURN(CERTSTORE); + } + while (dpIndex < dpList->length) { + SECItem **derDpNames = NULL; + PKIX_Boolean removeDp = PKIX_FALSE; + + PKIX_CHECK( + PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp, + plContext), + PKIX_LISTGETITEMFAILED); + if (!dp->isPartitionedByReasonCode) { + /* See if we know about this dp anything why we should + * not use it to download a crl. */ + if (dp->nssdp->distPointType == generalName) { + /* dp can only be created from nssdp. */ + derDpNames = dp->nssdp->derFullName; + } else { + removeDp = PKIX_TRUE; + } + while (derDpNames && *derDpNames != NULL) { + NamedCRLCacheEntry* cacheEntry = NULL; + const SECItem *derDpName = *derDpNames++; + /* Removing from the list all dps that we know about. */ + rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName, + &cacheEntry); + if (rv && cacheEntry) { + if (cacheEntry->unsupported || + (cacheEntry->inCRLCache && + (cacheEntry->successfulInsertionTime + reloadDelay > time || + (cacheEntry->dupe && + cacheEntry->lastAttemptTime + reloadDelay > time))) || + (cacheEntry->badDER && + cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) { + removeDp = PKIX_TRUE; + } + } + } + } else { + /* Remove dp that point to a partitioned crl . RFC 5280 + * recommends against crl partitioned by reason code. + * Will skip such crls */ + removeDp = PKIX_TRUE; + } + if (removeDp) { + PKIX_CHECK_ONLY_FATAL( + pkix_List_Remove(dpList,(PKIX_PL_Object*)dp, + plContext), + PKIX_LISTGETITEMFAILED); + } else { + dpIndex += 1; + } + PKIX_DECREF(dp); + } + +cleanup: + if (nameCrlCache) { + cert_ReleaseNamedCRLCache(nameCrlCache); + } + PKIX_DECREF(dp); + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_Pk11CertStore_DownloadCrl + */ +static PKIX_Error * +DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl, + const SEC_HttpClientFcnV1 *hcv1, void *plContext) +{ + char *location = NULL; + char *hostname = NULL; + char *path = NULL; + PRUint16 port; + SEC_HTTP_SERVER_SESSION pServerSession = NULL; + SEC_HTTP_REQUEST_SESSION pRequestSession = NULL; + PRUint16 myHttpResponseCode; + const char *myHttpResponseData = NULL; + PRUint32 myHttpResponseDataLen; + SECItem *uri = NULL; + SECItem *derCrlCopy = NULL; + CERTSignedCrl *nssCrl = NULL; + CERTGeneralName *genName = NULL; + SECItem **derGenNames = NULL; + SECItem *derGenName = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_DownloadCrl"); + + /* Do not support dps others than a one with GeneralName + * name type. */ + if (dp->distPointType != generalName || + !dp->nssdp->derFullName) { + PKIX_ERROR(PKIX_UNSUPPORTEDCRLDPTYPE); + } + genName = dp->name.fullName; + derGenNames = dp->nssdp->derFullName; + do { + derGenName = *derGenNames; + do { + if (!derGenName || + !genName->name.other.data) { + /* get to next name if no data. */ + break; + } + uri = &genName->name.other; + location = (char*)PR_Malloc(1 + uri->len); + if (!location) { + break; + } + PORT_Memcpy(location, uri->data, uri->len); + location[uri->len] = 0; + if (CERT_ParseURL(location, &hostname, + &port, &path) != SECSuccess) { + PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL); + break; + } + + PORT_Assert(hostname != NULL); + PORT_Assert(path != NULL); + + if ((*hcv1->createSessionFcn)(hostname, port, + &pServerSession) != SECSuccess) { + PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL); + break; + } + + if ((*hcv1->createFcn)(pServerSession, "http", path, "GET", + /* Users with slow connections might not get CRL revocation + checking for certs that use big CRLs because of the timeout + We absolutely need code that limits our retry attempts. + */ + PR_SecondsToInterval( + ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), + &pRequestSession) != SECSuccess) { + break; + } + + myHttpResponseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + if (myHttpResponseDataLen < PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH) + myHttpResponseDataLen = PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH; + + /* We use a non-zero timeout, which means: + - the client will use blocking I/O + - TryFcn will not return WOULD_BLOCK nor a poll descriptor + - it's sufficient to call TryFcn once + */ + /* we don't want result objects larger than this: */ + if ((*hcv1->trySendAndReceiveFcn)( + pRequestSession, + NULL, + &myHttpResponseCode, + NULL, + NULL, + &myHttpResponseData, + &myHttpResponseDataLen) != SECSuccess) { + break; + } + + if (myHttpResponseCode != 200) { + break; + } + } while(0); + if (!myHttpResponseData) { + /* Going to the next one. */ + genName = CERT_GetNextGeneralName(genName); + derGenNames++; + } + /* Staing in the loop through all the names until + * we have a successful download. */ + } while (!myHttpResponseData && *derGenNames && + genName != dp->name.fullName); + /* Need this name to track the crl source location. */ + PORT_Assert(derGenName); + + if (!myHttpResponseData) { + /* Generating fake bad CRL to keep track of this dp */ + SECItem derCrl = {siBuffer, (void*)"BadCrl", 6 }; + + derCrlCopy = SECITEM_DupItem(&derCrl); + if (!derCrlCopy) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + derGenName = *dp->nssdp->derFullName; + } else { + SECItem derCrl = { siBuffer, + (void*)myHttpResponseData, + myHttpResponseDataLen }; + derCrlCopy = SECITEM_DupItem(&derCrl); + if (!derCrlCopy) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + /* crl will be based on derCrlCopy, but will not own the der. */ + nssCrl = + CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE, + CRL_DECODE_DONT_COPY_DER | + CRL_DECODE_SKIP_ENTRIES); + } + /* pkix crl owns the der. */ + PKIX_CHECK( + pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, + derGenName, + crl, plContext), + PKIX_CRLCREATEWITHSIGNEDCRLFAILED); + /* pkix crl now own both objects. */ + derCrlCopy = NULL; + nssCrl = NULL; + +cleanup: + if (derCrlCopy) + PORT_Free(derCrlCopy); + if (nssCrl) + SEC_DestroyCrl(nssCrl); + if (pRequestSession != NULL) + (*hcv1->freeFcn)(pRequestSession); + if (pServerSession != NULL) + (*hcv1->freeSessionFcn)(pServerSession); + if (path != NULL) + PORT_Free(path); + if (hostname != NULL) + PORT_Free(hostname); + if (location) { + PORT_Free(location); + } + + PKIX_RETURN(CERTSTORE); +} + +/* + * FUNCTION: pkix_pl_Pk11CertStore_GetCRL + * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) + */ +static PKIX_Error * +pkix_pl_Pk11CertStore_GetCRL( + PKIX_CertStore *store, + PKIX_CRLSelector *selector, + void **pNBIOContext, + PKIX_List **pCrlList, + void *plContext) +{ + PKIX_UInt32 dpIndex = 0; + PKIX_PL_CRL *crl = NULL; + PKIX_List *crlList = NULL; + PKIX_List *dpList = NULL; + pkix_pl_CrlDp *dp = NULL; + PKIX_PL_Date *date = NULL; + const SEC_HttpClientFcn *registeredHttpClient = NULL; + + PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCRL"); + PKIX_NULLCHECK_THREE(store, pNBIOContext, pCrlList); + PKIX_NULLCHECK_TWO(selector, selector->params); + + registeredHttpClient = SEC_GetRegisteredHttpClient(); + if (!registeredHttpClient || registeredHttpClient->version != 1) { + goto cleanup; + } + dpList = selector->params->crldpList; + date = selector->params->date; + PKIX_CHECK( + RemovePartitionedDpsFromList(dpList, date, + plContext), + PKIX_FAILTOREMOVEDPFROMLIST); + for (;dpIndex < dpList->length;dpIndex++) { + PKIX_DECREF(dp); + pkixErrorResult = + PKIX_List_GetItem(dpList, dpIndex, + (PKIX_PL_Object **)&dp, + plContext); + if (pkixErrorResult) { + PKIX_DECREF(pkixErrorResult); + continue; + } + pkixErrorResult = + DownloadCrl(dp, &crl, + ®isteredHttpClient->fcnTable.ftable1, + plContext); + if (pkixErrorResult || !crl) { + /* continue to next dp in case of unsuccesfull + * download attempt. */ + PKIX_DECREF(pkixErrorResult); + continue; + } + if (!crlList) { + PKIX_CHECK(PKIX_List_Create(&crlList, plContext), + PKIX_LISTCREATEFAILED); + } + pkixErrorResult = + PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl, + plContext); + if (pkixErrorResult) { + PKIX_DECREF(pkixErrorResult); + } + PKIX_DECREF(crl); + } + *pCrlList = crlList; + crlList = NULL; + +cleanup: + PKIX_DECREF(dp); + PKIX_DECREF(crl); + PKIX_DECREF(crlList); + + PKIX_RETURN(CERTSTORE); +} + + +/* --Public-Pk11CertStore-Functions----------------------------------- */ + +/* + * FUNCTION: PKIX_PL_Pk11CertStore_Create + * (see comments in pkix_samples_modules.h) + */ +PKIX_Error * +PKIX_PL_Pk11CertStore_Create( + PKIX_CertStore **pCertStore, + void *plContext) +{ + PKIX_CertStore *certStore = NULL; + + PKIX_ENTER(CERTSTORE, "PKIX_PL_Pk11CertStore_Create"); + PKIX_NULLCHECK_ONE(pCertStore); + + PKIX_CHECK(PKIX_CertStore_Create + (pkix_pl_Pk11CertStore_GetCert, + pkix_pl_Pk11CertStore_GetCRL, + NULL, /* getCertContinue */ + NULL, /* getCrlContinue */ + pkix_pl_Pk11CertStore_CheckTrust, + pkix_pl_Pk11CertStore_ImportCrl, + pkix_pl_Pk11CertStore_CheckRevByCrl, + NULL, + PKIX_TRUE, /* cache flag */ + PKIX_TRUE, /* local - no network I/O */ + &certStore, + plContext), + PKIX_CERTSTORECREATEFAILED); + + *pCertStore = certStore; + +cleanup: + + PKIX_RETURN(CERTSTORE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h new file mode 100644 index 0000000000..506707683d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h @@ -0,0 +1,31 @@ +/* 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_pl_pk11certstore.h + * + * PK11Certstore Object Type Definition + * + */ + +#ifndef _PKIX_PL_PK11CERTSTORE_H +#define _PKIX_PL_PK11CERTSTORE_H + +#include "pkix_pl_common.h" +#include "certi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* see source file for function documentation */ +PKIX_Error * +PKIX_PL_Pk11CertStore_Create( + PKIX_CertStore **pCertStore, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_PK11CERTSTORE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c new file mode 100644 index 0000000000..e8698376b5 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c @@ -0,0 +1,1695 @@ +/* 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_pl_socket.c + * + * Socket Function Definitions + * + */ + +/* + * If Socket Tracing is active, messages sent and received will be + * timestamped and dumped (to stdout) in standard hex-dump format. E.g., + * + * 1116612359156140: + * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!. + * + * The timestamp is not formatted to be meaningful except as an increasing + * value of seconds.microseconds, which is good enough to correlate two + * sides of a message exchange and to figure durations. + * + * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE + * is defined, but that doesn't mean socket tracing is active. Tracing also + * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is + * the default value, but it can be overridden by using the debugger to + * change its value -- allowing tracing to be turned on and off at various + * breakpoints -- or by setting the environment variable SOCKETTRACE. A + * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other + * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment + * value is checked during system initialization. + */ +#ifndef BUILD_OPT +#define PKIX_SOCKETTRACE 1 +#endif + +#ifdef PKIX_SOCKETDEBUG +#define PKIX_SOCKETTRACE 1 +#endif + +#include "pkix_pl_socket.h" + +/* --Private-Socket-Functions---------------------------------- */ + +#ifdef PKIX_SOCKETTRACE +static PKIX_Boolean socketTraceFlag = PKIX_FALSE; + +/* + * FUNCTION: pkix_pl_socket_timestamp + * DESCRIPTION: + * + * This functions prints to stdout the time of day, as obtained from the + * system function gettimeofday, as seconds.microseconds. Its resolution + * is whatever the system call provides. + * + * PARAMETERS: + * none + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static void pkix_pl_socket_timestamp() { + PRInt64 prTime; + prTime = PR_Now(); +/* We shouldn't use PR_ALTERNATE_INT64_TYPEDEF, but nor can we use PRId64 */ +#if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF) + printf("%ld:\n", prTime); +#else + printf("%lld:\n", prTime); +#endif +} + +/* + * FUNCTION: pkix_pl_socket_hexDigit + * DESCRIPTION: + * + * This functions prints to stdout the byte "byteVal" as two hex digits. + * + * PARAMETERS: + * "byteVal" + * The value to be printed. + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static void pkix_pl_socket_hexDigit(char byteVal) { + int n = 0; + char cHi = '\0'; + char cLow = '\0'; + n = ((byteVal >> 4) & 0xf); + if (n > 9) { + cHi = (char) ((n - 10) + 'A'); + } else { + cHi = (char) (n + '0'); + } + n = byteVal & 0xf; + if (n > 9) { + cLow = (char) ((n - 10) + 'A'); + } else { + cLow = (char) (n + '0'); + } + (void) printf("%c%c", cHi, cLow); +} + +/* + * FUNCTION: pkix_pl_socket_linePrefix + * DESCRIPTION: + * + * This functions prints to stdout the address provided by "addr" as four + * hexadecimal digits followed by a colon and a space. + * + * PARAMETERS: + * "addr" + * The address to be printed + * none + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr) { + pkix_pl_socket_hexDigit((char)((addr >> 8) & 0xff)); + pkix_pl_socket_hexDigit((char)(addr & 0xff)); + (void) printf(": "); +} + +/* + * FUNCTION: pkix_pl_socket_traceLine + * DESCRIPTION: + * + * This functions prints to stdout the sixteen bytes beginning at the + * address pointed to by "ptr". The bytes are printed as sixteen pairs + * of hexadecimal characters followed by an ascii interpretation, in which + * characters from 0x20 to 0x7d are shown as their ascii equivalents, and + * other values are represented as periods. + * + * PARAMETERS: + * "ptr" + * The address of the first of the bytes to be printed + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static void pkix_pl_socket_traceLine(char *ptr) { + PKIX_UInt32 i = 0; + pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL)); + for (i = 0; i < 16; i++) { + printf(" "); + pkix_pl_socket_hexDigit(ptr[i]); + if (i == 7) { + printf(" "); + } + } + printf(" "); + for (i = 0; i < 16; i++) { + if ((ptr[i] < ' ') || (ptr[i] > '}')) { + printf("."); + } else { + printf("%c", ptr[i]); + } + } + printf("\n"); +} + +/* + * FUNCTION: pkix_pl_socket_tracePartialLine + * DESCRIPTION: + * + * This functions prints to stdout the number of bytes given by "nBytes", + * beginning at the address pointed to by "ptr". The bytes are printed as + * pairs of hexadecimal characters followed by an ascii interpretation, in + * which characters from 0x20 to 0x7d are shown as their ascii equivalents, + * and other values are represented as periods. + * + * PARAMETERS: + * "ptr" + * The address of the first of the bytes to be printed + * "nBytes" + * The Int32 value giving the number of bytes to be printed. If "nBytes" + * is greater than sixteen, the results will be unattractive. + * none + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static void pkix_pl_socket_tracePartialLine(char *ptr, PKIX_UInt32 nBytes) { + PKIX_UInt32 i = 0; + if (nBytes > 0) { + pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL)); + } + for (i = 0; i < nBytes; i++) { + printf(" "); + pkix_pl_socket_hexDigit(ptr[i]); + if (i == 7) { + printf(" "); + } + } + for (i = nBytes; i < 16; i++) { + printf(" "); + if (i == 7) { + printf(" "); + } + } + printf(" "); + for (i = 0; i < nBytes; i++) { + if ((ptr[i] < ' ') || (ptr[i] > '}')) { + printf("."); + } else { + printf("%c", ptr[i]); + } + } + printf("\n"); +} + +/* + * FUNCTION: pkix_pl_socket_tracebuff + * DESCRIPTION: + * + * This functions prints to stdout the number of bytes given by "nBytes", + * beginning with the byte pointed to by "buf". The output is preceded by + * a timestamp, and each group of sixteen (and a remainder, if any) is + * preceded by its address. The contents are shown in hexadecimal and as + * ascii characters. If "nBytes" is zero, the timestamp and starting + * address are displayed. + * + * PARAMETERS: + * "buf" + * The starting address of the bytes to be printed + * "nBytes" + * The number of bytes to be printed + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +void pkix_pl_socket_tracebuff(void *buf, PKIX_UInt32 nBytes) { + PKIX_UInt32 bytesRemaining = nBytes; + PKIX_UInt32 offset = 0; + char *bufptr = (char *)buf; + + if (socketTraceFlag == PKIX_FALSE) return; + + pkix_pl_socket_timestamp(); + /* + * Special case: if called with length of zero, just do address + */ + if (nBytes == 0) { + pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)buf - (char *)NULL)); + printf("\n"); + } else { + while (bytesRemaining >= 16) { + pkix_pl_socket_traceLine(&bufptr[offset]); + bytesRemaining -= 16; + offset += 16; + } + pkix_pl_socket_tracePartialLine + (&bufptr[offset], bytesRemaining); + } +} + +#endif + +/* + * FUNCTION: pkix_pl_Socket_SetNonBlocking + * DESCRIPTION: + * + * This functions sets the socket represented by the PRFileDesc "fileDesc" + * to nonblocking mode. + * + * PARAMETERS: + * "fileDesc" + * The address of the PRFileDesc whose I/O mode is to be set + * non-blocking. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_SetNonBlocking( + PRFileDesc *fileDesc, + void *plContext) +{ + PRStatus rv = PR_FAILURE; + PRSocketOptionData sockOptionData; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_SetNonBlocking"); + PKIX_NULLCHECK_ONE(fileDesc); + + sockOptionData.option = PR_SockOpt_Nonblocking; + sockOptionData.value.non_blocking = PR_TRUE; + + PKIX_PL_NSSCALLRV(SOCKET, rv, fileDesc->methods->setsocketoption, + (fileDesc, &sockOptionData)); + + if (rv != PR_SUCCESS) { + PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); + } +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_CreateClient + * DESCRIPTION: + * + * This functions creates a client socket for the PKIX_PL_Socket pointed to + * by "socket". If "socket" was created with a timeout value of zero, the + * client socket is set to use nonblocking I/O. + * + * PARAMETERS: + * "socket" + * The address of the Socket for which a client socket is to be + * created. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ + +static PKIX_Error * +pkix_pl_Socket_CreateClient( + PKIX_PL_Socket *socket, + void *plContext) +{ +#ifdef PKIX_SOCKETDEBUG + PRErrorCode errorcode = 0; +#endif + PRFileDesc *mySock = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateClient"); + PKIX_NULLCHECK_ONE(socket); + + PKIX_PL_NSSCALLRV(SOCKET, mySock, PR_NewTCPSocket, ()); + if (!mySock) { +#ifdef PKIX_SOCKETDEBUG + errorcode = PR_GetError(); + printf + ("pkix_pl_Socket_CreateClient: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); + } + +#ifdef PKIX_SOCKETDEBUG + printf("Created socket, PRFileDesc @ %#X\n", mySock); +#endif + + socket->clientSock = mySock; + socket->status = SOCKET_UNCONNECTED; + if (socket->timeout == 0) { + PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock, plContext), + PKIX_SOCKETSETNONBLOCKINGFAILED); + } + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_CreateServer + * DESCRIPTION: + * + * This functions creates a server socket for the PKIX_PL_Socket pointed to + * by "socket". If "socket" was created with a timeout value of zero, the + * server socket is set to use nonblocking I/O. + * + * Warning: there seems to be a problem with operating a server socket in + * non-blocking mode. If the server calls Recv prior to a corresponding + * Send, the message may be lost. + * + * PARAMETERS: + * "socket" + * The address of the Socket for which a server socket is to be + * created. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_CreateServer( + PKIX_PL_Socket *socket, + void *plContext) +{ +/* #ifdef PKIX_SOCKETDEBUG */ + PRErrorCode errorcode = 0; +/* #endif */ + PRStatus rv = PR_FAILURE; + PRFileDesc *serverSock = NULL; + PRSocketOptionData sockOptionData; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateServer"); + PKIX_NULLCHECK_ONE(socket); + + PKIX_PL_NSSCALLRV(SOCKET, serverSock, PR_NewTCPSocket, ()); + if (!serverSock) { +#ifdef PKIX_SOCKETDEBUG + errorcode = PR_GetError(); + printf + ("pkix_pl_Socket_CreateServer: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); + } + + socket->serverSock = serverSock; + +#ifdef PKIX_SOCKETDEBUG + printf("Created socket, PRFileDesc @ %#X\n", serverSock); +#endif + + if (socket->timeout == 0) { + PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock, plContext), + PKIX_SOCKETSETNONBLOCKINGFAILED); + } + + sockOptionData.option = PR_SockOpt_Reuseaddr; + sockOptionData.value.reuse_addr = PR_TRUE; + + PKIX_PL_NSSCALLRV(SOCKET, rv, serverSock->methods->setsocketoption, + (serverSock, &sockOptionData)); + + if (rv != PR_SUCCESS) { + PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); + } + + PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Bind, (serverSock, socket->netAddr)); + + if (rv == PR_FAILURE) { +/* #ifdef PKIX_SOCKETDEBUG */ + errorcode = PR_GetError(); + printf + ("pkix_pl_Socket_CreateServer: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +/* #endif */ + PKIX_ERROR(PKIX_PRBINDFAILED); + } + +#ifdef PKIX_SOCKETDEBUG + printf("Successful bind!\n"); +#endif + + socket->status = SOCKET_BOUND; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Connect + * DESCRIPTION: + * + * This functions performs the connect function for the client socket + * specified in "socket", storing the status at "pStatus". + * + * PARAMETERS: + * "socket" + * The address of the Socket for which a connect is to be performed. + * Must be non-NULL. + * "pStatus" + * The address at which the connection status is stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Connect( + PKIX_PL_Socket *socket, + PRErrorCode *pStatus, + void *plContext) +{ + PRStatus rv = PR_FAILURE; + PRErrorCode errorcode = 0; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Connect"); + PKIX_NULLCHECK_TWO(socket, socket->clientSock); + + PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Connect, + (socket->clientSock, socket->netAddr, socket->timeout)); + + if (rv == PR_FAILURE) { + errorcode = PR_GetError(); + *pStatus = errorcode; + if (errorcode == PR_IN_PROGRESS_ERROR) { + socket->status = SOCKET_CONNECTPENDING; + goto cleanup; + } else { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_Connect: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRCONNECTFAILED); + } + } + +#ifdef PKIX_SOCKETDEBUG + printf("Successful connect!\n"); +#endif + + *pStatus = 0; + socket->status = SOCKET_CONNECTED; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_ConnectContinue + * DESCRIPTION: + * + * This functions continues the connect function for the client socket + * specified in "socket", storing the status at "pStatus". It is expected that + * the non-blocking connect has returned PR_IN_PROGRESS_ERROR. + * + * PARAMETERS: + * "socket" + * The address of the Socket for which a connect is to be continued. + * Must be non-NULL. + * "pStatus" + * The address at which the connection status is stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_ConnectContinue( + PKIX_PL_Socket *socket, + PRErrorCode *pStatus, + void *plContext) +{ + PRStatus rv = PR_FAILURE; + PRErrorCode errorcode = 0; + PRPollDesc pollDesc; + PRInt32 numEvents = 0; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_ConnectContinue"); + PKIX_NULLCHECK_TWO(socket, socket->clientSock); + + pollDesc.fd = socket->clientSock; + pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; + pollDesc.out_flags = 0; + PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); + if (numEvents < 0) { + PKIX_ERROR(PKIX_PRPOLLFAILED); + } + + if (numEvents == 0) { + *pStatus = PR_IN_PROGRESS_ERROR; + goto cleanup; + } + + PKIX_PL_NSSCALLRV(SOCKET, rv, PR_ConnectContinue, + (socket->clientSock, pollDesc.out_flags)); + + /* + * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS + * even though the connection is not yet ready. But its deceit + * is betrayed by the contents of out_flags! + */ + if ((rv == PR_SUCCESS) && (pollDesc.out_flags == PR_POLL_ERR)) { + *pStatus = PR_IN_PROGRESS_ERROR; + goto cleanup; + } + + if (rv == PR_FAILURE) { + errorcode = PR_GetError(); + *pStatus = errorcode; + if (errorcode == PR_IN_PROGRESS_ERROR) { + goto cleanup; + } else { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_ConnectContinue: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED); + } + } + +#ifdef PKIX_SOCKETDEBUG + printf("Successful connect!\n"); +#endif + + *pStatus = 0; + socket->status = SOCKET_CONNECTED; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Socket_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Socket *socket = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_SOCKET_TYPE, plContext), + PKIX_OBJECTNOTANSOCKET); + + socket = (PKIX_PL_Socket *)object; + + if (socket->isServer) { + if (socket->serverSock) { + PR_Close(socket->serverSock); + } + } else { + if (socket->clientSock) { + PR_Close(socket->clientSock); + } + } + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Socket_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_Socket *socket = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_SOCKET_TYPE, plContext), + PKIX_OBJECTNOTSOCKET); + + socket = (PKIX_PL_Socket *)object; + + *pHashcode = (((socket->timeout << 3) + + (socket->netAddr->inet.family << 3)) + + (*((PKIX_UInt32 *)&(socket->netAddr->inet.ip)))) + + socket->netAddr->inet.port; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Socket_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_Socket *firstSocket = NULL; + PKIX_PL_Socket *secondSocket = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + *pResult = PKIX_FALSE; + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_SOCKET_TYPE, plContext), + PKIX_OBJECTNOTSOCKET); + + firstSocket = (PKIX_PL_Socket *)firstObject; + secondSocket = (PKIX_PL_Socket *)secondObject; + + if (firstSocket->timeout != secondSocket->timeout) { + goto cleanup; + } + + if (firstSocket->netAddr == secondSocket->netAddr) { + *pResult = PKIX_TRUE; + goto cleanup; + } + + if ((firstSocket->netAddr->inet.family != + secondSocket->netAddr->inet.family) || + (*((PKIX_UInt32 *)&(firstSocket->netAddr->inet.ip)) != + *((PKIX_UInt32 *)&(secondSocket->netAddr->inet.ip))) || + (firstSocket->netAddr->inet.port != + secondSocket->netAddr->inet.port)) { + + goto cleanup; + + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_PL_SOCKET_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_pl_Socket_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_RegisterSelf"); + + entry.description = "Socket"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_Socket); + entry.destructor = pkix_pl_Socket_Destroy; + entry.equalsFunction = pkix_pl_Socket_Equals; + entry.hashcodeFunction = pkix_pl_Socket_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_SOCKET_TYPE] = entry; + +#ifdef PKIX_SOCKETTRACE + { + char *val = NULL; + val = PR_GetEnvSecure("SOCKETTRACE"); + /* Is SOCKETTRACE set in the environment? */ + if ((val != NULL) && (*val != '\0')) { + socketTraceFlag = + ((*val == '1')?PKIX_TRUE:PKIX_FALSE); + } + } +#endif + + PKIX_RETURN(SOCKET); +} + +/* --Public-Socket-Functions----------------------------------- */ + +/* + * FUNCTION: pkix_pl_Socket_Listen + * DESCRIPTION: + * + * This functions establishes a listening queue for the server Socket + * pointed to by "socket". + * + * PARAMETERS: + * "socket" + * The address of the server socket for which the queue is to be + * established. Must be non-NULL. + * "backlog" + * The UInt32 value of the length of the queue to be established. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Listen( + PKIX_PL_Socket *socket, + PKIX_UInt32 backlog, + void *plContext) +{ +#ifdef PKIX_SOCKETDEBUG + PRErrorCode errorcode = 0; +#endif + PRStatus rv = PR_FAILURE; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Listen"); + PKIX_NULLCHECK_TWO(socket, socket->serverSock); + + PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Listen, + (socket->serverSock, (PRIntn)backlog)); + + if (rv == PR_FAILURE) { +#ifdef PKIX_SOCKETDEBUG + errorcode = PR_GetError(); + printf + ("pkix_pl_Socket_Listen: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRLISTENFAILED); + } + +#ifdef PKIX_SOCKETDEBUG + printf("Successful listen!\n"); +#endif + + socket->status = SOCKET_LISTENING; +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Shutdown + * DESCRIPTION: + * + * This functions performs the shutdown of any connections controlled by the + * socket pointed to by "socket". + * + * PARAMETERS: + * "socket" + * The address of the socket to be shut down. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Shutdown( + PKIX_PL_Socket *socket, + void *plContext) +{ +#ifdef PKIX_SOCKETDEBUG + PRErrorCode errorcode = 0; +#endif + PRStatus rv = PR_FAILURE; + PRFileDesc *fileDesc = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Shutdown"); + PKIX_NULLCHECK_ONE(socket); + + fileDesc = + (socket->isServer)?(socket->serverSock):(socket->clientSock); + + PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Shutdown, + (fileDesc, PR_SHUTDOWN_BOTH)); + + if (rv == PR_FAILURE) { +#ifdef PKIX_SOCKETDEBUG + errorcode = PR_GetError(); + printf + ("pkix_pl_Socket_Shutdown: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRSHUTDOWNFAILED); + } + socket->status = SOCKET_SHUTDOWN; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Send + * DESCRIPTION: + * + * This functions sends a message using the socket pointed to by "sendSock", + * from the buffer pointed to by "buf", of the number of bytes given by + * "bytesToWrite", storing the number of bytes actually written at + * "pBytesWritten". If "socket" is in non-blocking mode, the send operation + * may store -1 at "pBytesWritten" and the write is not complete until a + * corresponding pkix_pl_Poll call has indicated its completion by returning + * a non-negative value for bytes written. + * + * PARAMETERS: + * "sendSock" + * The address of the Socket on which the message is to be sent. Must + * be non-NULL. + * "buf" + * The address of the data to be sent. Must be non-NULL. + * "bytesToWrite"" + * The UInt32 value indicating the number of bytes to write. + * "pBytesWritten" + * The address at which the Int32 value indicating the number of bytes + * actually written is to be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Send( + PKIX_PL_Socket *sendSock, + void *buf, + PKIX_UInt32 bytesToWrite, + PKIX_Int32 *pBytesWritten, + void *plContext) +{ + PRInt32 bytesWritten = 0; + PRErrorCode errorcode = 0; + PRFileDesc *fd = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Send"); + PKIX_NULLCHECK_TWO(buf, pBytesWritten); + + fd = sendSock->clientSock; + + PKIX_PL_NSSCALLRV(SOCKET, bytesWritten, PR_Send, + (fd, buf, (PRInt32)bytesToWrite, 0, sendSock->timeout)); + + if (bytesWritten >= 0) { + if (sendSock->status == SOCKET_SENDRCVPENDING) { + sendSock->status = SOCKET_RCVPENDING; + } else { + sendSock->status = SOCKET_CONNECTED; + } +#ifdef PKIX_SOCKETTRACE + pkix_pl_socket_tracebuff(buf, bytesWritten); +#endif + } else { + errorcode = PR_GetError(); + if (errorcode != PR_WOULD_BLOCK_ERROR) { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_Send: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRSENDFAILED); + } + + sendSock->writeBuf = buf; + sendSock->writeBufSize = bytesToWrite; + if (sendSock->status == SOCKET_RCVPENDING) { + sendSock->status = SOCKET_SENDRCVPENDING; + } else { + sendSock->status = SOCKET_SENDPENDING; + } + } + + *pBytesWritten = (PKIX_Int32)bytesWritten; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Recv + * DESCRIPTION: + * + * This functions receives a message on the socket pointed to by "rcvSock", + * into the buffer pointed to by "buf", of capacity given by "capacity", + * storing the number of bytes actually received at "pBytesRead". If "socket" + * is in non-blocking mode, the receive operation may store -1 at + * "pBytesWritten". In that case the write is not complete until a + * corresponding pkix_pl_Poll call has indicated its completion by returning + * a non-negative value for bytes read. + * + * PARAMETERS: + * "rcvSock" + * The address of the Socket on which the message is to be received. + * Must be non-NULL. + * "buf" + * The address of the buffer into which the message is to be received. + * Must be non-NULL. + * "capacity" + * The UInt32 value of the size of the buffer; that is, the maximum + * number of bytes that can be received. + * "pBytesRead" + * The address at which is stored the Int32 value of the number of bytes + * actually received. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Recv( + PKIX_PL_Socket *rcvSock, + void *buf, + PKIX_UInt32 capacity, + PKIX_Int32 *pBytesRead, + void *plContext) +{ + PRErrorCode errorcode = 0; + PRInt32 bytesRead = 0; + PRFileDesc *fd = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Recv"); + PKIX_NULLCHECK_THREE(rcvSock, buf, pBytesRead); + + fd = rcvSock->clientSock; + + PKIX_PL_NSSCALLRV(SOCKET, bytesRead, PR_Recv, + (fd, buf, (PRInt32)capacity, 0, rcvSock->timeout)); + + if (bytesRead > 0) { + if (rcvSock->status == SOCKET_SENDRCVPENDING) { + rcvSock->status = SOCKET_SENDPENDING; + } else { + rcvSock->status = SOCKET_CONNECTED; + } +#ifdef PKIX_SOCKETTRACE + pkix_pl_socket_tracebuff(buf, bytesRead); +#endif + } else if (bytesRead == 0) { + PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED); + } else { + errorcode = PR_GetError(); + if (errorcode != PR_WOULD_BLOCK_ERROR) { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_Recv: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRRECVFAILED); + } + rcvSock->readBuf = buf; + rcvSock->readBufSize = capacity; + if (rcvSock->status == SOCKET_SENDPENDING) { + rcvSock->status = SOCKET_SENDRCVPENDING; + } else { + rcvSock->status = SOCKET_RCVPENDING; + } + + } + + *pBytesRead = (PKIX_Int32)bytesRead; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Poll + * DESCRIPTION: + * + * This functions checks for completion of an earlier Send or Recv on the + * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes + * written by a completed Send and in "pBytesRead" the number of bytes + * received in a completed Recv. A value of -1 returned indicates the + * operation has still not completed. A NULL pointer may be supplied for + * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer + * may be supplied for "pBytesRead" to avoid checking for completion of a Recv. + * + * PARAMETERS: + * "sock" + * The address of the socket for which completions are to be checked. + * "pBytesWritten" + * The address at which the number of bytes written is to be stored, if + * a pending Send has completed. If NULL, Sends are not checked. + * "pBytesRead" + * The address at which the number of bytes read is to be stored, if + * a pending Recv has completed. If NULL, Recvs are not checked. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Poll( + PKIX_PL_Socket *sock, + PKIX_Int32 *pBytesWritten, + PKIX_Int32 *pBytesRead, + void *plContext) +{ + PRPollDesc pollDesc; + PRInt32 numEvents = 0; + PKIX_Int32 bytesRead = 0; + PKIX_Int32 bytesWritten = 0; + PRErrorCode errorcode = 0; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Poll"); + PKIX_NULLCHECK_ONE(sock); + + pollDesc.fd = sock->clientSock; + pollDesc.in_flags = 0; + pollDesc.out_flags = 0; + + if ((pBytesWritten) && + ((sock->status == SOCKET_SENDPENDING) || + (sock->status == SOCKET_SENDRCVPENDING))) { + pollDesc.in_flags = PR_POLL_WRITE; + } + + if ((pBytesRead) && + ((sock->status == SOCKET_RCVPENDING) || + (sock->status == SOCKET_SENDRCVPENDING))) { + pollDesc.in_flags |= PR_POLL_READ; + } + + PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); + + if (numEvents < 0) { + PKIX_ERROR(PKIX_PRPOLLFAILED); + } else if (numEvents > 0) { + if (pollDesc.out_flags & PR_POLL_WRITE) { + PKIX_CHECK(pkix_pl_Socket_Send + (sock, + sock->writeBuf, + sock->writeBufSize, + &bytesWritten, + plContext), + PKIX_SOCKETSENDFAILED); + *pBytesWritten = (PKIX_Int32)bytesWritten; + if (bytesWritten >= 0) { + sock->writeBuf = NULL; + sock->writeBufSize = 0; + } + } + + if (pollDesc.out_flags & PR_POLL_READ) { + PKIX_CHECK(pkix_pl_Socket_Recv + (sock, + sock->readBuf, + sock->readBufSize, + &bytesRead, + plContext), + PKIX_SOCKETRECVFAILED); + *pBytesRead = (PKIX_Int32)bytesRead; + if (bytesRead >= 0) { + sock->readBuf = NULL; + sock->readBufSize = 0; + } + } + } else if (numEvents == 0) { + errorcode = PR_GetError(); + if (errorcode != PR_WOULD_BLOCK_ERROR) { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_Poll: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRPOLLFAILED); + } + if (pBytesWritten) { + *pBytesWritten = 0; + } + if (pBytesRead) { + *pBytesRead = 0; + } + } + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Accept + * DESCRIPTION: + * + * This functions accepts a client connection for the server Socket pointed + * to by "serverSocket", creating a new Socket and storing the result at + * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this + * function will return NULL if there is no client connection to accept. + * Otherwise this function will block until a connection is available. + * When a client connection is available the new Socket will have the same + * blocking/non-blocking property as "serverSocket". + * + * PARAMETERS: + * "serverSocket" + * The address of the Socket for which a client connection is to be + * accepted. Must be non-NULL. + * "pRendezvousSocket" + * The address at which the created Socket is stored, when a client + * connection is available, or at which NULL is stored, if no connection + * is available for a non-blocking "serverSocket". Must be non-NULL. + * "plContext" + * Platform-specific context pointer + * THREAD SAFETY: + * Thread Safe (see Thread Safety definitions in Programmer's Guide) + * RETURNS: + * none + */ +static PKIX_Error * +pkix_pl_Socket_Accept( + PKIX_PL_Socket *serverSocket, + PKIX_PL_Socket **pRendezvousSocket, + void *plContext) +{ + PRErrorCode errorcode = 0; + PRFileDesc *rendezvousSock = NULL; + PRNetAddr *clientAddr = NULL; + PKIX_PL_Socket *newSocket = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Accept"); + PKIX_NULLCHECK_TWO(serverSocket, pRendezvousSocket); + + PKIX_PL_NSSCALLRV(SOCKET, rendezvousSock, PR_Accept, + (serverSocket->serverSock, clientAddr, serverSocket->timeout)); + + if (!rendezvousSock) { + errorcode = PR_GetError(); + if (errorcode != PR_WOULD_BLOCK_ERROR) { +#ifdef PKIX_SOCKETDEBUG + printf + ("pkix_pl_Socket_Accept: %s\n", + PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); +#endif + PKIX_ERROR(PKIX_PRACCEPTFAILED); + } + serverSocket->status = SOCKET_ACCEPTPENDING; + *pRendezvousSocket = NULL; + goto cleanup; + + } + +#ifdef PKIX_SOCKETDEBUG + printf("Successful accept!\n"); +#endif + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_SOCKET_TYPE, + sizeof (PKIX_PL_Socket), + (PKIX_PL_Object **)&newSocket, + plContext), + PKIX_COULDNOTCREATESOCKETOBJECT); + + newSocket->isServer = PKIX_FALSE; + newSocket->timeout = serverSocket->timeout; + newSocket->clientSock = rendezvousSock; + newSocket->serverSock = NULL; + newSocket->netAddr = NULL; + newSocket->status = SOCKET_CONNECTED; + newSocket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; + newSocket->callbackList.listenCallback = pkix_pl_Socket_Listen; + newSocket->callbackList.acceptCallback = pkix_pl_Socket_Accept; + newSocket->callbackList.connectcontinueCallback = + pkix_pl_Socket_ConnectContinue; + newSocket->callbackList.sendCallback = pkix_pl_Socket_Send; + newSocket->callbackList.recvCallback = pkix_pl_Socket_Recv; + newSocket->callbackList.pollCallback = pkix_pl_Socket_Poll; + + if (serverSocket->timeout == 0) { + PKIX_CHECK(pkix_pl_Socket_SetNonBlocking + (rendezvousSock, plContext), + PKIX_SOCKETSETNONBLOCKINGFAILED); + } + + *pRendezvousSocket = newSocket; + +cleanup: + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_Create + * DESCRIPTION: + * + * This function creates a new Socket, setting it to be a server or a client + * according to the value of "isServer", setting its timeout value from + * "timeout" and server address from "netAddr", and stores the created Socket + * at "pSocket". + * + * PARAMETERS: + * "isServer" + * The Boolean value indicating if PKIX_TRUE, that a server socket (using + * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a + * client socket (using Connect) is to be created. + * "timeout" + * A PRTimeInterval value to be used for I/O waits for this socket. If + * zero, non-blocking I/O is to be used. + * "netAddr" + * The PRNetAddr to be used for the Bind function, if this is a server + * socket, or for the Connect, if this is a client socket. + * "pSocket" + * The address at which the Socket is to 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 Socket 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_pl_Socket_Create( + PKIX_Boolean isServer, + PRIntervalTime timeout, + PRNetAddr *netAddr, + PRErrorCode *status, + PKIX_PL_Socket **pSocket, + void *plContext) +{ + PKIX_PL_Socket *socket = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create"); + PKIX_NULLCHECK_ONE(pSocket); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_SOCKET_TYPE, + sizeof (PKIX_PL_Socket), + (PKIX_PL_Object **)&socket, + plContext), + PKIX_COULDNOTCREATESOCKETOBJECT); + + socket->isServer = isServer; + socket->timeout = timeout; + socket->clientSock = NULL; + socket->serverSock = NULL; + socket->netAddr = netAddr; + + socket->callbackList.listenCallback = pkix_pl_Socket_Listen; + socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; + socket->callbackList.connectcontinueCallback = + pkix_pl_Socket_ConnectContinue; + socket->callbackList.sendCallback = pkix_pl_Socket_Send; + socket->callbackList.recvCallback = pkix_pl_Socket_Recv; + socket->callbackList.pollCallback = pkix_pl_Socket_Poll; + socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; + + if (isServer) { + PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), + PKIX_SOCKETCREATESERVERFAILED); + *status = 0; + } else { + socket->timeout = timeout; + PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), + PKIX_SOCKETCREATECLIENTFAILED); + PKIX_CHECK(pkix_pl_Socket_Connect(socket, status, plContext), + PKIX_SOCKETCONNECTFAILED); + } + + *pSocket = socket; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(socket); + } + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_CreateByName + * DESCRIPTION: + * + * This function creates a new Socket, setting it to be a server or a client + * according to the value of "isServer", setting its timeout value from + * "timeout" and server address and port number from "serverName", and stores + * the status at "pStatus" and the created Socket at "pSocket". + * + * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip + * address of PR_INADDR_ANY. + * + * PARAMETERS: + * "isServer" + * The Boolean value indicating if PKIX_TRUE, that a server socket (using + * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a + * client socket (using Connect) is to be created. + * "timeout" + * A PRTimeInterval value to be used for I/O waits for this socket. If + * zero, non-blocking I/O is to be used. + * "serverName" + * Address of a character string consisting of the server's domain name + * followed by a colon and a port number for the desired socket. + * "pStatus" + * Address at which the PRErrorCode resulting from the create is + * stored. Must be non-NULL. + * "pSocket" + * The address at which the Socket is to 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 Socket 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_pl_Socket_CreateByName( + PKIX_Boolean isServer, + PRIntervalTime timeout, + char *serverName, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext) +{ + PRNetAddr netAddr; + PKIX_PL_Socket *socket = NULL; + char *sepPtr = NULL; + PRHostEnt hostent; + PRIntn hostenum; + PRStatus prstatus = PR_FAILURE; + char buf[PR_NETDB_BUF_SIZE]; + PRUint16 portNum = 0; + char *localCopyName = NULL; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByName"); + PKIX_NULLCHECK_TWO(serverName, pSocket); + + localCopyName = PL_strdup(serverName); + + sepPtr = strchr(localCopyName, ':'); + /* First strip off the portnum, if present, from the end of the name */ + if (sepPtr) { + *sepPtr++ = '\0'; + portNum = (PRUint16)atoi(sepPtr); + } else { + portNum = (PRUint16)LDAP_PORT; + } + + prstatus = PR_GetHostByName(localCopyName, buf, sizeof(buf), &hostent); + + if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { + /* + * The hostname may be a fully-qualified name. Try using just + * the leftmost component in our lookup. + */ + sepPtr = strchr(localCopyName, '.'); + if (sepPtr) { + *sepPtr++ = '\0'; + } + prstatus = PR_GetHostByName + (localCopyName, buf, sizeof(buf), &hostent); + + if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { + PKIX_ERROR + (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); + } + } + + netAddr.inet.family = PR_AF_INET; + netAddr.inet.port = PR_htons(portNum); + + if (isServer) { + + netAddr.inet.ip = PR_INADDR_ANY; + + } else { + + hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &netAddr); + if (hostenum == -1) { + PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); + } + } + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_SOCKET_TYPE, + sizeof (PKIX_PL_Socket), + (PKIX_PL_Object **)&socket, + plContext), + PKIX_COULDNOTCREATESOCKETOBJECT); + + socket->isServer = isServer; + socket->timeout = timeout; + socket->clientSock = NULL; + socket->serverSock = NULL; + socket->netAddr = &netAddr; + + socket->callbackList.listenCallback = pkix_pl_Socket_Listen; + socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; + socket->callbackList.connectcontinueCallback = + pkix_pl_Socket_ConnectContinue; + socket->callbackList.sendCallback = pkix_pl_Socket_Send; + socket->callbackList.recvCallback = pkix_pl_Socket_Recv; + socket->callbackList.pollCallback = pkix_pl_Socket_Poll; + socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; + + if (isServer) { + PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), + PKIX_SOCKETCREATESERVERFAILED); + *pStatus = 0; + } else { + PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), + PKIX_SOCKETCREATECLIENTFAILED); + PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), + PKIX_SOCKETCONNECTFAILED); + } + + *pSocket = socket; + +cleanup: + PL_strfree(localCopyName); + + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(socket); + } + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_CreateByHostAndPort + * DESCRIPTION: + * + * This function creates a new Socket, setting it to be a server or a client + * according to the value of "isServer", setting its timeout value from + * "timeout", host from "hostname", and port number from "portNum", and stores + * the status at "pStatus" and the created Socket at "pSocket". + * + * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip + * address of PR_INADDR_ANY. + * + * PARAMETERS: + * "isServer" + * The Boolean value indicating if PKIX_TRUE, that a server socket (using + * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a + * client socket (using Connect) is to be created. + * "timeout" + * A PRTimeInterval value to be used for I/O waits for this socket. If + * zero, non-blocking I/O is to be used. + * "hostname" + * Address of a character string consisting of the server's domain name. + * "portNum" + * UInt16 value of the port number for the desired socket. + * "pStatus" + * Address at which the PRErrorCode resulting from the create is + * stored. Must be non-NULL. + * "pSocket" + * The address at which the Socket is to 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 Socket 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_pl_Socket_CreateByHostAndPort( + PKIX_Boolean isServer, + PRIntervalTime timeout, + char *hostname, + PRUint16 portnum, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext) +{ + PRNetAddr netAddr; + PKIX_PL_Socket *socket = NULL; + char *sepPtr = NULL; + PRHostEnt hostent; + PRIntn hostenum; + PRStatus prstatus = PR_FAILURE; + char buf[PR_NETDB_BUF_SIZE]; + + PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort"); + PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket); + + + prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); + + if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { + /* + * The hostname may be a fully-qualified name. Try using just + * the leftmost component in our lookup. + */ + sepPtr = strchr(hostname, '.'); + if (sepPtr) { + *sepPtr++ = '\0'; + } + prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); + + if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { + PKIX_ERROR + (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); + } + } + + netAddr.inet.family = PR_AF_INET; + netAddr.inet.port = PR_htons(portnum); + + if (isServer) { + + netAddr.inet.ip = PR_INADDR_ANY; + + } else { + + hostenum = PR_EnumerateHostEnt(0, &hostent, portnum, &netAddr); + if (hostenum == -1) { + PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); + } + } + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_SOCKET_TYPE, + sizeof (PKIX_PL_Socket), + (PKIX_PL_Object **)&socket, + plContext), + PKIX_COULDNOTCREATESOCKETOBJECT); + + socket->isServer = isServer; + socket->timeout = timeout; + socket->clientSock = NULL; + socket->serverSock = NULL; + socket->netAddr = &netAddr; + + socket->callbackList.listenCallback = pkix_pl_Socket_Listen; + socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; + socket->callbackList.connectcontinueCallback = + pkix_pl_Socket_ConnectContinue; + socket->callbackList.sendCallback = pkix_pl_Socket_Send; + socket->callbackList.recvCallback = pkix_pl_Socket_Recv; + socket->callbackList.pollCallback = pkix_pl_Socket_Poll; + socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; + + if (isServer) { + PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), + PKIX_SOCKETCREATESERVERFAILED); + *pStatus = 0; + } else { + PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), + PKIX_SOCKETCREATECLIENTFAILED); + PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), + PKIX_SOCKETCONNECTFAILED); + } + + *pSocket = socket; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + PKIX_DECREF(socket); + } + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_GetCallbackList + */ +PKIX_Error * +pkix_pl_Socket_GetCallbackList( + PKIX_PL_Socket *socket, + PKIX_PL_Socket_Callback **pCallbackList, + void *plContext) +{ + PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetCallbackList"); + PKIX_NULLCHECK_TWO(socket, pCallbackList); + + *pCallbackList = &(socket->callbackList); + + PKIX_RETURN(SOCKET); +} + +/* + * FUNCTION: pkix_pl_Socket_GetPRFileDesc + */ +PKIX_Error * +pkix_pl_Socket_GetPRFileDesc( + PKIX_PL_Socket *socket, + PRFileDesc **pDesc, + void *plContext) +{ + PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetPRFileDesc"); + PKIX_NULLCHECK_TWO(socket, pDesc); + + *pDesc = socket->clientSock; + + PKIX_RETURN(SOCKET); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h new file mode 100644 index 0000000000..abf6628b32 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h @@ -0,0 +1,209 @@ +/* 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_pl_socket.h + * + * Socket Object Type Definition + * + */ + +#ifndef _PKIX_PL_SOCKET_H +#define _PKIX_PL_SOCKET_H + +#include <errno.h> +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SOCKET_BOUND, + SOCKET_LISTENING, + SOCKET_ACCEPTPENDING, + SOCKET_UNCONNECTED, + SOCKET_CONNECTPENDING, + SOCKET_CONNECTED, + SOCKET_SENDPENDING, + SOCKET_RCVPENDING, + SOCKET_SENDRCVPENDING, + SOCKET_SHUTDOWN +} SockStatus; + +/* This is the default port number, if none is supplied to CreateByName. */ +#define LDAP_PORT 389 + +/* + * These callbacks allow a user to substitute a counterfeit socket in places + * where a PKIX_PL_Socket is expected. A conforming usage will use the + * ListenCallback function instead of Listen, AcceptCallback instead of Accept, + * etc. The counterfeit socket may have special capabilites such as the + * ability to do proxy authentication, etc. + */ + +typedef PKIX_Error * +(*pkix_pl_Socket_ListenCallback)( + PKIX_PL_Socket *socket, + PKIX_UInt32 backlog, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_AcceptCallback)( + PKIX_PL_Socket *socket, + PKIX_PL_Socket **pRendezvousSock, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_ConnectContinueCallback)( + PKIX_PL_Socket *socket, + PRErrorCode *pStatus, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_SendCallback)( + PKIX_PL_Socket *sendSock, + void *buf, + PKIX_UInt32 bytesToWrite, + PKIX_Int32 *pBytesWritten, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_RecvCallback)( + PKIX_PL_Socket *rcvSock, + void *buf, + PKIX_UInt32 capacity, + PKIX_Int32 *pBytesRead, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_PollCallback)( + PKIX_PL_Socket *sock, + PKIX_Int32 *pBytesWritten, + PKIX_Int32 *pBytesRead, + void *plContext); + +typedef PKIX_Error * +(*pkix_pl_Socket_ShutdownCallback)( + PKIX_PL_Socket *socket, void *plContext); + +typedef struct PKIX_PL_Socket_CallbackStruct { + pkix_pl_Socket_ListenCallback listenCallback; + pkix_pl_Socket_AcceptCallback acceptCallback; + pkix_pl_Socket_ConnectContinueCallback connectcontinueCallback; + pkix_pl_Socket_SendCallback sendCallback; + pkix_pl_Socket_RecvCallback recvCallback; + pkix_pl_Socket_PollCallback pollCallback; + pkix_pl_Socket_ShutdownCallback shutdownCallback; +} PKIX_PL_Socket_Callback; + +struct PKIX_PL_SocketStruct { + PKIX_Boolean isServer; + PRIntervalTime timeout; /* zero for non-blocking I/O */ + SockStatus status; + PRFileDesc *clientSock; + PRFileDesc *serverSock; + void *readBuf; + void *writeBuf; + PKIX_UInt32 readBufSize; + PKIX_UInt32 writeBufSize; + PRNetAddr *netAddr; + PKIX_PL_Socket_Callback callbackList; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_Socket_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_Socket_Create( + PKIX_Boolean isServer, + PRIntervalTime timeout, /* zero for non-blocking I/O */ + PRNetAddr *netAddr, + PRErrorCode *status, + PKIX_PL_Socket **pSocket, + void *plContext); + +PKIX_Error * +pkix_pl_Socket_CreateByName( + PKIX_Boolean isServer, + PRIntervalTime timeout, + char *serverName, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext); + +PKIX_Error * +pkix_pl_Socket_CreateByHostAndPort( + PKIX_Boolean isServer, + PRIntervalTime timeout, + char *hostname, + PRUint16 portnum, + PRErrorCode *pStatus, + PKIX_PL_Socket **pSocket, + void *plContext); + +/* Do not use these functions directly; use their callback variants instead + * static PKIX_Error * + * pkix_pl_Socket_Listen( + * PKIX_PL_Socket *socket, + * PKIX_UInt32 backlog, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_Accept( + * PKIX_PL_Socket *socket, + * PKIX_PL_Socket **pRendezvousSock, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_ConnectContinue( + * PKIX_PL_Socket *socket, + * PRErrorCode *pStatus, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_Send( + * PKIX_PL_Socket *sendSock, + * void *buf, + * PKIX_UInt32 bytesToWrite, + * PKIX_Int32 *pBytesWritten, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_Recv( + * PKIX_PL_Socket *rcvSock, + * void *buf, + * PKIX_UInt32 capacity, + * PKIX_Int32 *pBytesRead, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_Poll( + * PKIX_PL_Socket *sock, + * PKIX_Int32 *pBytesWritten, + * PKIX_Int32 *pBytesRead, + * void *plContext); + * + * static PKIX_Error * + * pkix_pl_Socket_Shutdown( + * PKIX_PL_Socket *socket, void *plContext); + */ + +PKIX_Error * +pkix_pl_Socket_GetCallbackList( + PKIX_PL_Socket *socket, + PKIX_PL_Socket_Callback **pCallbackList, + void *plContext); + +PKIX_Error * +pkix_pl_Socket_GetPRFileDesc( + PKIX_PL_Socket *socket, + PRFileDesc **pDesc, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_SOCKET_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile new file mode 100644 index 0000000000..2b4b1574ab --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile @@ -0,0 +1,47 @@ +#! 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_pl_nss/pki/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp new file mode 100644 index 0000000000..616f94fd46 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp @@ -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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'lib_libpkix_pkix_pl_nss_pki_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_pl_basicconstraints.h', + 'pkix_pl_cert.h', + 'pkix_pl_certpolicyinfo.h', + 'pkix_pl_certpolicymap.h', + 'pkix_pl_certpolicyqualifier.h', + 'pkix_pl_crl.h', + 'pkix_pl_crldp.h', + 'pkix_pl_crlentry.h', + 'pkix_pl_date.h', + 'pkix_pl_generalname.h', + 'pkix_pl_infoaccess.h', + 'pkix_pl_nameconstraints.h', + 'pkix_pl_ocspcertid.h', + 'pkix_pl_ocsprequest.h', + 'pkix_pl_ocspresponse.h', + 'pkix_pl_publickey.h', + 'pkix_pl_x500name.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn new file mode 100644 index 0000000000..aba1367e56 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn @@ -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/. +CORE_DEPTH = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_pl_basicconstraints.h \ + pkix_pl_cert.h \ + pkix_pl_certpolicyinfo.h \ + pkix_pl_certpolicymap.h \ + pkix_pl_certpolicyqualifier.h \ + pkix_pl_crl.h \ + pkix_pl_crldp.h \ + pkix_pl_crlentry.h \ + pkix_pl_date.h \ + pkix_pl_generalname.h \ + pkix_pl_infoaccess.h \ + pkix_pl_nameconstraints.h \ + pkix_pl_ocsprequest.h \ + pkix_pl_ocspresponse.h \ + pkix_pl_publickey.h \ + pkix_pl_x500name.h \ + pkix_pl_ocspcertid.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_pl_basicconstraints.c \ + pkix_pl_cert.c \ + pkix_pl_certpolicyinfo.c \ + pkix_pl_certpolicymap.c \ + pkix_pl_certpolicyqualifier.c \ + pkix_pl_crl.c \ + pkix_pl_crldp.c \ + pkix_pl_crlentry.c \ + pkix_pl_date.c \ + pkix_pl_generalname.c \ + pkix_pl_infoaccess.c \ + pkix_pl_nameconstraints.c \ + pkix_pl_ocsprequest.c \ + pkix_pl_ocspresponse.c \ + pkix_pl_publickey.c \ + pkix_pl_x500name.c \ + pkix_pl_ocspcertid.c \ + $(NULL) + +LIBRARY_NAME = pkixpki +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp new file mode 100644 index 0000000000..af7730c0bf --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp @@ -0,0 +1,39 @@ +# 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': 'pkixpki', + 'type': 'static_library', + 'sources': [ + 'pkix_pl_basicconstraints.c', + 'pkix_pl_cert.c', + 'pkix_pl_certpolicyinfo.c', + 'pkix_pl_certpolicymap.c', + 'pkix_pl_certpolicyqualifier.c', + 'pkix_pl_crl.c', + 'pkix_pl_crldp.c', + 'pkix_pl_crlentry.c', + 'pkix_pl_date.c', + 'pkix_pl_generalname.c', + 'pkix_pl_infoaccess.c', + 'pkix_pl_nameconstraints.c', + 'pkix_pl_ocspcertid.c', + 'pkix_pl_ocsprequest.c', + 'pkix_pl_ocspresponse.c', + 'pkix_pl_publickey.c', + 'pkix_pl_x500name.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c new file mode 100644 index 0000000000..81615da37a --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c @@ -0,0 +1,407 @@ +/* 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_pl_basicconstraints.c + * + * BasicConstraints Object Functions + * + */ + +#include "pkix_pl_basicconstraints.h" + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_Create + * DESCRIPTION: + * + * Creates a new CertBasicConstraints object whose CA Flag has the value + * given by the Boolean value of "isCA" and whose path length field has the + * value given by the "pathLen" argument and stores it at "pObject". + * + * PARAMETERS + * "isCA" + * Boolean value with the desired value of CA Flag. + * "pathLen" + * a PKIX_Int32 with the desired value of path length + * "pObject" + * Address of object pointer's destination. 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 CertBasicConstraints 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_pl_CertBasicConstraints_Create( + PKIX_Boolean isCA, + PKIX_Int32 pathLen, + PKIX_PL_CertBasicConstraints **pObject, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *basic = NULL; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_Create"); + PKIX_NULLCHECK_ONE(pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTBASICCONSTRAINTS_TYPE, + sizeof (PKIX_PL_CertBasicConstraints), + (PKIX_PL_Object **)&basic, + plContext), + PKIX_COULDNOTCREATECERTBASICCONSTRAINTSOBJECT); + + basic->isCA = isCA; + + /* pathLen has meaning only for CAs, but it's not worth checking */ + basic->pathLen = pathLen; + + *pObject = basic; + +cleanup: + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertBasicConstraints_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *certB = NULL; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), + PKIX_OBJECTNOTCERTBASICCONSTRAINTS); + + certB = (PKIX_PL_CertBasicConstraints*)object; + + certB->isCA = PKIX_FALSE; + certB->pathLen = 0; + +cleanup: + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertBasicConstraints_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *certBasicConstraintsString = NULL; + PKIX_PL_CertBasicConstraints *certB = NULL; + PKIX_Boolean isCA = PKIX_FALSE; + PKIX_Int32 pathLen = 0; + PKIX_PL_String *outString = NULL; + char *fmtString = NULL; + PKIX_Boolean pathlenArg = PKIX_FALSE; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), + PKIX_FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT); + + certB = (PKIX_PL_CertBasicConstraints *)object; + + /* + * if CA == TRUE + * if pathLen == CERT_UNLIMITED_PATH_CONSTRAINT + * print "CA(-1)" + * else print "CA(nnn)" + * if CA == FALSE, print "~CA" + */ + + isCA = certB->isCA; + + if (isCA) { + pathLen = certB->pathLen; + + if (pathLen == CERT_UNLIMITED_PATH_CONSTRAINT) { + /* print "CA(-1)" */ + fmtString = "CA(-1)"; + pathlenArg = PKIX_FALSE; + } else { + /* print "CA(pathLen)" */ + fmtString = "CA(%d)"; + pathlenArg = PKIX_TRUE; + } + } else { + /* print "~CA" */ + fmtString = "~CA"; + pathlenArg = PKIX_FALSE; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + fmtString, + 0, + &certBasicConstraintsString, + plContext), + PKIX_STRINGCREATEFAILED); + + if (pathlenArg) { + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + certBasicConstraintsString, + pathLen), + PKIX_SPRINTFFAILED); + } else { + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, + plContext, + certBasicConstraintsString), + PKIX_SPRINTFFAILED); + } + + *pString = outString; + +cleanup: + + PKIX_DECREF(certBasicConstraintsString); + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertBasicConstraints_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *certB = NULL; + PKIX_Boolean isCA = PKIX_FALSE; + PKIX_Int32 pathLen = 0; + PKIX_Int32 hashInput = 0; + PKIX_UInt32 cbcHash = 0; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), + PKIX_OBJECTNOTCERTBASICCONSTRAINTS); + + certB = (PKIX_PL_CertBasicConstraints *)object; + + /* + * if CA == TRUE + * hash(pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT) + * if CA == FALSE, hash(0) + */ + + isCA = certB->isCA; + + if (isCA) { + pathLen = certB->pathLen; + + hashInput = pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT; + } + + PKIX_CHECK(pkix_hash + ((const unsigned char *)&hashInput, + sizeof (hashInput), + &cbcHash, + plContext), + PKIX_HASHFAILED); + + *pHashcode = cbcHash; + +cleanup: + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertBasicConstraints_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *firstCBC = NULL; + PKIX_PL_CertBasicConstraints *secondCBC = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean firstIsCA = PKIX_FALSE; + PKIX_Boolean secondIsCA = PKIX_FALSE; + PKIX_Int32 firstPathLen = 0; + PKIX_Int32 secondPathLen = 0; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CertBasicConstraints */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERTBASICCONSTRAINTS); + + /* + * Since we know firstObject is a CertBasicConstraints, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a CertBasicConstraints, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CERTBASICCONSTRAINTS_TYPE) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + firstCBC = (PKIX_PL_CertBasicConstraints *)firstObject; + secondCBC = (PKIX_PL_CertBasicConstraints *)secondObject; + + /* + * Compare the value of the CAFlag components + */ + + firstIsCA = firstCBC->isCA; + + /* + * Failure here would be an error, not merely a miscompare, + * since we know second is a CertBasicConstraints. + */ + secondIsCA = secondCBC->isCA; + + /* + * If isCA flags differ, the objects are not equal. + */ + if (secondIsCA != firstIsCA) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + /* + * If isCA was FALSE, the objects are equal, because + * pathLen is meaningless in that case. + */ + if (!firstIsCA) { + *pResult = PKIX_TRUE; + goto cleanup; + } + + firstPathLen = firstCBC->pathLen; + secondPathLen = secondCBC->pathLen; + + *pResult = (secondPathLen == firstPathLen); + +cleanup: + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertBasicConstraints_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTBASICCONSTRAINTS_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_pl_CertBasicConstraints_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTBASICCONSTRAINTS, + "pkix_pl_CertBasicConstraints_RegisterSelf"); + + entry.description = "CertBasicConstraints"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CertBasicConstraints); + entry.destructor = pkix_pl_CertBasicConstraints_Destroy; + entry.equalsFunction = pkix_pl_CertBasicConstraints_Equals; + entry.hashcodeFunction = pkix_pl_CertBasicConstraints_Hashcode; + entry.toStringFunction = pkix_pl_CertBasicConstraints_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERTBASICCONSTRAINTS_TYPE] = entry; + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_BasicConstraints_GetCAFlag( + PKIX_PL_CertBasicConstraints *basicConstraints, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_ENTER(CERTBASICCONSTRAINTS, + "PKIX_PL_BasicConstraintsGetCAFlag"); + PKIX_NULLCHECK_TWO(basicConstraints, pResult); + + *pResult = basicConstraints->isCA; + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} + +/* + * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_BasicConstraints_GetPathLenConstraint( + PKIX_PL_CertBasicConstraints *basicConstraints, + PKIX_Int32 *pPathLenConstraint, + void *plContext) +{ + PKIX_ENTER(CERTBASICCONSTRAINTS, + "PKIX_PL_BasicConstraintsGetPathLenConstraint"); + PKIX_NULLCHECK_TWO(basicConstraints, pPathLenConstraint); + + *pPathLenConstraint = basicConstraints->pathLen; + + PKIX_RETURN(CERTBASICCONSTRAINTS); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h new file mode 100644 index 0000000000..857529c95c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.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_pl_basicconstraints.h + * + * BasicConstraints Object Definitions + * + */ + +#ifndef _PKIX_PL_BASICCONSTRAINTS_H +#define _PKIX_PL_BASICCONSTRAINTS_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This structure reflects the contents of the basic constraints + * extension as described in Section 4.2.1.10 of RFC 3280. + * The cA flag indicates whether the public key in this certificate + * belongs to a certification authority. The pathLen constraint + * gives the maximum number of non-self-issued intermediate certificates + * that may follow this certificate in a valid certification path. + */ +struct PKIX_PL_CertBasicConstraintsStruct { + PKIX_Boolean isCA; + PKIX_Int32 pathLen; +}; + +PKIX_Error * +pkix_pl_CertBasicConstraints_Create( + PKIX_Boolean isCA, + PKIX_Int32 pathLen, + PKIX_PL_CertBasicConstraints **object, + void *plContext); + +PKIX_Error * +pkix_pl_CertBasicConstraints_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_BASICCONSTRAINTS_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c new file mode 100644 index 0000000000..9dddd2e40f --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c @@ -0,0 +1,3734 @@ +/* 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_pl_cert.c + * + * Certificate Object Functions + * + */ + +#include "pkix_pl_cert.h" + +extern PKIX_PL_HashTable *cachedCertSigTable; + +/* --Private-Cert-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_Cert_IsExtensionCritical + * DESCRIPTION: + * + * Checks the Cert specified by "cert" to determine whether the extension + * whose tag is the UInt32 value given by "tag" is marked as a critical + * extension, and stores the result in "pCritical". + * + * Tags are the index into the table "oids" of SECOidData defined in the + * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are + * are defined in secoidt.h for most of the table entries. + * + * If the specified tag is invalid (not in the list of tags) or if the + * extension is not found in the certificate, PKIX_FALSE is stored. + * + * PARAMETERS + * "cert" + * Address of Cert whose extensions are to be examined. Must be non-NULL. + * "tag" + * The UInt32 value of the tag for the extension whose criticality is + * to be determined + * "pCritical" + * Address where the Boolean value 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_pl_Cert_IsExtensionCritical( + PKIX_PL_Cert *cert, + PKIX_UInt32 tag, + PKIX_Boolean *pCritical, + void *plContext) +{ + PKIX_Boolean criticality = PKIX_FALSE; + CERTCertExtension **extensions = NULL; + SECStatus rv; + + PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical); + + extensions = cert->nssCert->extensions; + PKIX_NULLCHECK_ONE(extensions); + + PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n"); + rv = CERT_GetExtenCriticality(extensions, tag, &criticality); + if (SECSuccess == rv) { + *pCritical = criticality; + } else { + *pCritical = PKIX_FALSE; + } + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_DecodePolicyInfo + * DESCRIPTION: + * + * Decodes the contents of the CertificatePolicy extension in the + * CERTCertificate pointed to by "nssCert", to create a List of + * CertPolicyInfos, which is stored at the address "pCertPolicyInfos". + * A CERTCertificate contains the DER representation of the Cert. + * If this certificate does not have a CertificatePolicy extension, + * NULL will be stored. If a List is returned, it will be immutable. + * + * PARAMETERS + * "nssCert" + * Address of the Cert data whose extension is to be examined. Must be + * non-NULL. + * "pCertPolicyInfos" + * Address where the List of CertPolicyInfos 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. + */ +static PKIX_Error * +pkix_pl_Cert_DecodePolicyInfo( + CERTCertificate *nssCert, + PKIX_List **pCertPolicyInfos, + void *plContext) +{ + + SECStatus rv; + SECItem encodedCertPolicyInfo; + + /* Allocated in the arena; freed in CERT_Destroy... */ + CERTCertificatePolicies *certPol = NULL; + CERTPolicyInfo **policyInfos = NULL; + + /* Holder for the return value */ + PKIX_List *infos = NULL; + + PKIX_PL_OID *pkixOID = NULL; + PKIX_List *qualifiers = NULL; + PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; + PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL; + PKIX_PL_ByteArray *qualifierArray = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo"); + PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos); + + /* get PolicyInfo as a SECItem */ + PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); + rv = CERT_FindCertExtension + (nssCert, + SEC_OID_X509_CERTIFICATE_POLICIES, + &encodedCertPolicyInfo); + if (SECSuccess != rv) { + *pCertPolicyInfos = NULL; + goto cleanup; + } + + /* translate PolicyInfo to CERTCertificatePolicies */ + PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n"); + certPol = CERT_DecodeCertificatePoliciesExtension + (&encodedCertPolicyInfo); + + PORT_Free(encodedCertPolicyInfo.data); + + if (NULL == certPol) { + PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED); + } + + /* + * Check whether there are any policyInfos, so we can + * avoid creating an unnecessary List + */ + policyInfos = certPol->policyInfos; + if (!policyInfos) { + *pCertPolicyInfos = NULL; + goto cleanup; + } + + /* create a List of CertPolicyInfo Objects */ + PKIX_CHECK(PKIX_List_Create(&infos, plContext), + PKIX_LISTCREATEFAILED); + + /* + * Traverse the CERTCertificatePolicies structure, + * building each PKIX_PL_CertPolicyInfo object in turn + */ + while (*policyInfos != NULL) { + CERTPolicyInfo *policyInfo = *policyInfos; + CERTPolicyQualifier **policyQualifiers = + policyInfo->policyQualifiers; + if (policyQualifiers) { + /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */ + PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext), + PKIX_LISTCREATEFAILED); + + while (*policyQualifiers != NULL) { + CERTPolicyQualifier *policyQualifier = + *policyQualifiers; + + /* create the qualifier's OID object */ + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (&policyQualifier->qualifierID, + &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + + /* create qualifier's ByteArray object */ + + PKIX_CHECK(PKIX_PL_ByteArray_Create + (policyQualifier->qualifierValue.data, + policyQualifier->qualifierValue.len, + &qualifierArray, + plContext), + PKIX_BYTEARRAYCREATEFAILED); + + /* create a CertPolicyQualifier object */ + + PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create + (pkixOID, + qualifierArray, + &certPolicyQualifier, + plContext), + PKIX_CERTPOLICYQUALIFIERCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (qualifiers, + (PKIX_PL_Object *)certPolicyQualifier, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(pkixOID); + PKIX_DECREF(qualifierArray); + PKIX_DECREF(certPolicyQualifier); + + policyQualifiers++; + } + + PKIX_CHECK(PKIX_List_SetImmutable + (qualifiers, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + } + + + /* + * Create an OID object pkixOID from policyInfo->policyID. + * (The CERTPolicyInfo structure has an oid field, but it + * is of type SECOidTag. This function wants a SECItem.) + */ + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (&policyInfo->policyID, &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + + /* Create a CertPolicyInfo object */ + PKIX_CHECK(pkix_pl_CertPolicyInfo_Create + (pkixOID, qualifiers, &certPolicyInfo, plContext), + PKIX_CERTPOLICYINFOCREATEFAILED); + + /* Append the new CertPolicyInfo object to the list */ + PKIX_CHECK(PKIX_List_AppendItem + (infos, (PKIX_PL_Object *)certPolicyInfo, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(pkixOID); + PKIX_DECREF(qualifiers); + PKIX_DECREF(certPolicyInfo); + + policyInfos++; + } + + /* + * If there were no policies, we went straight to + * cleanup, so we don't have to NULLCHECK infos. + */ + PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pCertPolicyInfos = infos; + infos = NULL; + +cleanup: + if (certPol) { + PKIX_CERT_DEBUG + ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n"); + CERT_DestroyCertificatePoliciesExtension(certPol); + } + + PKIX_DECREF(infos); + PKIX_DECREF(pkixOID); + PKIX_DECREF(qualifiers); + PKIX_DECREF(certPolicyInfo); + PKIX_DECREF(certPolicyQualifier); + PKIX_DECREF(qualifierArray); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_DecodePolicyMapping + * DESCRIPTION: + * + * Decodes the contents of the PolicyMapping extension of the CERTCertificate + * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at + * the address pointed to by "pCertPolicyMaps". If this certificate does not + * have a PolicyMapping extension, NULL will be stored. If a List is returned, + * it will be immutable. + * + * PARAMETERS + * "nssCert" + * Address of the Cert data whose extension is to be examined. Must be + * non-NULL. + * "pCertPolicyMaps" + * Address where the List of CertPolicyMaps 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. + */ +static PKIX_Error * +pkix_pl_Cert_DecodePolicyMapping( + CERTCertificate *nssCert, + PKIX_List **pCertPolicyMaps, + void *plContext) +{ + SECStatus rv; + SECItem encodedCertPolicyMaps; + + /* Allocated in the arena; freed in CERT_Destroy... */ + CERTCertificatePolicyMappings *certPolMaps = NULL; + CERTPolicyMap **policyMaps = NULL; + + /* Holder for the return value */ + PKIX_List *maps = NULL; + + PKIX_PL_OID *issuerDomainOID = NULL; + PKIX_PL_OID *subjectDomainOID = NULL; + PKIX_PL_CertPolicyMap *certPolicyMap = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping"); + PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps); + + /* get PolicyMappings as a SECItem */ + PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n"); + rv = CERT_FindCertExtension + (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps); + if (SECSuccess != rv) { + *pCertPolicyMaps = NULL; + goto cleanup; + } + + /* translate PolicyMaps to CERTCertificatePolicyMappings */ + certPolMaps = CERT_DecodePolicyMappingsExtension + (&encodedCertPolicyMaps); + + PORT_Free(encodedCertPolicyMaps.data); + + if (!certPolMaps) { + PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED); + } + + PKIX_NULLCHECK_ONE(certPolMaps->policyMaps); + + policyMaps = certPolMaps->policyMaps; + + /* create a List of CertPolicyMap Objects */ + PKIX_CHECK(PKIX_List_Create(&maps, plContext), + PKIX_LISTCREATEFAILED); + + /* + * Traverse the CERTCertificatePolicyMappings structure, + * building each CertPolicyMap object in turn + */ + do { + CERTPolicyMap *policyMap = *policyMaps; + + /* create the OID for the issuer Domain Policy */ + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (&policyMap->issuerDomainPolicy, + &issuerDomainOID, plContext), + PKIX_OIDCREATEFAILED); + + /* create the OID for the subject Domain Policy */ + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (&policyMap->subjectDomainPolicy, + &subjectDomainOID, plContext), + PKIX_OIDCREATEFAILED); + + /* create the CertPolicyMap */ + + PKIX_CHECK(pkix_pl_CertPolicyMap_Create + (issuerDomainOID, + subjectDomainOID, + &certPolicyMap, + plContext), + PKIX_CERTPOLICYMAPCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (maps, (PKIX_PL_Object *)certPolicyMap, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(issuerDomainOID); + PKIX_DECREF(subjectDomainOID); + PKIX_DECREF(certPolicyMap); + + policyMaps++; + } while (*policyMaps != NULL); + + PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pCertPolicyMaps = maps; + maps = NULL; + +cleanup: + if (certPolMaps) { + PKIX_CERT_DEBUG + ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n"); + CERT_DestroyPolicyMappingsExtension(certPolMaps); + } + + PKIX_DECREF(maps); + PKIX_DECREF(issuerDomainOID); + PKIX_DECREF(subjectDomainOID); + PKIX_DECREF(certPolicyMap); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints + * DESCRIPTION: + * + * Decodes the contents of the PolicyConstraints extension in the + * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values + * which are stored at the addresses "pExplicitPolicySkipCerts" and + * "pInhibitMappingSkipCerts", respectively. If this certificate does + * not have an PolicyConstraints extension, or if either of the optional + * components is not supplied, this function stores a value of -1 for any + * missing component. + * + * PARAMETERS + * "nssCert" + * Address of the Cert data whose extension is to be examined. Must be + * non-NULL. + * "pExplicitPolicySkipCerts" + * Address where the SkipCert value for the requireExplicitPolicy + * component will be stored. Must be non-NULL. + * "pInhibitMappingSkipCerts" + * Address where the SkipCert value for the inhibitPolicyMapping + * component 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. + */ +static PKIX_Error * +pkix_pl_Cert_DecodePolicyConstraints( + CERTCertificate *nssCert, + PKIX_Int32 *pExplicitPolicySkipCerts, + PKIX_Int32 *pInhibitMappingSkipCerts, + void *plContext) +{ + CERTCertificatePolicyConstraints policyConstraints; + SECStatus rv; + SECItem encodedCertPolicyConstraints; + PKIX_Int32 explicitPolicySkipCerts = -1; + PKIX_Int32 inhibitMappingSkipCerts = -1; + + PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints"); + PKIX_NULLCHECK_THREE + (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts); + + /* get the two skipCert values as SECItems */ + PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); + rv = CERT_FindCertExtension + (nssCert, + SEC_OID_X509_POLICY_CONSTRAINTS, + &encodedCertPolicyConstraints); + + if (rv == SECSuccess) { + + policyConstraints.explicitPolicySkipCerts.data = + (unsigned char *)&explicitPolicySkipCerts; + policyConstraints.inhibitMappingSkipCerts.data = + (unsigned char *)&inhibitMappingSkipCerts; + + /* translate DER to CERTCertificatePolicyConstraints */ + rv = CERT_DecodePolicyConstraintsExtension + (&policyConstraints, &encodedCertPolicyConstraints); + + PORT_Free(encodedCertPolicyConstraints.data); + + if (rv != SECSuccess) { + PKIX_ERROR + (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED); + } + } + + *pExplicitPolicySkipCerts = explicitPolicySkipCerts; + *pInhibitMappingSkipCerts = inhibitMappingSkipCerts; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy + * DESCRIPTION: + * + * Decodes the contents of the InhibitAnyPolicy extension in the + * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value, + * which is stored at the address "pSkipCerts". If this certificate does + * not have an InhibitAnyPolicy extension, -1 will be stored. + * + * PARAMETERS + * "nssCert" + * Address of the Cert data whose InhibitAnyPolicy extension is to be + * processed. Must be non-NULL. + * "pSkipCerts" + * Address where the SkipCert value from the InhibitAnyPolicy extension + * 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_pl_Cert_DecodeInhibitAnyPolicy( + CERTCertificate *nssCert, + PKIX_Int32 *pSkipCerts, + void *plContext) +{ + CERTCertificateInhibitAny inhibitAny; + SECStatus rv; + SECItem encodedCertInhibitAny; + PKIX_Int32 skipCerts = -1; + + PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy"); + PKIX_NULLCHECK_TWO(nssCert, pSkipCerts); + + /* get InhibitAny as a SECItem */ + PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n"); + rv = CERT_FindCertExtension + (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny); + + if (rv == SECSuccess) { + inhibitAny.inhibitAnySkipCerts.data = + (unsigned char *)&skipCerts; + + /* translate DER to CERTCertificateInhibitAny */ + rv = CERT_DecodeInhibitAnyExtension + (&inhibitAny, &encodedCertInhibitAny); + + PORT_Free(encodedCertInhibitAny.data); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED); + } + } + + *pSkipCerts = skipCerts; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames + * DESCRIPTION: + * + * Retrieves the Subject Alternative Names of the certificate specified by + * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative + * Name extension is not present, NULL is returned at "pNssSubjAltNames". + * If the Subject Alternative Names has not been previously decoded, it is + * decoded here with lock on the "cert" unless the flag "hasLock" indicates + * the lock had been obtained at a higher call level. + * + * PARAMETERS + * "cert" + * Address of the certificate whose Subject Alternative Names extensions + * is retrieved. Must be non-NULL. + * "hasLock" + * Boolean indicates caller has acquired a lock. + * Must be non-NULL. + * "pNssSubjAltNames" + * Address where the returned Subject Alternative Names 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. + */ +static PKIX_Error * +pkix_pl_Cert_GetNssSubjectAltNames( + PKIX_PL_Cert *cert, + PKIX_Boolean hasLock, + CERTGeneralName **pNssSubjAltNames, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + CERTGeneralName *nssOriginalAltName = NULL; + PLArenaPool *arena = NULL; + SECItem altNameExtension = {siBuffer, NULL, 0}; + SECStatus rv = SECFailure; + + PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames"); + PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert); + + nssCert = cert->nssCert; + + if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ + + if (!hasLock) { + PKIX_OBJECT_LOCK(cert); + } + + if ((cert->nssSubjAltNames == NULL) && + (!cert->subjAltNamesAbsent)){ + + PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, + (nssCert, + SEC_OID_X509_SUBJECT_ALT_NAME, + &altNameExtension)); + + if (rv != SECSuccess) { + *pNssSubjAltNames = NULL; + cert->subjAltNamesAbsent = PKIX_TRUE; + goto cleanup; + } + + if (cert->arenaNameConstraints == NULL) { + PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, + (DER_DEFAULT_CHUNKSIZE)); + + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + cert->arenaNameConstraints = arena; + } + + PKIX_PL_NSSCALLRV + (CERT, + nssOriginalAltName, + (CERTGeneralName *) CERT_DecodeAltNameExtension, + (cert->arenaNameConstraints, &altNameExtension)); + + PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data)); + + if (nssOriginalAltName == NULL) { + PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED); + } + cert->nssSubjAltNames = nssOriginalAltName; + + } + + if (!hasLock) { + PKIX_OBJECT_UNLOCK(cert); + } + } + + *pNssSubjAltNames = cert->nssSubjAltNames; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage + * DESCRIPTION: + * + * For each of the ON bit in "requiredExtendedKeyUsages" that represents its + * SECCertUsageEnum type, this function checks "cert"'s certType (extended + * key usage) and key usage with what is required for SECCertUsageEnum type. + * + * PARAMETERS + * "cert" + * Address of the certificate whose Extended Key Usage extensions + * is retrieved. Must be non-NULL. + * "requiredExtendedKeyUsages" + * An unsigned integer, its bit location is ON based on the required key + * usage value representing in SECCertUsageEnum. + * "pPass" + * Address where the return value, indicating key usage check passed, 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 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_pl_Cert_CheckExtendedKeyUsage( + PKIX_PL_Cert *cert, + PKIX_UInt32 requiredExtendedKeyUsages, + PKIX_Boolean *pPass, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *basicConstraints = NULL; + PKIX_UInt32 certType = 0; + PKIX_UInt32 requiredKeyUsage = 0; + PKIX_UInt32 requiredCertType = 0; + PKIX_UInt32 requiredExtendedKeyUsage = 0; + PKIX_UInt32 i; + PKIX_Boolean isCA = PKIX_FALSE; + SECStatus rv = SECFailure; + + PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage"); + PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert); + + *pPass = PKIX_FALSE; + + PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n"); + cert_GetCertType(cert->nssCert); + certType = cert->nssCert->nsCertType; + + PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints + (cert, + &basicConstraints, + plContext), + PKIX_CERTGETBASICCONSTRAINTFAILED); + + if (basicConstraints != NULL) { + PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag + (basicConstraints, &isCA, plContext), + PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); + } + + i = 0; + while (requiredExtendedKeyUsages != 0) { + + /* Find the bit location of the right-most non-zero bit */ + while (requiredExtendedKeyUsages != 0) { + if (((1 << i) & requiredExtendedKeyUsages) != 0) { + requiredExtendedKeyUsage = 1 << i; + break; + } + i++; + } + requiredExtendedKeyUsages ^= requiredExtendedKeyUsage; + + requiredExtendedKeyUsage = i; + + PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage, + (requiredExtendedKeyUsage, + isCA, + &requiredKeyUsage, + &requiredCertType)); + + if (!(certType & requiredCertType)) { + goto cleanup; + } + + PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage, + (cert->nssCert, requiredKeyUsage)); + if (rv != SECSuccess) { + goto cleanup; + } + i++; + + } + + *pPass = PKIX_TRUE; + +cleanup: + PKIX_DECREF(basicConstraints); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the Cert pointed + * to by "cert" and stores it at "pString", where the value of + * "partialString" determines whether a full or partial representation of + * the Cert is stored. + * + * PARAMETERS + * "cert" + * Address of Cert whose string representation is desired. + * Must be non-NULL. + * "partialString" + * Boolean indicating whether a partial Cert representation is desired. + * "pString" + * 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 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_pl_Cert_ToString_Helper( + PKIX_PL_Cert *cert, + PKIX_Boolean partialString, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *certString = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_UInt32 certVersion; + PKIX_PL_BigInt *certSN = NULL; + PKIX_PL_String *certSNString = NULL; + PKIX_PL_X500Name *certIssuer = NULL; + PKIX_PL_String *certIssuerString = NULL; + PKIX_PL_X500Name *certSubject = NULL; + PKIX_PL_String *certSubjectString = NULL; + PKIX_PL_String *notBeforeString = NULL; + PKIX_PL_String *notAfterString = NULL; + PKIX_List *subjAltNames = NULL; + PKIX_PL_String *subjAltNamesString = NULL; + PKIX_PL_ByteArray *authKeyId = NULL; + PKIX_PL_String *authKeyIdString = NULL; + PKIX_PL_ByteArray *subjKeyId = NULL; + PKIX_PL_String *subjKeyIdString = NULL; + PKIX_PL_PublicKey *nssPubKey = NULL; + PKIX_PL_String *nssPubKeyString = NULL; + PKIX_List *critExtOIDs = NULL; + PKIX_PL_String *critExtOIDsString = NULL; + PKIX_List *extKeyUsages = NULL; + PKIX_PL_String *extKeyUsagesString = NULL; + PKIX_PL_CertBasicConstraints *basicConstraint = NULL; + PKIX_PL_String *certBasicConstraintsString = NULL; + PKIX_List *policyInfo = NULL; + PKIX_PL_String *certPolicyInfoString = NULL; + PKIX_List *certPolicyMappings = NULL; + PKIX_PL_String *certPolicyMappingsString = NULL; + PKIX_Int32 certExplicitPolicy = 0; + PKIX_Int32 certInhibitMapping = 0; + PKIX_Int32 certInhibitAnyPolicy = 0; + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + PKIX_PL_String *nameConstraintsString = NULL; + PKIX_List *authorityInfoAccess = NULL; + PKIX_PL_String *authorityInfoAccessString = NULL; + PKIX_List *subjectInfoAccess = NULL; + PKIX_PL_String *subjectInfoAccessString = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString); + + /* + * XXX Add to this format as certificate components are developed. + */ + + if (partialString){ + asciiFormat = + "\t[Issuer: %s\n" + "\t Subject: %s]"; + } else { + asciiFormat = + "[\n" + "\tVersion: v%d\n" + "\tSerialNumber: %s\n" + "\tIssuer: %s\n" + "\tSubject: %s\n" + "\tValidity: [From: %s\n" + "\t To: %s]\n" + "\tSubjectAltNames: %s\n" + "\tAuthorityKeyId: %s\n" + "\tSubjectKeyId: %s\n" + "\tSubjPubKeyAlgId: %s\n" + "\tCritExtOIDs: %s\n" + "\tExtKeyUsages: %s\n" + "\tBasicConstraint: %s\n" + "\tCertPolicyInfo: %s\n" + "\tPolicyMappings: %s\n" + "\tExplicitPolicy: %d\n" + "\tInhibitMapping: %d\n" + "\tInhibitAnyPolicy:%d\n" + "\tNameConstraints: %s\n" + "\tAuthorityInfoAccess: %s\n" + "\tSubjectInfoAccess: %s\n" + "\tCacheFlag: %d\n" + "]\n"; + } + + + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + /* Issuer */ + PKIX_CHECK(PKIX_PL_Cert_GetIssuer + (cert, &certIssuer, plContext), + PKIX_CERTGETISSUERFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext), + PKIX_X500NAMETOSTRINGFAILED); + + /* Subject */ + PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext), + PKIX_CERTGETSUBJECTFAILED); + + PKIX_TOSTRING(certSubject, &certSubjectString, plContext, + PKIX_X500NAMETOSTRINGFAILED); + + if (partialString){ + PKIX_CHECK(PKIX_PL_Sprintf + (&certString, + plContext, + formatString, + certIssuerString, + certSubjectString), + PKIX_SPRINTFFAILED); + + *pString = certString; + goto cleanup; + } + + /* Version */ + PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext), + PKIX_CERTGETVERSIONFAILED); + + /* SerialNumber */ + PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext), + PKIX_CERTGETSERIALNUMBERFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)certSN, &certSNString, plContext), + PKIX_BIGINTTOSTRINGFAILED); + + /* Validity: NotBefore */ + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&(cert->nssCert->validity.notBefore), + ¬BeforeString, + plContext), + PKIX_DATETOSTRINGHELPERFAILED); + + /* Validity: NotAfter */ + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&(cert->nssCert->validity.notAfter), + ¬AfterString, + plContext), + PKIX_DATETOSTRINGHELPERFAILED); + + /* SubjectAltNames */ + PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames + (cert, &subjAltNames, plContext), + PKIX_CERTGETSUBJECTALTNAMESFAILED); + + PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* AuthorityKeyIdentifier */ + PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier + (cert, &authKeyId, plContext), + PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); + + PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext, + PKIX_BYTEARRAYTOSTRINGFAILED); + + /* SubjectKeyIdentifier */ + PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier + (cert, &subjKeyId, plContext), + PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); + + PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext, + PKIX_BYTEARRAYTOSTRINGFAILED); + + /* SubjectPublicKey */ + PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey + (cert, &nssPubKey, plContext), + PKIX_CERTGETSUBJECTPUBLICKEYFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext), + PKIX_PUBLICKEYTOSTRINGFAILED); + + /* CriticalExtensionOIDs */ + PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs + (cert, &critExtOIDs, plContext), + PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); + + PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* ExtendedKeyUsages */ + PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage + (cert, &extKeyUsages, plContext), + PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); + + PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* CertBasicConstraints */ + PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints + (cert, &basicConstraint, plContext), + PKIX_CERTGETBASICCONSTRAINTSFAILED); + + PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext, + PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED); + + /* CertPolicyInfo */ + PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation + (cert, &policyInfo, plContext), + PKIX_CERTGETPOLICYINFORMATIONFAILED); + + PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* Advanced Policies */ + PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings + (cert, &certPolicyMappings, plContext), + PKIX_CERTGETPOLICYMAPPINGSFAILED); + + PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy + (cert, &certExplicitPolicy, plContext), + PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited + (cert, &certInhibitMapping, plContext), + PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy + (cert, &certInhibitAnyPolicy, plContext), + PKIX_CERTGETINHIBITANYPOLICYFAILED); + + /* Name Constraints */ + PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints + (cert, &nameConstraints, plContext), + PKIX_CERTGETNAMECONSTRAINTSFAILED); + + PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* Authority Information Access */ + PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess + (cert, &authorityInfoAccess, plContext), + PKIX_CERTGETAUTHORITYINFOACCESSFAILED); + + PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* Subject Information Access */ + PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess + (cert, &subjectInfoAccess, plContext), + PKIX_CERTGETSUBJECTINFOACCESSFAILED); + + PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&certString, + plContext, + formatString, + certVersion + 1, + certSNString, + certIssuerString, + certSubjectString, + notBeforeString, + notAfterString, + subjAltNamesString, + authKeyIdString, + subjKeyIdString, + nssPubKeyString, + critExtOIDsString, + extKeyUsagesString, + certBasicConstraintsString, + certPolicyInfoString, + certPolicyMappingsString, + certExplicitPolicy, /* an Int32, not a String */ + certInhibitMapping, /* an Int32, not a String */ + certInhibitAnyPolicy, /* an Int32, not a String */ + nameConstraintsString, + authorityInfoAccessString, + subjectInfoAccessString, + cert->cacheFlag), /* a boolean */ + PKIX_SPRINTFFAILED); + + *pString = certString; + +cleanup: + PKIX_DECREF(certSN); + PKIX_DECREF(certSNString); + PKIX_DECREF(certIssuer); + PKIX_DECREF(certIssuerString); + PKIX_DECREF(certSubject); + PKIX_DECREF(certSubjectString); + PKIX_DECREF(notBeforeString); + PKIX_DECREF(notAfterString); + PKIX_DECREF(subjAltNames); + PKIX_DECREF(subjAltNamesString); + PKIX_DECREF(authKeyId); + PKIX_DECREF(authKeyIdString); + PKIX_DECREF(subjKeyId); + PKIX_DECREF(subjKeyIdString); + PKIX_DECREF(nssPubKey); + PKIX_DECREF(nssPubKeyString); + PKIX_DECREF(critExtOIDs); + PKIX_DECREF(critExtOIDsString); + PKIX_DECREF(extKeyUsages); + PKIX_DECREF(extKeyUsagesString); + PKIX_DECREF(basicConstraint); + PKIX_DECREF(certBasicConstraintsString); + PKIX_DECREF(policyInfo); + PKIX_DECREF(certPolicyInfoString); + PKIX_DECREF(certPolicyMappings); + PKIX_DECREF(certPolicyMappingsString); + PKIX_DECREF(nameConstraints); + PKIX_DECREF(nameConstraintsString); + PKIX_DECREF(authorityInfoAccess); + PKIX_DECREF(authorityInfoAccessString); + PKIX_DECREF(subjectInfoAccess); + PKIX_DECREF(subjectInfoAccessString); + PKIX_DECREF(formatString); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Cert_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Cert *cert = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), + PKIX_OBJECTNOTCERT); + + cert = (PKIX_PL_Cert*)object; + + PKIX_DECREF(cert->subject); + PKIX_DECREF(cert->issuer); + PKIX_DECREF(cert->subjAltNames); + PKIX_DECREF(cert->publicKeyAlgId); + PKIX_DECREF(cert->publicKey); + PKIX_DECREF(cert->serialNumber); + PKIX_DECREF(cert->critExtOids); + PKIX_DECREF(cert->authKeyId); + PKIX_DECREF(cert->subjKeyId); + PKIX_DECREF(cert->extKeyUsages); + PKIX_DECREF(cert->certBasicConstraints); + PKIX_DECREF(cert->certPolicyInfos); + PKIX_DECREF(cert->certPolicyMappings); + PKIX_DECREF(cert->nameConstraints); + PKIX_DECREF(cert->store); + PKIX_DECREF(cert->authorityInfoAccess); + PKIX_DECREF(cert->subjectInfoAccess); + PKIX_DECREF(cert->crldpList); + + if (cert->arenaNameConstraints){ + /* This arena was allocated for SubjectAltNames */ + PKIX_PL_NSSCALL(CERT, PORT_FreeArena, + (cert->arenaNameConstraints, PR_FALSE)); + + cert->arenaNameConstraints = NULL; + cert->nssSubjAltNames = NULL; + } + + CERT_DestroyCertificate(cert->nssCert); + cert->nssCert = NULL; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Cert_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *certString = NULL; + PKIX_PL_Cert *pkixCert = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), + PKIX_OBJECTNOTCERT); + + pkixCert = (PKIX_PL_Cert *)object; + + PKIX_CHECK(pkix_pl_Cert_ToString_Helper + (pkixCert, PKIX_FALSE, &certString, plContext), + PKIX_CERTTOSTRINGHELPERFAILED); + + *pString = certString; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Cert_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_Cert *pkixCert = NULL; + CERTCertificate *nssCert = NULL; + unsigned char *derBytes = NULL; + PKIX_UInt32 derLength; + PKIX_UInt32 certHash; + + PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext), + PKIX_OBJECTNOTCERT); + + pkixCert = (PKIX_PL_Cert *)object; + + nssCert = pkixCert->nssCert; + derBytes = (nssCert->derCert).data; + derLength = (nssCert->derCert).len; + + PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext), + PKIX_HASHFAILED); + + *pHashcode = certHash; + +cleanup: + PKIX_RETURN(CERT); +} + + +/* + * FUNCTION: pkix_pl_Cert_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Cert_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + CERTCertificate *firstCert = NULL; + CERTCertificate *secondCert = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + + PKIX_ENTER(CERT, "pkix_pl_Cert_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a Cert */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERT); + + /* + * Since we know firstObject is a Cert, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a Cert, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CERT_TYPE) goto cleanup; + + firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert; + secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert; + + PKIX_NULLCHECK_TWO(firstCert, secondCert); + + /* CERT_CompareCerts does byte comparison on DER encodings of certs */ + PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n"); + cmpResult = CERT_CompareCerts(firstCert, secondCert); + + *pResult = cmpResult; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_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_pl_Cert_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf"); + + entry.description = "Cert"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_Cert); + entry.destructor = pkix_pl_Cert_Destroy; + entry.equalsFunction = pkix_pl_Cert_Equals; + entry.hashcodeFunction = pkix_pl_Cert_Hashcode; + entry.toStringFunction = pkix_pl_Cert_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERT_TYPE] = entry; + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_CreateWithNSSCert + * DESCRIPTION: + * + * Creates a new certificate using the CERTCertificate pointed to by "nssCert" + * and stores it at "pCert". Once created, a Cert is immutable. + * + * This function is primarily used as a convenience function for the + * performance tests that have easy access to a CERTCertificate. + * + * PARAMETERS: + * "nssCert" + * Address of CERTCertificate representing the NSS certificate. + * Must be non-NULL. + * "pCert" + * 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 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_pl_Cert_CreateWithNSSCert( + CERTCertificate *nssCert, + PKIX_PL_Cert **pCert, + void *plContext) +{ + PKIX_PL_Cert *cert = NULL; + + PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert"); + PKIX_NULLCHECK_TWO(pCert, nssCert); + + /* create a PKIX_PL_Cert object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERT_TYPE, + sizeof (PKIX_PL_Cert), + (PKIX_PL_Object **)&cert, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* populate the nssCert field */ + cert->nssCert = nssCert; + + /* initialize remaining fields */ + /* + * Fields ending with Absent are initialized to PKIX_FALSE so that the + * first time we need the value we will look for it. If we find it is + * actually absent, the flag will at that time be set to PKIX_TRUE to + * prevent searching for it later. + * Fields ending with Processed are those where a value is defined + * for the Absent case, and a value of zero is possible. When the + * flag is still true we have to look for the field, set the default + * value if necessary, and set the Processed flag to PKIX_TRUE. + */ + cert->subject = NULL; + cert->issuer = NULL; + cert->subjAltNames = NULL; + cert->subjAltNamesAbsent = PKIX_FALSE; + cert->publicKeyAlgId = NULL; + cert->publicKey = NULL; + cert->serialNumber = NULL; + cert->critExtOids = NULL; + cert->subjKeyId = NULL; + cert->subjKeyIdAbsent = PKIX_FALSE; + cert->authKeyId = NULL; + cert->authKeyIdAbsent = PKIX_FALSE; + cert->extKeyUsages = NULL; + cert->extKeyUsagesAbsent = PKIX_FALSE; + cert->certBasicConstraints = NULL; + cert->basicConstraintsAbsent = PKIX_FALSE; + cert->certPolicyInfos = NULL; + cert->policyInfoAbsent = PKIX_FALSE; + cert->policyMappingsAbsent = PKIX_FALSE; + cert->certPolicyMappings = NULL; + cert->policyConstraintsProcessed = PKIX_FALSE; + cert->policyConstraintsExplicitPolicySkipCerts = 0; + cert->policyConstraintsInhibitMappingSkipCerts = 0; + cert->inhibitAnyPolicyProcessed = PKIX_FALSE; + cert->inhibitAnySkipCerts = 0; + cert->nameConstraints = NULL; + cert->nameConstraintsAbsent = PKIX_FALSE; + cert->arenaNameConstraints = NULL; + cert->nssSubjAltNames = NULL; + cert->cacheFlag = PKIX_FALSE; + cert->store = NULL; + cert->authorityInfoAccess = NULL; + cert->subjectInfoAccess = NULL; + cert->isUserTrustAnchor = PKIX_FALSE; + cert->crldpList = NULL; + + *pCert = cert; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_pl_Cert_CreateToList + * DESCRIPTION: + * + * Creates a new certificate using the DER-encoding pointed to by "derCertItem" + * and appends it to the list pointed to by "certList". If Cert creation fails, + * the function returns with certList unchanged, but any decoding Error is + * discarded. + * + * PARAMETERS: + * "derCertItem" + * Address of SECItem containing the DER representation of a certificate. + * Must be non-NULL. + * "certList" + * Address of List to which the Cert will be appended, if successfully + * created. May be empty, but 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_pl_Cert_CreateToList( + SECItem *derCertItem, + PKIX_List *certList, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + PKIX_PL_Cert *cert = NULL; + CERTCertDBHandle *handle; + + PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList"); + PKIX_NULLCHECK_TWO(derCertItem, certList); + + handle = CERT_GetDefaultCertDB(); + nssCert = CERT_NewTempCertificate(handle, derCertItem, + /* nickname */ NULL, + /* isPerm */ PR_FALSE, + /* copyDer */ PR_TRUE); + if (!nssCert) { + goto cleanup; + } + + PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert + (nssCert, &cert, plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); + + nssCert = NULL; + + PKIX_CHECK(PKIX_List_AppendItem + (certList, (PKIX_PL_Object *) cert, plContext), + PKIX_LISTAPPENDITEMFAILED); + +cleanup: + if (nssCert) { + CERT_DestroyCertificate(nssCert); + } + + PKIX_DECREF(cert); + PKIX_RETURN(CERT); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h) + * XXX We may want to cache the cert after parsing it, so it can be reused + * XXX Are the NSS/NSPR functions thread safe + */ +PKIX_Error * +PKIX_PL_Cert_Create( + PKIX_PL_ByteArray *byteArray, + PKIX_PL_Cert **pCert, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + SECItem *derCertItem = NULL; + void *derBytes = NULL; + PKIX_UInt32 derLength; + PKIX_PL_Cert *cert = NULL; + CERTCertDBHandle *handle; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_Create"); + PKIX_NULLCHECK_TWO(pCert, byteArray); + + PKIX_CHECK(PKIX_PL_ByteArray_GetPointer + (byteArray, &derBytes, plContext), + PKIX_BYTEARRAYGETPOINTERFAILED); + + PKIX_CHECK(PKIX_PL_ByteArray_GetLength + (byteArray, &derLength, plContext), + PKIX_BYTEARRAYGETLENGTHFAILED); + + derCertItem = SECITEM_AllocItem(NULL, NULL, derLength); + if (derCertItem == NULL){ + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + (void) PORT_Memcpy(derCertItem->data, derBytes, derLength); + + /* + * setting copyDER to true forces NSS to make its own copy of the DER, + * allowing us to free our copy without worrying about whether NSS + * is still using it + */ + handle = CERT_GetDefaultCertDB(); + nssCert = CERT_NewTempCertificate(handle, derCertItem, + /* nickname */ NULL, + /* isPerm */ PR_FALSE, + /* copyDer */ PR_TRUE); + if (!nssCert){ + PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED); + } + + PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert + (nssCert, &cert, plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); + + *pCert = cert; + +cleanup: + if (derCertItem){ + SECITEM_FreeItem(derCertItem, PKIX_TRUE); + } + + if (nssCert && PKIX_ERROR_RECEIVED){ + PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); + CERT_DestroyCertificate(nssCert); + nssCert = NULL; + } + + PKIX_FREE(derBytes); + PKIX_RETURN(CERT); +} + + +/* + * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_CreateFromCERTCertificate( + const CERTCertificate *nssCert, + PKIX_PL_Cert **pCert, + void *plContext) +{ + void *buf = NULL; + PKIX_UInt32 len; + PKIX_PL_ByteArray *byteArray = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert"); + PKIX_NULLCHECK_TWO(pCert, nssCert); + + buf = (void*)nssCert->derCert.data; + len = nssCert->derCert.len; + + PKIX_CHECK( + PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext), + PKIX_BYTEARRAYCREATEFAILED); + + PKIX_CHECK( + PKIX_PL_Cert_Create(byteArray, pCert, plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); + +#ifdef PKIX_UNDEF + /* will be tested and used as a patch for bug 391612 */ + nssCert = CERT_DupCertificate(nssInCert); + + PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert + (nssCert, &cert, plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); +#endif /* PKIX_UNDEF */ + +cleanup: + +#ifdef PKIX_UNDEF + if (nssCert && PKIX_ERROR_RECEIVED){ + PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n"); + CERT_DestroyCertificate(nssCert); + nssCert = NULL; + } +#endif /* PKIX_UNDEF */ + + PKIX_DECREF(byteArray); + PKIX_RETURN(CERT); +} + + +/* + * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetVersion( + PKIX_PL_Cert *cert, + PKIX_UInt32 *pVersion, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + PKIX_UInt32 myVersion = 0; /* v1 */ + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion); + + nssCert = cert->nssCert; + if (nssCert->version.len != 0) { + myVersion = *(nssCert->version.data); + } + + if (myVersion > 2){ + PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3); + } + + *pVersion = myVersion; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSerialNumber( + PKIX_PL_Cert *cert, + PKIX_PL_BigInt **pSerialNumber, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + SECItem serialNumItem; + PKIX_PL_BigInt *serialNumber = NULL; + char *bytes = NULL; + PKIX_UInt32 length; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber); + + if (cert->serialNumber == NULL){ + + PKIX_OBJECT_LOCK(cert); + + if (cert->serialNumber == NULL){ + + nssCert = cert->nssCert; + serialNumItem = nssCert->serialNumber; + + length = serialNumItem.len; + bytes = (char *)serialNumItem.data; + + PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes + (bytes, length, &serialNumber, plContext), + PKIX_BIGINTCREATEWITHBYTESFAILED); + + /* save a cached copy in case it is asked for again */ + cert->serialNumber = serialNumber; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->serialNumber); + *pSerialNumber = cert->serialNumber; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubject( + PKIX_PL_Cert *cert, + PKIX_PL_X500Name **pCertSubject, + void *plContext) +{ + PKIX_PL_X500Name *pkixSubject = NULL; + CERTName *subjName = NULL; + SECItem *derSubjName = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject); + + /* if we don't have a cached copy from before, we create one */ + if (cert->subject == NULL){ + + PKIX_OBJECT_LOCK(cert); + + if (cert->subject == NULL){ + + subjName = &cert->nssCert->subject; + derSubjName = &cert->nssCert->derSubject; + + /* if there is no subject name */ + if (derSubjName->data == NULL) { + + pkixSubject = NULL; + + } else { + PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName + (derSubjName, subjName, &pkixSubject, + plContext), + PKIX_X500NAMECREATEFROMCERTNAMEFAILED); + + } + /* save a cached copy in case it is asked for again */ + cert->subject = pkixSubject; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->subject); + *pCertSubject = cert->subject; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetIssuer( + PKIX_PL_Cert *cert, + PKIX_PL_X500Name **pCertIssuer, + void *plContext) +{ + PKIX_PL_X500Name *pkixIssuer = NULL; + SECItem *derIssuerName = NULL; + CERTName *issuerName = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer); + + /* if we don't have a cached copy from before, we create one */ + if (cert->issuer == NULL){ + + PKIX_OBJECT_LOCK(cert); + + if (cert->issuer == NULL){ + + issuerName = &cert->nssCert->issuer; + derIssuerName = &cert->nssCert->derIssuer; + + /* if there is no subject name */ + PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName + (derIssuerName, issuerName, + &pkixIssuer, plContext), + PKIX_X500NAMECREATEFROMCERTNAMEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->issuer = pkixIssuer; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->issuer); + *pCertIssuer = cert->issuer; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubjectAltNames( + PKIX_PL_Cert *cert, + PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + PKIX_PL_GeneralName *pkixAltName = NULL; + PKIX_List *altNamesList = NULL; + + CERTGeneralName *nssOriginalAltName = NULL; + CERTGeneralName *nssTempAltName = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames"); + PKIX_NULLCHECK_TWO(cert, pSubjectAltNames); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){ + + PKIX_OBJECT_LOCK(cert); + + if ((cert->subjAltNames == NULL) && + (!cert->subjAltNamesAbsent)){ + + PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames + (cert, + PKIX_TRUE, + &nssOriginalAltName, + plContext), + PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); + + if (nssOriginalAltName == NULL) { + cert->subjAltNamesAbsent = PKIX_TRUE; + pSubjectAltNames = NULL; + goto cleanup; + } + + nssTempAltName = nssOriginalAltName; + + PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext), + PKIX_LISTCREATEFAILED); + + do { + PKIX_CHECK(pkix_pl_GeneralName_Create + (nssTempAltName, &pkixAltName, plContext), + PKIX_GENERALNAMECREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (altNamesList, + (PKIX_PL_Object *)pkixAltName, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(pkixAltName); + + PKIX_CERT_DEBUG + ("\t\tCalling CERT_GetNextGeneralName).\n"); + nssTempAltName = CERT_GetNextGeneralName + (nssTempAltName); + + } while (nssTempAltName != nssOriginalAltName); + + /* save a cached copy in case it is asked for again */ + cert->subjAltNames = altNamesList; + PKIX_CHECK(PKIX_List_SetImmutable + (cert->subjAltNames, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->subjAltNames); + + *pSubjectAltNames = cert->subjAltNames; + +cleanup: + PKIX_DECREF(pkixAltName); + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(altNamesList); + } + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetAllSubjectNames( + PKIX_PL_Cert *cert, + PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */ + void *plContext) +{ + CERTGeneralName *nssOriginalSubjectName = NULL; + CERTGeneralName *nssTempSubjectName = NULL; + PKIX_List *allSubjectNames = NULL; + PKIX_PL_GeneralName *pkixSubjectName = NULL; + PLArenaPool *arena = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames); + + + if (cert->nssCert->subjectName == NULL){ + /* if there is no subject DN, just get altnames */ + + PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames + (cert, + PKIX_FALSE, /* hasLock */ + &nssOriginalSubjectName, + plContext), + PKIX_CERTGETNSSSUBJECTALTNAMESFAILED); + + } else { /* get subject DN and altnames */ + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + /* This NSS call returns both Subject and Subject Alt Names */ + PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n"); + nssOriginalSubjectName = + CERT_GetCertificateNames(cert->nssCert, arena); + } + + if (nssOriginalSubjectName == NULL) { + pAllSubjectNames = NULL; + goto cleanup; + } + + nssTempSubjectName = nssOriginalSubjectName; + + PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext), + PKIX_LISTCREATEFAILED); + + do { + PKIX_CHECK(pkix_pl_GeneralName_Create + (nssTempSubjectName, &pkixSubjectName, plContext), + PKIX_GENERALNAMECREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (allSubjectNames, + (PKIX_PL_Object *)pkixSubjectName, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(pkixSubjectName); + + PKIX_CERT_DEBUG + ("\t\tCalling CERT_GetNextGeneralName).\n"); + nssTempSubjectName = CERT_GetNextGeneralName + (nssTempSubjectName); + } while (nssTempSubjectName != nssOriginalSubjectName); + + *pAllSubjectNames = allSubjectNames; + +cleanup: + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(allSubjectNames); + } + + if (arena){ + PORT_FreeArena(arena, PR_FALSE); + } + PKIX_DECREF(pkixSubjectName); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubjectPublicKeyAlgId( + PKIX_PL_Cert *cert, + PKIX_PL_OID **pSubjKeyAlgId, + void *plContext) +{ + PKIX_PL_OID *pubKeyAlgId = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId); + + /* if we don't have a cached copy from before, we create one */ + if (cert->publicKeyAlgId == NULL){ + PKIX_OBJECT_LOCK(cert); + if (cert->publicKeyAlgId == NULL){ + CERTCertificate *nssCert = cert->nssCert; + SECAlgorithmID *algorithm; + SECItem *algBytes; + + algorithm = &nssCert->subjectPublicKeyInfo.algorithm; + algBytes = &algorithm->algorithm; + if (!algBytes->data || !algBytes->len) { + PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0); + } + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (algBytes, &pubKeyAlgId, plContext), + PKIX_OIDCREATEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->publicKeyAlgId = pubKeyAlgId; + pubKeyAlgId = NULL; + } + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->publicKeyAlgId); + *pSubjKeyAlgId = cert->publicKeyAlgId; + +cleanup: + PKIX_DECREF(pubKeyAlgId); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubjectPublicKey( + PKIX_PL_Cert *cert, + PKIX_PL_PublicKey **pPublicKey, + void *plContext) +{ + PKIX_PL_PublicKey *pkixPubKey = NULL; + SECStatus rv; + + CERTSubjectPublicKeyInfo *from = NULL; + CERTSubjectPublicKeyInfo *to = NULL; + SECItem *fromItem = NULL; + SECItem *toItem = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey); + + /* if we don't have a cached copy from before, we create one */ + if (cert->publicKey == NULL){ + + PKIX_OBJECT_LOCK(cert); + + if (cert->publicKey == NULL){ + + /* create a PKIX_PL_PublicKey object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_PUBLICKEY_TYPE, + sizeof (PKIX_PL_PublicKey), + (PKIX_PL_Object **)&pkixPubKey, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* initialize fields */ + pkixPubKey->nssSPKI = NULL; + + /* populate the SPKI field */ + PKIX_CHECK(PKIX_PL_Malloc + (sizeof (CERTSubjectPublicKeyInfo), + (void **)&pkixPubKey->nssSPKI, + plContext), + PKIX_MALLOCFAILED); + + to = pkixPubKey->nssSPKI; + from = &cert->nssCert->subjectPublicKeyInfo; + + PKIX_NULLCHECK_TWO(to, from); + + PKIX_CERT_DEBUG + ("\t\tCalling SECOID_CopyAlgorithmID).\n"); + rv = SECOID_CopyAlgorithmID + (NULL, &to->algorithm, &from->algorithm); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED); + } + + /* + * NSS stores the length of subjectPublicKey in bits. + * Therefore, we use that length converted to bytes + * using ((length+7)>>3) before calling PORT_Memcpy + * in order to avoid "read from uninitialized memory" + * errors. + */ + + toItem = &to->subjectPublicKey; + fromItem = &from->subjectPublicKey; + + PKIX_NULLCHECK_TWO(toItem, fromItem); + + toItem->type = fromItem->type; + + toItem->data = + (unsigned char*) PORT_ZAlloc(fromItem->len); + if (!toItem->data){ + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + (void) PORT_Memcpy(toItem->data, + fromItem->data, + (fromItem->len + 7)>>3); + toItem->len = fromItem->len; + + /* save a cached copy in case it is asked for again */ + cert->publicKey = pkixPubKey; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->publicKey); + *pPublicKey = cert->publicKey; + +cleanup: + + if (PKIX_ERROR_RECEIVED && pkixPubKey){ + PKIX_DECREF(pkixPubKey); + cert->publicKey = NULL; + } + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetCriticalExtensionOIDs( + PKIX_PL_Cert *cert, + PKIX_List **pList, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_List *oidsList = NULL; + CERTCertExtension **extensions = NULL; + CERTCertificate *nssCert = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList); + + /* if we don't have a cached copy from before, we create one */ + if (cert->critExtOids == NULL) { + + PKIX_OBJECT_LOCK(cert); + + if (cert->critExtOids == NULL) { + + nssCert = cert->nssCert; + + /* + * ASN.1 for Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + * + */ + + extensions = nssCert->extensions; + + PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs + (extensions, &oidsList, plContext), + PKIX_GETCRITICALEXTENSIONOIDSFAILED); + + /* save a cached copy in case it is asked for again */ + cert->critExtOids = oidsList; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + /* We should return a copy of the List since this list changes */ + PKIX_DUPLICATE(cert->critExtOids, pList, plContext, + PKIX_OBJECTDUPLICATELISTFAILED); + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetAuthorityKeyIdentifier( + PKIX_PL_Cert *cert, + PKIX_PL_ByteArray **pAuthKeyId, + void *plContext) +{ + PKIX_PL_ByteArray *authKeyId = NULL; + CERTCertificate *nssCert = NULL; + CERTAuthKeyID *authKeyIdExtension = NULL; + PLArenaPool *arena = NULL; + SECItem retItem; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ + + PKIX_OBJECT_LOCK(cert); + + if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){ + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + nssCert = cert->nssCert; + + authKeyIdExtension = + CERT_FindAuthKeyIDExten(arena, nssCert); + if (authKeyIdExtension == NULL){ + cert->authKeyIdAbsent = PKIX_TRUE; + *pAuthKeyId = NULL; + goto cleanup; + } + + retItem = authKeyIdExtension->keyID; + + if (retItem.len == 0){ + cert->authKeyIdAbsent = PKIX_TRUE; + *pAuthKeyId = NULL; + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_ByteArray_Create + (retItem.data, + retItem.len, + &authKeyId, + plContext), + PKIX_BYTEARRAYCREATEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->authKeyId = authKeyId; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->authKeyId); + *pAuthKeyId = cert->authKeyId; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + if (arena){ + PORT_FreeArena(arena, PR_FALSE); + } + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubjectKeyIdentifier( + PKIX_PL_Cert *cert, + PKIX_PL_ByteArray **pSubjKeyId, + void *plContext) +{ + PKIX_PL_ByteArray *subjKeyId = NULL; + CERTCertificate *nssCert = NULL; + SECItem *retItem = NULL; + SECStatus status; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ + + PKIX_OBJECT_LOCK(cert); + + if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){ + + retItem = SECITEM_AllocItem(NULL, NULL, 0); + if (retItem == NULL){ + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + nssCert = cert->nssCert; + + status = CERT_FindSubjectKeyIDExtension + (nssCert, retItem); + if (status != SECSuccess) { + cert->subjKeyIdAbsent = PKIX_TRUE; + *pSubjKeyId = NULL; + goto cleanup; + } + + PKIX_CHECK(PKIX_PL_ByteArray_Create + (retItem->data, + retItem->len, + &subjKeyId, + plContext), + PKIX_BYTEARRAYCREATEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->subjKeyId = subjKeyId; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->subjKeyId); + *pSubjKeyId = cert->subjKeyId; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + if (retItem){ + SECITEM_FreeItem(retItem, PKIX_TRUE); + } + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetExtendedKeyUsage( + PKIX_PL_Cert *cert, + PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */ + void *plContext) +{ + CERTOidSequence *extKeyUsage = NULL; + CERTCertificate *nssCert = NULL; + PKIX_PL_OID *pkixOID = NULL; + PKIX_List *oidsList = NULL; + SECItem **oids = NULL; + SECItem encodedExtKeyUsage; + SECStatus rv; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){ + + PKIX_OBJECT_LOCK(cert); + + if ((cert->extKeyUsages == NULL) && + (!cert->extKeyUsagesAbsent)){ + + nssCert = cert->nssCert; + + rv = CERT_FindCertExtension + (nssCert, SEC_OID_X509_EXT_KEY_USAGE, + &encodedExtKeyUsage); + if (rv != SECSuccess){ + cert->extKeyUsagesAbsent = PKIX_TRUE; + *pKeyUsage = NULL; + goto cleanup; + } + + extKeyUsage = + CERT_DecodeOidSequence(&encodedExtKeyUsage); + if (extKeyUsage == NULL){ + PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED); + } + + PORT_Free(encodedExtKeyUsage.data); + + oids = extKeyUsage->oids; + + if (!oids){ + /* no extended key usage extensions found */ + cert->extKeyUsagesAbsent = PKIX_TRUE; + *pKeyUsage = NULL; + goto cleanup; + } + + PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), + PKIX_LISTCREATEFAILED); + + while (*oids){ + SECItem *oid = *oids++; + + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (oid, &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (oidsList, + (PKIX_PL_Object *)pkixOID, + plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(pkixOID); + } + + PKIX_CHECK(PKIX_List_SetImmutable + (oidsList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->extKeyUsages = oidsList; + oidsList = NULL; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->extKeyUsages); + *pKeyUsage = cert->extKeyUsages; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + + PKIX_DECREF(pkixOID); + PKIX_DECREF(oidsList); + CERT_DestroyOidSequence(extKeyUsage); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetBasicConstraints + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetBasicConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertBasicConstraints **pBasicConstraints, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + CERTBasicConstraints nssBasicConstraint; + SECStatus rv; + PKIX_PL_CertBasicConstraints *basic; + PKIX_Int32 pathLen = 0; + PKIX_Boolean isCA = PKIX_FALSE; + enum { + realBC, synthBC, absentBC + } constraintSource = absentBC; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->certBasicConstraints == NULL) && + (!cert->basicConstraintsAbsent)) { + + PKIX_OBJECT_LOCK(cert); + + if ((cert->certBasicConstraints == NULL) && + (!cert->basicConstraintsAbsent)) { + + nssCert = cert->nssCert; + + PKIX_CERT_DEBUG( + "\t\tCalling Cert_FindBasicConstraintExten\n"); + rv = CERT_FindBasicConstraintExten + (nssCert, &nssBasicConstraint); + if (rv == SECSuccess) { + constraintSource = realBC; + } + + if (constraintSource == absentBC) { + /* can we deduce it's a CA and create a + synthetic constraint? + */ + CERTCertTrust trust; + rv = CERT_GetCertTrust(nssCert, &trust); + if (rv == SECSuccess) { + int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA; + if ((trust.sslFlags & anyWantedFlag) + || (trust.emailFlags & anyWantedFlag) + || (trust.objectSigningFlags & anyWantedFlag)) { + + constraintSource = synthBC; + } + } + } + + if (constraintSource == absentBC) { + cert->basicConstraintsAbsent = PKIX_TRUE; + *pBasicConstraints = NULL; + goto cleanup; + } + } + + if (constraintSource == synthBC) { + isCA = PKIX_TRUE; + pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; + } else { + isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE; + + /* The pathLen has meaning only for CAs */ + if (isCA) { + if (CERT_UNLIMITED_PATH_CONSTRAINT == + nssBasicConstraint.pathLenConstraint) { + pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT; + } else { + pathLen = nssBasicConstraint.pathLenConstraint; + } + } + } + + PKIX_CHECK(pkix_pl_CertBasicConstraints_Create + (isCA, pathLen, &basic, plContext), + PKIX_CERTBASICCONSTRAINTSCREATEFAILED); + + /* save a cached copy in case it is asked for again */ + cert->certBasicConstraints = basic; + } + + PKIX_INCREF(cert->certBasicConstraints); + *pBasicConstraints = cert->certBasicConstraints; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyInformation + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetPolicyInformation( + PKIX_PL_Cert *cert, + PKIX_List **pPolicyInfo, + void *plContext) +{ + PKIX_List *policyList = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo); + + /* if we don't have a cached copy from before, we create one */ + if ((cert->certPolicyInfos == NULL) && + (!cert->policyInfoAbsent)) { + + PKIX_OBJECT_LOCK(cert); + + if ((cert->certPolicyInfos == NULL) && + (!cert->policyInfoAbsent)) { + + PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo + (cert->nssCert, &policyList, plContext), + PKIX_CERTDECODEPOLICYINFOFAILED); + + if (!policyList) { + cert->policyInfoAbsent = PKIX_TRUE; + *pPolicyInfo = NULL; + goto cleanup; + } + } + + PKIX_OBJECT_UNLOCK(cert); + + /* save a cached copy in case it is asked for again */ + cert->certPolicyInfos = policyList; + policyList = NULL; + } + + PKIX_INCREF(cert->certPolicyInfos); + *pPolicyInfo = cert->certPolicyInfos; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + + PKIX_DECREF(policyList); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetPolicyMappings( + PKIX_PL_Cert *cert, + PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */ + void *plContext) +{ + PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */ + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings); + + /* if we don't have a cached copy from before, we create one */ + if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) { + + PKIX_OBJECT_LOCK(cert); + + if (!(cert->certPolicyMappings) && + !(cert->policyMappingsAbsent)) { + + PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping + (cert->nssCert, &policyMappings, plContext), + PKIX_CERTDECODEPOLICYMAPPINGFAILED); + + if (!policyMappings) { + cert->policyMappingsAbsent = PKIX_TRUE; + *pPolicyMappings = NULL; + goto cleanup; + } + } + + PKIX_OBJECT_UNLOCK(cert); + + /* save a cached copy in case it is asked for again */ + cert->certPolicyMappings = policyMappings; + policyMappings = NULL; + } + + PKIX_INCREF(cert->certPolicyMappings); + *pPolicyMappings = cert->certPolicyMappings; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + + PKIX_DECREF(policyMappings); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetRequireExplicitPolicy( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext) +{ + PKIX_Int32 explicitPolicySkipCerts = 0; + PKIX_Int32 inhibitMappingSkipCerts = 0; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); + + if (!(cert->policyConstraintsProcessed)) { + PKIX_OBJECT_LOCK(cert); + + if (!(cert->policyConstraintsProcessed)) { + + /* + * If we can't process it now, we probably will be + * unable to process it later. Set the default value. + */ + cert->policyConstraintsProcessed = PKIX_TRUE; + cert->policyConstraintsExplicitPolicySkipCerts = -1; + cert->policyConstraintsInhibitMappingSkipCerts = -1; + + PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints + (cert->nssCert, + &explicitPolicySkipCerts, + &inhibitMappingSkipCerts, + plContext), + PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); + + cert->policyConstraintsExplicitPolicySkipCerts = + explicitPolicySkipCerts; + cert->policyConstraintsInhibitMappingSkipCerts = + inhibitMappingSkipCerts; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetPolicyMappingInhibited( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext) +{ + PKIX_Int32 explicitPolicySkipCerts = 0; + PKIX_Int32 inhibitMappingSkipCerts = 0; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); + + if (!(cert->policyConstraintsProcessed)) { + PKIX_OBJECT_LOCK(cert); + + if (!(cert->policyConstraintsProcessed)) { + + /* + * If we can't process it now, we probably will be + * unable to process it later. Set the default value. + */ + cert->policyConstraintsProcessed = PKIX_TRUE; + cert->policyConstraintsExplicitPolicySkipCerts = -1; + cert->policyConstraintsInhibitMappingSkipCerts = -1; + + PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints + (cert->nssCert, + &explicitPolicySkipCerts, + &inhibitMappingSkipCerts, + plContext), + PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED); + + cert->policyConstraintsExplicitPolicySkipCerts = + explicitPolicySkipCerts; + cert->policyConstraintsInhibitMappingSkipCerts = + inhibitMappingSkipCerts; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetInhibitAnyPolicy( + PKIX_PL_Cert *cert, + PKIX_Int32 *pSkipCerts, + void *plContext) +{ + PKIX_Int32 skipCerts = 0; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts); + + if (!(cert->inhibitAnyPolicyProcessed)) { + + PKIX_OBJECT_LOCK(cert); + + if (!(cert->inhibitAnyPolicyProcessed)) { + + /* + * If we can't process it now, we probably will be + * unable to process it later. Set the default value. + */ + cert->inhibitAnyPolicyProcessed = PKIX_TRUE; + cert->inhibitAnySkipCerts = -1; + + PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy + (cert->nssCert, &skipCerts, plContext), + PKIX_CERTDECODEINHIBITANYPOLICYFAILED); + + cert->inhibitAnySkipCerts = skipCerts; + } + + PKIX_OBJECT_UNLOCK(cert); + } + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + *pSkipCerts = cert->inhibitAnySkipCerts; + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_AreCertPoliciesCritical( + PKIX_PL_Cert *cert, + PKIX_Boolean *pCritical, + void *plContext) +{ + PKIX_Boolean criticality = PKIX_FALSE; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical"); + PKIX_NULLCHECK_TWO(cert, pCritical); + + PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical( + cert, + SEC_OID_X509_CERTIFICATE_POLICIES, + &criticality, + plContext), + PKIX_CERTISEXTENSIONCRITICALFAILED); + + *pCritical = criticality; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_VerifySignature( + PKIX_PL_Cert *cert, + PKIX_PL_PublicKey *pubKey, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + SECKEYPublicKey *nssPubKey = NULL; + CERTSignedData *tbsCert = NULL; + PKIX_PL_Cert *cachedCert = NULL; + PKIX_Error *verifySig = NULL; + PKIX_Error *cachedSig = NULL; + PKIX_Error *checkSig = NULL; + SECStatus status; + PKIX_Boolean certEqual = PKIX_FALSE; + PKIX_Boolean certInHash = PKIX_FALSE; + PKIX_Boolean checkCertSig = PKIX_TRUE; + void* wincx = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey); + + /* if the cert check flag is off, skip the check */ + checkSig = pkix_pl_NssContext_GetCertSignatureCheck( + (PKIX_PL_NssContext *)plContext, &checkCertSig); + if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) { + goto cleanup; + } + + verifySig = PKIX_PL_HashTable_Lookup + (cachedCertSigTable, + (PKIX_PL_Object *) pubKey, + (PKIX_PL_Object **) &cachedCert, + plContext); + + if (cachedCert != NULL && verifySig == NULL) { + /* Cached Signature Table lookup succeed */ + PKIX_EQUALS(cert, cachedCert, &certEqual, plContext, + PKIX_OBJECTEQUALSFAILED); + if (certEqual == PKIX_TRUE) { + goto cleanup; + } + /* Different PubKey may hash to same value, skip add */ + certInHash = PKIX_TRUE; + } + + nssCert = cert->nssCert; + tbsCert = &nssCert->signatureWrap; + + PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n"); + nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); + if (!nssPubKey){ + PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); + } + + PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n"); + + PKIX_CHECK(pkix_pl_NssContext_GetWincx + ((PKIX_PL_NssContext *)plContext, &wincx), + PKIX_NSSCONTEXTGETWINCXFAILED); + + status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx); + + if (status != SECSuccess) { + if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + } + PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); + } + + if (certInHash == PKIX_FALSE) { + cachedSig = PKIX_PL_HashTable_Add + (cachedCertSigTable, + (PKIX_PL_Object *) pubKey, + (PKIX_PL_Object *) cert, + plContext); + + if (cachedSig != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); + } + } + +cleanup: + if (nssPubKey){ + PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n"); + SECKEY_DestroyPublicKey(nssPubKey); + } + + PKIX_DECREF(cachedCert); + PKIX_DECREF(checkSig); + PKIX_DECREF(verifySig); + PKIX_DECREF(cachedSig); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_CheckValidity( + PKIX_PL_Cert *cert, + PKIX_PL_Date *date, + void *plContext) +{ + SECCertTimeValidity val; + PRTime timeToCheck; + PKIX_Boolean allowOverride; + SECCertificateUsage requiredUsages; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity"); + PKIX_NULLCHECK_ONE(cert); + + /* if the caller supplies a date, we use it; else, use current time */ + if (date != NULL){ + PKIX_CHECK(pkix_pl_Date_GetPRTime + (date, &timeToCheck, plContext), + PKIX_DATEGETPRTIMEFAILED); + } else { + timeToCheck = PR_Now(); + } + + requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage; + allowOverride = + (PRBool)((requiredUsages & certificateUsageSSLServer) || + (requiredUsages & certificateUsageSSLServerWithStepUp) || + (requiredUsages & certificateUsageIPsec)); + val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride); + if (val != secCertTimeValid){ + PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED); + } + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetValidityNotAfter( + PKIX_PL_Cert *cert, + PKIX_PL_Date **pDate, + void *plContext) +{ + PRTime prtime; + SECStatus rv = SECFailure; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter"); + PKIX_NULLCHECK_TWO(cert, pDate); + + PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n"); + rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter)); + if (rv != SECSuccess){ + PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); + } + + PKIX_CHECK(pkix_pl_Date_CreateFromPRTime + (prtime, pDate, plContext), + PKIX_DATECREATEFROMPRTIMEFAILED); + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_VerifyCertAndKeyType( + PKIX_PL_Cert *cert, + PKIX_Boolean isChainCert, + void *plContext) +{ + PKIX_PL_CertBasicConstraints *basicConstraints = NULL; + SECCertificateUsage certificateUsage; + SECCertUsage certUsage = 0; + unsigned int requiredKeyUsage; + unsigned int requiredCertType; + unsigned int certType; + SECStatus rv = SECSuccess; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType"); + PKIX_NULLCHECK_TWO(cert, plContext); + + certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; + + /* ensure we obtained a single usage bit only */ + PORT_Assert(!(certificateUsage & (certificateUsage - 1))); + + /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ + while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } + + /* check key usage and netscape cert type */ + cert_GetCertType(cert->nssCert); + certType = cert->nssCert->nsCertType; + if (isChainCert || + (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) { + rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert, + &requiredKeyUsage, + &requiredCertType); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE); + } + } else { + /* use this key usage and cert type for certUsageAnyCA and + * certUsageVerifyCA. */ + requiredKeyUsage = KU_KEY_CERT_SIGN; + requiredCertType = NS_CERT_TYPE_CA; + } + if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { + PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); + } + if (!(certType & requiredCertType)) { + PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED); + } +cleanup: + PKIX_DECREF(basicConstraints); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_VerifyKeyUsage( + PKIX_PL_Cert *cert, + PKIX_UInt32 keyUsage, + void *plContext) +{ + CERTCertificate *nssCert = NULL; + PKIX_UInt32 nssKeyUsage = 0; + SECStatus status; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage"); + PKIX_NULLCHECK_TWO(cert, cert->nssCert); + + nssCert = cert->nssCert; + + /* if cert doesn't have keyUsage extension, all keyUsages are valid */ + if (!nssCert->keyUsagePresent){ + goto cleanup; + } + + if (keyUsage & PKIX_DIGITAL_SIGNATURE){ + nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE; + } + + if (keyUsage & PKIX_NON_REPUDIATION){ + nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION; + } + + if (keyUsage & PKIX_KEY_ENCIPHERMENT){ + nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT; + } + + if (keyUsage & PKIX_DATA_ENCIPHERMENT){ + nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT; + } + + if (keyUsage & PKIX_KEY_AGREEMENT){ + nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT; + } + + if (keyUsage & PKIX_KEY_CERT_SIGN){ + nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN; + } + + if (keyUsage & PKIX_CRL_SIGN){ + nssKeyUsage = nssKeyUsage | KU_CRL_SIGN; + } + + if (keyUsage & PKIX_ENCIPHER_ONLY){ + nssKeyUsage = nssKeyUsage | 0x01; + } + + if (keyUsage & PKIX_DECIPHER_ONLY){ + /* XXX we should support this once it is fixed in NSS */ + PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED); + } + + status = CERT_CheckKeyUsage(nssCert, nssKeyUsage); + if (status != SECSuccess) { + PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); + } + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetNameConstraints + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetNameConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints); + + /* if we don't have a cached copy from before, we create one */ + if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) { + + PKIX_OBJECT_LOCK(cert); + + if (cert->nameConstraints == NULL && + !cert->nameConstraintsAbsent) { + + PKIX_CHECK(pkix_pl_CertNameConstraints_Create + (cert->nssCert, &nameConstraints, plContext), + PKIX_CERTNAMECONSTRAINTSCREATEFAILED); + + if (nameConstraints == NULL) { + cert->nameConstraintsAbsent = PKIX_TRUE; + } + + cert->nameConstraints = nameConstraints; + } + + PKIX_OBJECT_UNLOCK(cert); + + } + + PKIX_INCREF(cert->nameConstraints); + + *pNameConstraints = cert->nameConstraints; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_CheckNameConstraints + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_CheckNameConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean treatCommonNameAsDNSName, + void *plContext) +{ + PKIX_Boolean checkPass = PKIX_TRUE; + CERTGeneralName *nssSubjectNames = NULL; + PLArenaPool *arena = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints"); + PKIX_NULLCHECK_ONE(cert); + + if (nameConstraints != NULL) { + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + /* only check common Name if the usage requires it */ + if (treatCommonNameAsDNSName) { + SECCertificateUsage certificateUsage; + certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; + if ((certificateUsage != certificateUsageSSLServer) && + (certificateUsage != certificateUsageIPsec)) { + treatCommonNameAsDNSName = PKIX_FALSE; + } + } + + /* This NSS call returns Subject Alt Names. If + * treatCommonNameAsDNSName is true, it also returns the + * Subject Common Name + */ + PKIX_CERT_DEBUG + ("\t\tCalling CERT_GetConstrainedCertificateNames\n"); + nssSubjectNames = CERT_GetConstrainedCertificateNames + (cert->nssCert, arena, treatCommonNameAsDNSName); + + PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames + (nssSubjectNames, + nameConstraints, + &checkPass, + plContext), + PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED); + + if (checkPass != PKIX_TRUE) { + PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING); + } + } + +cleanup: + if (arena){ + PORT_FreeArena(arena, PR_FALSE); + } + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_MergeNameConstraints + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_MergeNameConstraints( + PKIX_PL_CertNameConstraints *firstNC, + PKIX_PL_CertNameConstraints *secondNC, + PKIX_PL_CertNameConstraints **pResultNC, + void *plContext) +{ + PKIX_PL_CertNameConstraints *mergedNC = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints"); + PKIX_NULLCHECK_TWO(firstNC, pResultNC); + + if (secondNC == NULL) { + + PKIX_INCREF(firstNC); + *pResultNC = firstNC; + + goto cleanup; + } + + PKIX_CHECK(pkix_pl_CertNameConstraints_Merge + (firstNC, secondNC, &mergedNC, plContext), + PKIX_CERTNAMECONSTRAINTSMERGEFAILED); + + *pResultNC = mergedNC; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * Find out the state of the NSS trust bits for the requested usage. + * Returns SECFailure if the cert is explicitly distrusted. + * Returns SECSuccess if the cert can be used to form a chain (normal case), + * or it is explicitly trusted. The trusted bool is set to true if it is + * explicitly trusted. + */ +static SECStatus +pkix_pl_Cert_GetTrusted(void *plContext, + PKIX_PL_Cert *cert, + PKIX_Boolean *trusted, + PKIX_Boolean isCA) +{ + SECStatus rv; + CERTCertificate *nssCert = NULL; + SECCertUsage certUsage = 0; + SECCertificateUsage certificateUsage; + SECTrustType trustType; + unsigned int trustFlags; + unsigned int requiredFlags; + CERTCertTrust trust; + + *trusted = PKIX_FALSE; + + /* no key usage information */ + if (plContext == NULL) { + return SECSuccess; + } + + certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; + + /* ensure we obtained a single usage bit only */ + PORT_Assert(!(certificateUsage & (certificateUsage - 1))); + + /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ + while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } + + nssCert = cert->nssCert; + + if (!isCA) { + PRBool prTrusted; + unsigned int failedFlags; + rv = cert_CheckLeafTrust(nssCert, certUsage, + &failedFlags, &prTrusted); + *trusted = (PKIX_Boolean) prTrusted; + return rv; + } + rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, + &trustType); + if (rv != SECSuccess) { + return SECSuccess; + } + + rv = CERT_GetCertTrust(nssCert, &trust); + if (rv != SECSuccess) { + return SECSuccess; + } + trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); + /* normally trustTypeNone usages accept any of the given trust bits + * being on as acceptable. If any are distrusted (and none are trusted), + * then we will also distrust the cert */ + if ((trustFlags == 0) && (trustType == trustTypeNone)) { + trustFlags = trust.sslFlags | trust.emailFlags | + trust.objectSigningFlags; + } + if ((trustFlags & requiredFlags) == requiredFlags) { + *trusted = PKIX_TRUE; + return SECSuccess; + } + if ((trustFlags & CERTDB_TERMINAL_RECORD) && + ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) { + return SECFailure; + } + return SECSuccess; +} + +/* + * FUNCTION: PKIX_PL_Cert_IsCertTrusted + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_IsCertTrusted( + PKIX_PL_Cert *cert, + PKIX_PL_TrustAnchorMode trustAnchorMode, + PKIX_Boolean *pTrusted, + void *plContext) +{ + PKIX_CertStore_CheckTrustCallback trustCallback = NULL; + PKIX_Boolean trusted = PKIX_FALSE; + SECStatus rv = SECFailure; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted"); + PKIX_NULLCHECK_TWO(cert, pTrusted); + + /* Call GetTrusted first to see if we are going to distrust the + * certificate */ + rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE); + if (rv != SECSuccess) { + /* Failure means the cert is explicitly distrusted, + * let the next level know not to use it. */ + *pTrusted = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); + } + + if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive || + (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive && + cert->isUserTrustAnchor)) { + /* Use the trust anchor's |trusted| value */ + *pTrusted = cert->isUserTrustAnchor; + goto cleanup; + } + + /* no key usage information or store is not trusted */ + if (plContext == NULL || cert->store == NULL) { + *pTrusted = PKIX_FALSE; + goto cleanup; + } + + PKIX_CHECK(PKIX_CertStore_GetTrustCallback + (cert->store, &trustCallback, plContext), + PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); + + PKIX_CHECK_ONLY_FATAL(trustCallback + (cert->store, cert, &trusted, plContext), + PKIX_CHECKTRUSTCALLBACKFAILED); + + /* allow trust store to override if we can trust the trust + * bits */ + if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) { + *pTrusted = PKIX_FALSE; + goto cleanup; + } + + *pTrusted = trusted; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_IsLeafCertTrusted( + PKIX_PL_Cert *cert, + PKIX_Boolean *pTrusted, + void *plContext) +{ + SECStatus rv; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted"); + PKIX_NULLCHECK_TWO(cert, pTrusted); + + *pTrusted = PKIX_FALSE; + + rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE); + if (rv != SECSuccess) { + /* Failure means the cert is explicitly distrusted, + * let the next level know not to use it. */ + *pTrusted = PKIX_FALSE; + PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED); + } + +cleanup: + PKIX_RETURN(CERT); +} + +/* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */ +PKIX_Error* +PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor"); + PKIX_NULLCHECK_ONE(cert); + + cert->isUserTrustAnchor = PKIX_TRUE; + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetCacheFlag( + PKIX_PL_Cert *cert, + PKIX_Boolean *pCacheFlag, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag"); + PKIX_NULLCHECK_TWO(cert, pCacheFlag); + + *pCacheFlag = cert->cacheFlag; + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_SetCacheFlag( + PKIX_PL_Cert *cert, + PKIX_Boolean cacheFlag, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag"); + PKIX_NULLCHECK_ONE(cert); + + cert->cacheFlag = cacheFlag; + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetTrustCertStore( + PKIX_PL_Cert *cert, + PKIX_CertStore **pTrustCertStore, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore"); + PKIX_NULLCHECK_TWO(cert, pTrustCertStore); + + PKIX_INCREF(cert->store); + *pTrustCertStore = cert->store; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_SetTrustCertStore( + PKIX_PL_Cert *cert, + PKIX_CertStore *trustCertStore, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore"); + PKIX_NULLCHECK_TWO(cert, trustCertStore); + + PKIX_INCREF(trustCertStore); + cert->store = trustCertStore; + +cleanup: + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetAuthorityInfoAccess( + PKIX_PL_Cert *cert, + PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ + void *plContext) +{ + PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */ + SECItem *encodedAIA = NULL; + CERTAuthInfoAccess **aia = NULL; + PLArenaPool *arena = NULL; + SECStatus rv; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList); + + /* if we don't have a cached copy from before, we create one */ + if (cert->authorityInfoAccess == NULL) { + + PKIX_OBJECT_LOCK(cert); + + if (cert->authorityInfoAccess == NULL) { + + PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem, + (NULL, NULL, 0)); + + if (encodedAIA == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension, + (cert->nssCert, + SEC_OID_X509_AUTH_INFO_ACCESS, + encodedAIA)); + + if (rv == SECFailure) { + goto cleanup; + } + + PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena, + (DER_DEFAULT_CHUNKSIZE)); + + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_PL_NSSCALLRV + (CERT, aia, CERT_DecodeAuthInfoAccessExtension, + (arena, encodedAIA)); + + PKIX_CHECK(pkix_pl_InfoAccess_CreateList + (aia, &aiaList, plContext), + PKIX_INFOACCESSCREATELISTFAILED); + + cert->authorityInfoAccess = aiaList; + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->authorityInfoAccess); + + *pAiaList = cert->authorityInfoAccess; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + if (arena != NULL) { + PORT_FreeArena(arena, PR_FALSE); + } + + if (encodedAIA != NULL) { + SECITEM_FreeItem(encodedAIA, PR_TRUE); + } + + PKIX_RETURN(CERT); +} + +/* XXX Following defines belongs to NSS */ +static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x0b}; +#define OI(x) { siDEROID, (unsigned char *)x, sizeof x } + +/* + * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetSubjectInfoAccess( + PKIX_PL_Cert *cert, + PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */ + void *plContext) +{ + PKIX_List *siaList; /* of PKIX_PL_InfoAccess */ + SECItem siaOID = OI(siaOIDString); + SECItem *encodedSubjInfoAccess = NULL; + CERTAuthInfoAccess **subjInfoAccess = NULL; + PLArenaPool *arena = NULL; + SECStatus rv; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList); + + /* XXX + * Codes to deal with SubjectInfoAccess OID should be moved to + * NSS soon. I implemented them here so we don't touch NSS + * source tree, from JP's suggestion. + */ + + /* if we don't have a cached copy from before, we create one */ + if (cert->subjectInfoAccess == NULL) { + + PKIX_OBJECT_LOCK(cert); + + if (cert->subjectInfoAccess == NULL) { + + encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0); + if (encodedSubjInfoAccess == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_CERT_DEBUG + ("\t\tCalling CERT_FindCertExtensionByOID).\n"); + rv = CERT_FindCertExtensionByOID + (cert->nssCert, &siaOID, encodedSubjInfoAccess); + + if (rv == SECFailure) { + goto cleanup; + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + /* XXX + * Decode Subject Information Access - + * since its type is the same as Authority Information + * Access, reuse the call. NSS- change name to avoid + * confusion. + */ + PKIX_CERT_DEBUG + ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n"); + subjInfoAccess = CERT_DecodeAuthInfoAccessExtension + (arena, encodedSubjInfoAccess); + + PKIX_CHECK(pkix_pl_InfoAccess_CreateList + (subjInfoAccess, &siaList, plContext), + PKIX_INFOACCESSCREATELISTFAILED); + + cert->subjectInfoAccess = siaList; + + } + + PKIX_OBJECT_UNLOCK(cert); + } + + PKIX_INCREF(cert->subjectInfoAccess); + *pSiaList = cert->subjectInfoAccess; + +cleanup: + PKIX_OBJECT_UNLOCK(lockedObject); + if (arena != NULL) { + PORT_FreeArena(arena, PR_FALSE); + } + + if (encodedSubjInfoAccess != NULL) { + SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE); + } + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetCrlDp + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetCrlDp( + PKIX_PL_Cert *cert, + PKIX_List **pDpList, + void *plContext) +{ + PKIX_UInt32 dpIndex = 0; + pkix_pl_CrlDp *dp = NULL; + CERTCrlDistributionPoints *dpoints = NULL; + + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp"); + PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList); + + /* if we don't have a cached copy from before, we create one */ + if (cert->crldpList == NULL) { + PKIX_OBJECT_LOCK(cert); + if (cert->crldpList != NULL) { + goto cleanup; + } + PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext), + PKIX_LISTCREATEFAILED); + dpoints = CERT_FindCRLDistributionPoints(cert->nssCert); + if (!dpoints || !dpoints->distPoints) { + goto cleanup; + } + for (;dpoints->distPoints[dpIndex];dpIndex++) { + PKIX_CHECK( + pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex], + &cert->nssCert->issuer, + &dp, plContext), + PKIX_CRLDPCREATEFAILED); + /* Create crldp list in reverse order in attempt to get + * to the whole crl first. */ + PKIX_CHECK( + PKIX_List_InsertItem(cert->crldpList, 0, + (PKIX_PL_Object*)dp, + plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(dp); + } + } +cleanup: + PKIX_INCREF(cert->crldpList); + *pDpList = cert->crldpList; + + PKIX_OBJECT_UNLOCK(lockedObject); + PKIX_DECREF(dp); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: PKIX_PL_Cert_GetCERTCertificate + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Cert_GetCERTCertificate( + PKIX_PL_Cert *cert, + CERTCertificate **pnssCert, + void *plContext) +{ + PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert"); + PKIX_NULLCHECK_TWO(cert, pnssCert); + + *pnssCert = CERT_DupCertificate(cert->nssCert); + + PKIX_RETURN(CERT); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h new file mode 100644 index 0000000000..56fe64228d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h @@ -0,0 +1,107 @@ +/* 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_pl_cert.h + * + * Certificate Object Definitions + * + */ + +#ifndef _PKIX_PL_CERT_H +#define _PKIX_PL_CERT_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_CertStruct { + CERTCertificate *nssCert; /* Must be the first field. The + * cert_NSSCertFromPKIXCert function in + * lib/certhigh/certvfypkix.c depends on + * this. */ + CERTGeneralName *nssSubjAltNames; + PLArenaPool *arenaNameConstraints; + PKIX_PL_X500Name *issuer; + PKIX_PL_X500Name *subject; + PKIX_List *subjAltNames; + PKIX_Boolean subjAltNamesAbsent; + PKIX_PL_OID *publicKeyAlgId; + PKIX_PL_PublicKey *publicKey; + PKIX_PL_BigInt *serialNumber; + PKIX_List *critExtOids; + PKIX_PL_ByteArray *subjKeyId; + PKIX_Boolean subjKeyIdAbsent; + PKIX_PL_ByteArray *authKeyId; + PKIX_Boolean authKeyIdAbsent; + PKIX_List *extKeyUsages; + PKIX_Boolean extKeyUsagesAbsent; + PKIX_PL_CertBasicConstraints *certBasicConstraints; + PKIX_Boolean basicConstraintsAbsent; + PKIX_List *certPolicyInfos; + PKIX_Boolean policyInfoAbsent; + PKIX_Boolean policyMappingsAbsent; + PKIX_List *certPolicyMappings; /* List of PKIX_PL_CertPolicyMap */ + PKIX_Boolean policyConstraintsProcessed; + PKIX_Int32 policyConstraintsExplicitPolicySkipCerts; + PKIX_Int32 policyConstraintsInhibitMappingSkipCerts; + PKIX_Boolean inhibitAnyPolicyProcessed; + PKIX_Int32 inhibitAnySkipCerts; + PKIX_PL_CertNameConstraints *nameConstraints; + PKIX_Boolean nameConstraintsAbsent; + PKIX_Boolean cacheFlag; + PKIX_CertStore *store; + PKIX_List *authorityInfoAccess; /* list of PKIX_PL_InfoAccess */ + PKIX_List *subjectInfoAccess; /* list of PKIX_PL_InfoAccess */ + PKIX_Boolean isUserTrustAnchor; + PKIX_List *crldpList; /* list of CRL DPs based on der in nssCert arena. + * Destruction is needed for pkix object and + * not for undelying der as it is a part + * nssCert arena. */ +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_Cert_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_Cert_CreateWithNSSCert( + CERTCertificate *nssCert, + PKIX_PL_Cert **pCert, + void *plContext); + +PKIX_Error * +pkix_pl_Cert_CreateToList( + SECItem *derCertItem, + PKIX_List *certList, + void *plContext); + +PKIX_Error * +pkix_pl_Cert_CheckSubjectAltNameConstraints( + PKIX_PL_Cert *cert, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean matchAll, + void *plContext); + +PKIX_Error * +pkix_pl_Cert_ToString_Helper( + PKIX_PL_Cert *cert, + PKIX_Boolean partialString, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_pl_Cert_CheckExtendedKeyUsage( + PKIX_PL_Cert *cert, + PKIX_UInt32 requiredExtendedKeyUsages, + PKIX_Boolean *pPass, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_CERT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c new file mode 100644 index 0000000000..a44ac65900 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c @@ -0,0 +1,371 @@ +/* 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_pl_certpolicyinfo.c + * + * CertPolicyInfo Type Functions + * + */ + +#include "pkix_pl_certpolicyinfo.h" + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_Create + * DESCRIPTION: + * + * Creates a new CertPolicyInfo Object using the OID pointed to by "oid" and + * the List of CertPolicyQualifiers pointed to by "qualifiers", and stores it + * at "pObject". If a non-NULL list is provided, the caller is expected to + * have already set it to be immutable. The caller may provide an empty List, + * but a NULL List is preferable so a user does not need to call + * List_GetLength to get the number of qualifiers. + * + * PARAMETERS + * "oid" + * OID of the desired PolicyInfo ID; must be non-NULL + * "qualifiers" + * List of CertPolicyQualifiers; may be NULL or empty + * "pObject" + * 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_pl_CertPolicyInfo_Create( + PKIX_PL_OID *oid, + PKIX_List *qualifiers, + PKIX_PL_CertPolicyInfo **pObject, + void *plContext) +{ + PKIX_PL_CertPolicyInfo *policyInfo = NULL; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Create"); + + PKIX_NULLCHECK_TWO(oid, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYINFO_TYPE, + sizeof (PKIX_PL_CertPolicyInfo), + (PKIX_PL_Object **)&policyInfo, + plContext), + PKIX_COULDNOTCREATECERTPOLICYINFOOBJECT); + + PKIX_INCREF(oid); + policyInfo->cpID = oid; + + PKIX_INCREF(qualifiers); + policyInfo->policyQualifiers = qualifiers; + + *pObject = policyInfo; + policyInfo = NULL; + +cleanup: + PKIX_DECREF(policyInfo); + + PKIX_RETURN(CERTPOLICYINFO); +} + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyInfo_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CertPolicyInfo *certPI = NULL; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYINFO); + + certPI = (PKIX_PL_CertPolicyInfo*)object; + + PKIX_DECREF(certPI->cpID); + PKIX_DECREF(certPI->policyQualifiers); + +cleanup: + + PKIX_RETURN(CERTPOLICYINFO); +} + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyInfo_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_CertPolicyInfo *certPI = NULL; + PKIX_PL_String *oidString = NULL; + PKIX_PL_String *listString = NULL; + PKIX_PL_String *format = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_ToString"); + + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYINFO); + + certPI = (PKIX_PL_CertPolicyInfo *)object; + + PKIX_NULLCHECK_ONE(certPI->cpID); + + PKIX_TOSTRING + (certPI->cpID, + &oidString, + plContext, + PKIX_OIDTOSTRINGFAILED); + + PKIX_TOSTRING + (certPI->policyQualifiers, + &listString, + plContext, + PKIX_LISTTOSTRINGFAILED); + + /* Put them together in the form OID[Qualifiers] */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "%s[%s]", 0, &format, plContext), + PKIX_ERRORINSTRINGCREATE); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, plContext, format, oidString, listString), + PKIX_ERRORINSPRINTF); + + *pString = outString; + +cleanup: + + PKIX_DECREF(oidString); + PKIX_DECREF(listString); + PKIX_DECREF(format); + PKIX_RETURN(CERTPOLICYINFO); +} + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyInfo_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CertPolicyInfo *certPI = NULL; + PKIX_UInt32 oidHash = 0; + PKIX_UInt32 listHash = 0; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Hashcode"); + + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYINFO); + + certPI = (PKIX_PL_CertPolicyInfo *)object; + + PKIX_NULLCHECK_ONE(certPI->cpID); + + PKIX_HASHCODE + (certPI->cpID, + &oidHash, + plContext, + PKIX_ERRORINOIDHASHCODE); + + PKIX_HASHCODE + (certPI->policyQualifiers, + &listHash, + plContext, + PKIX_ERRORINLISTHASHCODE); + + *pHashcode = (31 * oidHash) + listHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYINFO); +} + + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyInfo_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertPolicyInfo *firstCPI = NULL; + PKIX_PL_CertPolicyInfo *secondCPI = NULL; + PKIX_UInt32 secondType = 0; + PKIX_Boolean compare = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CertPolicyInfo */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTPOLICYINFO_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERTPOLICYINFO); + + /* + * Since we know firstObject is a CertPolicyInfo, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a CertPolicyInfo, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CERTPOLICYINFO_TYPE) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + firstCPI = (PKIX_PL_CertPolicyInfo *)firstObject; + secondCPI = (PKIX_PL_CertPolicyInfo *)secondObject; + + /* + * Compare the value of the OID components + */ + + PKIX_NULLCHECK_TWO(firstCPI->cpID, secondCPI->cpID); + + PKIX_EQUALS + (firstCPI->cpID, + secondCPI->cpID, + &compare, + plContext, + PKIX_OIDEQUALSFAILED); + + /* + * If the OIDs did not match, we don't need to + * compare the Lists. If the OIDs did match, + * the return value is the value of the + * List comparison. + */ + if (compare) { + PKIX_EQUALS + (firstCPI->policyQualifiers, + secondCPI->policyQualifiers, + &compare, + plContext, + PKIX_LISTEQUALSFAILED); + } + + *pResult = compare; + +cleanup: + + PKIX_RETURN(CERTPOLICYINFO); +} + +/* + * FUNCTION: pkix_pl_CertPolicyInfo_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTPOLICYINFO_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_pl_CertPolicyInfo_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_RegisterSelf"); + + entry.description = "CertPolicyInfo"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyInfo); + entry.destructor = pkix_pl_CertPolicyInfo_Destroy; + entry.equalsFunction = pkix_pl_CertPolicyInfo_Equals; + entry.hashcodeFunction = pkix_pl_CertPolicyInfo_Hashcode; + entry.toStringFunction = pkix_pl_CertPolicyInfo_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERTPOLICYINFO_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYINFO); +} + +/* --Public-CertPolicyInfo-Functions------------------------- */ + +/* + * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolicyId + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CertPolicyInfo_GetPolicyId( + PKIX_PL_CertPolicyInfo *policyInfo, + PKIX_PL_OID **pPolicyId, + void *plContext) +{ + PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolicyId"); + + PKIX_NULLCHECK_TWO(policyInfo, pPolicyId); + + PKIX_INCREF(policyInfo->cpID); + + *pPolicyId = policyInfo->cpID; + +cleanup: + PKIX_RETURN(CERTPOLICYINFO); +} + +/* + * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolQualifiers + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CertPolicyInfo_GetPolQualifiers( + PKIX_PL_CertPolicyInfo *policyInfo, + PKIX_List **pQuals, + void *plContext) +{ + PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolQualifiers"); + + PKIX_NULLCHECK_TWO(policyInfo, pQuals); + + PKIX_INCREF(policyInfo->policyQualifiers); + + /* + * This List is created in PKIX_PL_Cert_DecodePolicyInfo + * and is set immutable immediately after being created. + */ + *pQuals = policyInfo->policyQualifiers; + +cleanup: + PKIX_RETURN(CERTPOLICYINFO); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h new file mode 100644 index 0000000000..5c324e6cd2 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.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_pl_certpolicyinfo.h + * + * PolicyInfo Type Definitions + * + */ + +#ifndef _PKIX_PL_POLICYINFO_H +#define _PKIX_PL_POLICYINFO_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure reflects the contents of the policy info extension as + * described in Section 4.2.1.5 of RFC3280. + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * PolicyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + */ +struct PKIX_PL_CertPolicyInfoStruct { + PKIX_PL_OID *cpID; + PKIX_List *policyQualifiers; /* LIST of PKIX_PL_CertPolicyQualifier */ +}; + +PKIX_Error * +pkix_pl_CertPolicyInfo_Create( + PKIX_PL_OID *oid, + PKIX_List *qualifiers, + PKIX_PL_CertPolicyInfo **pObject, + void *plContext); + +PKIX_Error * +pkix_pl_CertPolicyInfo_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_POLICYINFO_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c new file mode 100644 index 0000000000..08b1ca9df1 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c @@ -0,0 +1,386 @@ +/* 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_pl_certpolicymap.c + * + * CertPolicyMap Type Functions + * + */ + +#include "pkix_pl_certpolicymap.h" + +/* + * FUNCTION: pkix_pl_CertPolicyMap_Create + * DESCRIPTION: + * + * Creates a new CertPolicyMap Object pairing the OID given by + * "issuerDomainPolicy" with the OID given by "subjectDomainPolicy", and + * stores the result at "pCertPolicyMap". + * + * PARAMETERS + * "issuerDomainPolicy" + * Address of the OID of the IssuerDomainPolicy. Must be non-NULL. + * "subjectDomainPolicy" + * Address of the OID of the SubjectDomainPolicy. Must be non-NULL. + * "pCertPolicyMap" + * Address where CertPolicyMap 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 CertPolicyMap 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_pl_CertPolicyMap_Create( + PKIX_PL_OID *issuerDomainPolicy, + PKIX_PL_OID *subjectDomainPolicy, + PKIX_PL_CertPolicyMap **pCertPolicyMap, + void *plContext) +{ + PKIX_PL_CertPolicyMap *policyMap = NULL; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Create"); + + PKIX_NULLCHECK_THREE + (issuerDomainPolicy, subjectDomainPolicy, pCertPolicyMap); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYMAP_TYPE, + sizeof (PKIX_PL_CertPolicyMap), + (PKIX_PL_Object **)&policyMap, + plContext), + PKIX_COULDNOTCREATECERTPOLICYMAPOBJECT); + + PKIX_INCREF(issuerDomainPolicy); + policyMap->issuerDomainPolicy = issuerDomainPolicy; + + PKIX_INCREF(subjectDomainPolicy); + policyMap->subjectDomainPolicy = subjectDomainPolicy; + + *pCertPolicyMap = policyMap; + policyMap = NULL; + +cleanup: + PKIX_DECREF(policyMap); + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyMap_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CertPolicyMap *certMap = NULL; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYMAP); + + certMap = (PKIX_PL_CertPolicyMap*)object; + + PKIX_DECREF(certMap->issuerDomainPolicy); + PKIX_DECREF(certMap->subjectDomainPolicy); + +cleanup: + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyMap_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_CertPolicyMap *certMap = NULL; + PKIX_PL_String *format = NULL; + PKIX_PL_String *outString = NULL; + PKIX_PL_String *issuerString = NULL; + PKIX_PL_String *subjectString = NULL; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_ToString"); + + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYMAP); + + certMap = (PKIX_PL_CertPolicyMap *)object; + + PKIX_TOSTRING + (certMap->issuerDomainPolicy, + &issuerString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_TOSTRING + (certMap->subjectDomainPolicy, + &subjectString, + plContext, + PKIX_OBJECTTOSTRINGFAILED); + + /* Put them together in the form issuerPolicy=>subjectPolicy */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "%s=>%s", 0, &format, plContext), + PKIX_ERRORINSTRINGCREATE); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, plContext, format, issuerString, subjectString), + PKIX_ERRORINSPRINTF); + + *pString = outString; + +cleanup: + PKIX_DECREF(format); + PKIX_DECREF(issuerString); + PKIX_DECREF(subjectString); + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyMap_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 issuerHash = 0; + PKIX_UInt32 subjectHash = 0; + PKIX_PL_CertPolicyMap *certMap = NULL; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Hashcode"); + + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYMAP); + + certMap = (PKIX_PL_CertPolicyMap *)object; + + PKIX_HASHCODE + (certMap->issuerDomainPolicy, + &issuerHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_HASHCODE + (certMap->subjectDomainPolicy, + &subjectHash, + plContext, + PKIX_OBJECTHASHCODEFAILED); + + *pHashcode = issuerHash*31 + subjectHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyMap_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertPolicyMap *firstCertMap = NULL; + PKIX_PL_CertPolicyMap *secondCertMap = NULL; + PKIX_UInt32 secondType = 0; + PKIX_Boolean compare = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CertPolicyMap */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTPOLICYMAP_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERTPOLICYMAP); + + /* + * Since we know firstObject is a CertPolicyMap, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a CertPolicyMap, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CERTPOLICYMAP_TYPE) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + firstCertMap = (PKIX_PL_CertPolicyMap *)firstObject; + secondCertMap = (PKIX_PL_CertPolicyMap *)secondObject; + + PKIX_EQUALS + (firstCertMap->issuerDomainPolicy, + secondCertMap->issuerDomainPolicy, + &compare, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (compare) { + PKIX_EQUALS + (firstCertMap->subjectDomainPolicy, + secondCertMap->subjectDomainPolicy, + &compare, + plContext, + PKIX_OBJECTEQUALSFAILED); + } + + *pResult = compare; + +cleanup: + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_Duplicate + * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyMap_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_PL_CertPolicyMap *original = NULL; + PKIX_PL_CertPolicyMap *copy = NULL; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Duplicate"); + + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYMAP_TYPE, plContext), + PKIX_OBJECTARGUMENTNOTPOLICYMAP); + + original = (PKIX_PL_CertPolicyMap *)object; + + PKIX_CHECK(pkix_pl_CertPolicyMap_Create + (original->issuerDomainPolicy, + original->subjectDomainPolicy, + ©, + plContext), + PKIX_CERTPOLICYMAPCREATEFAILED); + + *pNewObject = (PKIX_PL_Object *)copy; + +cleanup: + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: pkix_pl_CertPolicyMap_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTPOLICYMAP_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_pl_CertPolicyMap_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_RegisterSelf"); + + entry.description = "CertPolicyMap"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyMap); + entry.destructor = pkix_pl_CertPolicyMap_Destroy; + entry.equalsFunction = pkix_pl_CertPolicyMap_Equals; + entry.hashcodeFunction = pkix_pl_CertPolicyMap_Hashcode; + entry.toStringFunction = pkix_pl_CertPolicyMap_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_pl_CertPolicyMap_Duplicate; + + systemClasses[PKIX_CERTPOLICYMAP_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYMAP); +} + +/* --Public-CertPolicyMap-Functions------------------------- */ + +/* + * FUNCTION: PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy( + PKIX_PL_CertPolicyMap *policyMapping, + PKIX_PL_OID **pIssuerDomainPolicy, + void *plContext) +{ + PKIX_ENTER + (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy"); + + PKIX_NULLCHECK_TWO(policyMapping, pIssuerDomainPolicy); + + PKIX_INCREF(policyMapping->issuerDomainPolicy); + *pIssuerDomainPolicy = policyMapping->issuerDomainPolicy; + +cleanup: + PKIX_RETURN(CERTPOLICYMAP); +} + +/* + * FUNCTION: PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy( + PKIX_PL_CertPolicyMap *policyMapping, + PKIX_PL_OID **pSubjectDomainPolicy, + void *plContext) +{ + PKIX_ENTER + (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy"); + + PKIX_NULLCHECK_TWO(policyMapping, pSubjectDomainPolicy); + + PKIX_INCREF(policyMapping->subjectDomainPolicy); + *pSubjectDomainPolicy = policyMapping->subjectDomainPolicy; + +cleanup: + PKIX_RETURN(CERTPOLICYMAP); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h new file mode 100644 index 0000000000..a03bce2c8c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h @@ -0,0 +1,49 @@ +/* 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_pl_certpolicymap.h + * + * CertPolicyMap Object Definitions + * + */ + +#ifndef _PKIX_PL_CERTPOLICYMAP_H +#define _PKIX_PL_CERTPOLICYMAP_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure reflects the contents of the policy mapping extension as + * described in Section 4.2.1.6 of RFC3280. + * + * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + * issuerDomainPolicy CertPolicyId, + * subjectDomainPolicy CertPolicyId } + * + */ +struct PKIX_PL_CertPolicyMapStruct { + PKIX_PL_OID *issuerDomainPolicy; + PKIX_PL_OID *subjectDomainPolicy; +}; + +PKIX_Error * +pkix_pl_CertPolicyMap_Create( + PKIX_PL_OID *issuerDomainPolicy, + PKIX_PL_OID *subjectDomainPolicy, + PKIX_PL_CertPolicyMap **pObject, + void *plContext); + +PKIX_Error * +pkix_pl_CertPolicyMap_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_CERTPOLICYMAP_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c new file mode 100644 index 0000000000..b57623d269 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c @@ -0,0 +1,365 @@ +/* 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_pl_certpolicyqualifier.c + * + * CertPolicyQualifier Type Functions + * + */ + +#include "pkix_pl_certpolicyqualifier.h" + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_Create + * DESCRIPTION: + * + * Creates a CertPolicyQualifier object with the OID given by "oid" + * and the ByteArray given by "qualifier", and stores it at "pObject". + * + * PARAMETERS + * "oid" + * Address of OID of the desired policyQualifierId; must be non-NULL + * "qualifier" + * Address of ByteArray with the desired value of the qualifier; + * must be non-NULL + * "pObject" + * 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_pl_CertPolicyQualifier_Create( + PKIX_PL_OID *oid, + PKIX_PL_ByteArray *qualifier, + PKIX_PL_CertPolicyQualifier **pObject, + void *plContext) +{ + PKIX_PL_CertPolicyQualifier *qual = NULL; + + PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Create"); + + PKIX_NULLCHECK_THREE(oid, qualifier, pObject); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTPOLICYQUALIFIER_TYPE, + sizeof (PKIX_PL_CertPolicyQualifier), + (PKIX_PL_Object **)&qual, + plContext), + PKIX_COULDNOTCREATECERTPOLICYQUALIFIEROBJECT); + + PKIX_INCREF(oid); + qual->policyQualifierId = oid; + + PKIX_INCREF(qualifier); + qual->qualifier = qualifier; + + *pObject = qual; + qual = NULL; + +cleanup: + PKIX_DECREF(qual); + + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyQualifier_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CertPolicyQualifier *certPQ = NULL; + + PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYQUALIFIER); + + certPQ = (PKIX_PL_CertPolicyQualifier*)object; + + PKIX_DECREF(certPQ->policyQualifierId); + PKIX_DECREF(certPQ->qualifier); + +cleanup: + + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyQualifier_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_CertPolicyQualifier *certPQ = NULL; + char *asciiFormat = "%s:%s"; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *pqIDString = NULL; + PKIX_PL_String *pqValString = NULL; + PKIX_PL_String *outString = NULL; + + PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_ToString"); + + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYQUALIFIER); + + certPQ = (PKIX_PL_CertPolicyQualifier *)object; + + /* + * The policyQualifierId is required. If there is no qualifier, + * we should have a ByteArray of zero length. + */ + PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING(certPQ->policyQualifierId, &pqIDString, plContext, + PKIX_OIDTOSTRINGFAILED); + + PKIX_CHECK(pkix_pl_ByteArray_ToHexString + (certPQ->qualifier, &pqValString, plContext), + PKIX_BYTEARRAYTOHEXSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&outString, plContext, formatString, pqIDString, pqValString), + PKIX_SPRINTFFAILED); + + *pString = outString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(pqIDString); + PKIX_DECREF(pqValString); + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyQualifier_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CertPolicyQualifier *certPQ = NULL; + PKIX_UInt32 cpidHash = 0; + PKIX_UInt32 cpqHash = 0; + + PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext), + PKIX_OBJECTNOTCERTPOLICYQUALIFIER); + + certPQ = (PKIX_PL_CertPolicyQualifier *)object; + + PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier); + + PKIX_HASHCODE(certPQ->policyQualifierId, &cpidHash, plContext, + PKIX_ERRORINOIDHASHCODE); + + PKIX_HASHCODE(certPQ->qualifier, &cpqHash, plContext, + PKIX_ERRORINBYTEARRAYHASHCODE); + + *pHashcode = cpidHash*31 + cpqHash; + +cleanup: + + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertPolicyQualifier_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertPolicyQualifier *firstCPQ = NULL; + PKIX_PL_CertPolicyQualifier *secondCPQ = NULL; + PKIX_UInt32 secondType = 0; + PKIX_Boolean compare = PKIX_FALSE; + + PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CertPolicyQualifier */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERTPOLICYQUALIFIER); + + /* + * Since we know firstObject is a CertPolicyQualifier, + * if both references are identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a CertPolicyQualifier, we + * don't throw an error. We simply return FALSE. + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CERTPOLICYQUALIFIER_TYPE) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + firstCPQ = (PKIX_PL_CertPolicyQualifier *)firstObject; + secondCPQ = (PKIX_PL_CertPolicyQualifier *)secondObject; + + /* + * Compare the value of the OID components + */ + + PKIX_NULLCHECK_TWO + (firstCPQ->policyQualifierId, secondCPQ->policyQualifierId); + + PKIX_EQUALS + (firstCPQ->policyQualifierId, + secondCPQ->policyQualifierId, + &compare, + plContext, + PKIX_OIDEQUALSFAILED); + + /* + * If the OIDs did not match, we don't need to + * compare the ByteArrays. If the OIDs did match, + * the return value is the value of the + * ByteArray comparison. + */ + if (compare) { + PKIX_NULLCHECK_TWO(firstCPQ->qualifier, secondCPQ->qualifier); + + PKIX_EQUALS + (firstCPQ->qualifier, + secondCPQ->qualifier, + &compare, + plContext, + PKIX_BYTEARRAYEQUALSFAILED); + } + + *pResult = compare; + +cleanup: + + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* + * FUNCTION: pkix_pl_CertPolicyQualifier_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTPOLICYQUALIFIER_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_pl_CertPolicyQualifier_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTPOLICYQUALIFIER, + "pkix_pl_CertPolicyQualifier_RegisterSelf"); + + entry.description = "CertPolicyQualifier"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyQualifier); + entry.destructor = pkix_pl_CertPolicyQualifier_Destroy; + entry.equalsFunction = pkix_pl_CertPolicyQualifier_Equals; + entry.hashcodeFunction = pkix_pl_CertPolicyQualifier_Hashcode; + entry.toStringFunction = pkix_pl_CertPolicyQualifier_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERTPOLICYQUALIFIER_TYPE] = entry; + + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* --Public-CertPolicyQualifier-Functions------------------------- */ + +/* + * FUNCTION: PKIX_PL_PolicyQualifier_GetPolicyQualifierId + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PolicyQualifier_GetPolicyQualifierId( + PKIX_PL_CertPolicyQualifier *policyQualifierInfo, + PKIX_PL_OID **pPolicyQualifierId, + void *plContext) +{ + PKIX_ENTER(CERTPOLICYQUALIFIER, + "PKIX_PL_PolicyQualifier_GetPolicyQualifierId"); + + PKIX_NULLCHECK_TWO(policyQualifierInfo, pPolicyQualifierId); + + PKIX_INCREF(policyQualifierInfo->policyQualifierId); + + *pPolicyQualifierId = policyQualifierInfo->policyQualifierId; + +cleanup: + PKIX_RETURN(CERTPOLICYQUALIFIER); +} + +/* + * FUNCTION: PKIX_PL_PolicyQualifier_GetQualifier + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PolicyQualifier_GetQualifier( + PKIX_PL_CertPolicyQualifier *policyQualifierInfo, + PKIX_PL_ByteArray **pQualifier, + void *plContext) +{ + PKIX_ENTER(CERTPOLICYQUALIFIER, "PKIX_PL_PolicyQualifier_GetQualifier"); + + PKIX_NULLCHECK_TWO(policyQualifierInfo, pQualifier); + + PKIX_INCREF(policyQualifierInfo->qualifier); + + *pQualifier = policyQualifierInfo->qualifier; + +cleanup: + PKIX_RETURN(CERTPOLICYQUALIFIER); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h new file mode 100644 index 0000000000..4c6c8a21ba --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h @@ -0,0 +1,52 @@ +/* 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_pl_certpolicyqualifier.h + * + * PolicyQualifier Type Definitions + * + */ + +#ifndef _PKIX_PL_POLICYQUALIFIER_H +#define _PKIX_PL_POLICYQUALIFIER_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure reflects the contents of the policy qualifier extension as + * described in Section 4.2.1.5 of RFC3280. + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * PolicyQualifierId ::= + * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice) + * + */ +struct PKIX_PL_CertPolicyQualifierStruct { + PKIX_PL_OID *policyQualifierId; + PKIX_PL_ByteArray *qualifier; +}; + +PKIX_Error * +pkix_pl_CertPolicyQualifier_Create( + PKIX_PL_OID *oid, + PKIX_PL_ByteArray *qualifierArray, + PKIX_PL_CertPolicyQualifier **pObject, + void *plContext); + +PKIX_Error * +pkix_pl_CertPolicyQualifier_RegisterSelf( + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_POLICYQUALIFIER_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c new file mode 100644 index 0000000000..b83db357ac --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c @@ -0,0 +1,1068 @@ +/* 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_pl_crl.c + * + * CRL Function Definitions + * + */ + +#include "pkix_pl_crl.h" +#include "certxutl.h" + +extern PKIX_PL_HashTable *cachedCrlSigTable; + +/* --Private-CRL-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_CRL_GetVersion + * DESCRIPTION: + * + * Retrieves the version of the CRL pointed to by "crl" and stores it at + * "pVersion". The version number will either be 0 or 1 (corresponding to + * v1 or v2, respectively). + * + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * PARAMETERS: + * "crl" + * Address of CRL whose version is to be stored. Must be non-NULL. + * "pVersion" + * Address where a version 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 CRL 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_pl_CRL_GetVersion( + PKIX_PL_CRL *crl, + PKIX_UInt32 *pVersion, + void *plContext) +{ + PKIX_UInt32 myVersion; + + PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion); + + PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data); + + myVersion = *(crl->nssSignedCrl->crl.version.data); + + if (myVersion > 1) { + PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2); + } + + *pVersion = myVersion; + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_GetCRLNumber( + PKIX_PL_CRL *crl, + PKIX_PL_BigInt **pCrlNumber, + void *plContext) +{ + PKIX_PL_BigInt *crlNumber = NULL; + SECItem nssCrlNumber; + PLArenaPool *arena = NULL; + SECStatus status; + PKIX_UInt32 length = 0; + char *bytes = NULL; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber); + + /* Can call this function only with der been adopted. */ + PORT_Assert(crl->adoptedDerCrl); + + if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { + + PKIX_OBJECT_LOCK(crl); + + if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { + + nssCrlNumber.type = 0; + nssCrlNumber.len = 0; + nssCrlNumber.data = NULL; + + PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n"); + status = CERT_FindCRLNumberExten + (arena, &crl->nssSignedCrl->crl, &nssCrlNumber); + + if (status == SECSuccess) { + /* Get data in bytes then convert to bigint */ + length = nssCrlNumber.len; + bytes = (char *)nssCrlNumber.data; + + PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes + (bytes, length, &crlNumber, plContext), + PKIX_BIGINTCREATEWITHBYTESFAILED); + + /* arena release does the job + PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n"); + SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE); + */ + crl->crlNumber = crlNumber; + + } else { + + crl->crlNumberAbsent = PKIX_TRUE; + } + } + + PKIX_OBJECT_UNLOCK(crl); + + } + + PKIX_INCREF(crl->crlNumber); + + *pCrlNumber = crl->crlNumber; + +cleanup: + + if (arena){ + PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_GetSignatureAlgId + * + * DESCRIPTION: + * Retrieves a pointer to the OID that represents the signature algorithm of + * the CRL pointed to by "crl" and stores it at "pSignatureAlgId". + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * PARAMETERS: + * "crl" + * Address of CRL whose signature algorithm OID is to be stored. + * Must be non-NULL. + * "pSignatureAlgId" + * 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 CRL 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_pl_CRL_GetSignatureAlgId( + PKIX_PL_CRL *crl, + PKIX_PL_OID **pSignatureAlgId, + void *plContext) +{ + PKIX_PL_OID *signatureAlgId = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId); + + /* if we don't have a cached copy from before, we create one */ + if (crl->signatureAlgId == NULL){ + PKIX_OBJECT_LOCK(crl); + if (crl->signatureAlgId == NULL){ + CERTCrl *nssCrl = &(crl->nssSignedCrl->crl); + SECAlgorithmID *algorithm = &nssCrl->signatureAlg; + SECItem *algBytes = &algorithm->algorithm; + + if (!algBytes->data || !algBytes->len) { + PKIX_ERROR(PKIX_OIDBYTESLENGTH0); + } + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem + (algBytes, &signatureAlgId, plContext), + PKIX_OIDCREATEFAILED); + + /* save a cached copy in case it is asked for again */ + crl->signatureAlgId = signatureAlgId; + signatureAlgId = NULL; + } + PKIX_OBJECT_UNLOCK(crl); + } + PKIX_INCREF(crl->signatureAlgId); + *pSignatureAlgId = crl->signatureAlgId; +cleanup: + PKIX_DECREF(signatureAlgId); + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_GetCRLEntries + * DESCRIPTION: + * + * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to + * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries, + * this functions stores NULL at "pCRLEntries". + * + * PARAMETERS: + * "crl" + * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL. + * "pCRLEntries" + * 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 CRL 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_pl_CRL_GetCRLEntries( + PKIX_PL_CRL *crl, + PKIX_List **pCrlEntries, + void *plContext) +{ + PKIX_List *entryList = NULL; + CERTCrl *nssCrl = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries); + + /* if we don't have a cached copy from before, we create one */ + if (crl->crlEntryList == NULL) { + + PKIX_OBJECT_LOCK(crl); + + if (crl->crlEntryList == NULL){ + + nssCrl = &(crl->nssSignedCrl->crl); + + PKIX_CHECK(pkix_pl_CRLEntry_Create + (nssCrl->entries, &entryList, plContext), + PKIX_CRLENTRYCREATEFAILED); + + PKIX_CHECK(PKIX_List_SetImmutable + (entryList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + crl->crlEntryList = entryList; + } + + PKIX_OBJECT_UNLOCK(crl); + + } + + PKIX_INCREF(crl->crlEntryList); + + *pCrlEntries = crl->crlEntryList; + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRL_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CRL *crl = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), + PKIX_OBJECTNOTCRL); + + crl = (PKIX_PL_CRL*)object; + + PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n"); + if (crl->nssSignedCrl) { + CERT_DestroyCrl(crl->nssSignedCrl); + } + if (crl->adoptedDerCrl) { + SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE); + } + crl->nssSignedCrl = NULL; + crl->adoptedDerCrl = NULL; + crl->crlNumberAbsent = PKIX_FALSE; + + PKIX_DECREF(crl->issuer); + PKIX_DECREF(crl->signatureAlgId); + PKIX_DECREF(crl->crlNumber); + PKIX_DECREF(crl->crlEntryList); + PKIX_DECREF(crl->critExtOids); + if (crl->derGenName) { + SECITEM_FreeItem(crl->derGenName, PR_TRUE); + } + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the CRL pointed + * to by "crl" and stores it at "pString". + * + * PARAMETERS + * "crl" + * Address of CRL whose string representation is desired. + * Must be non-NULL. + * "pString" + * 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 CRL 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_pl_CRL_ToString_Helper( + PKIX_PL_CRL *crl, + PKIX_PL_String **pString, + void *plContext) +{ + char *asciiFormat = NULL; + PKIX_UInt32 crlVersion = 0; + PKIX_PL_X500Name *crlIssuer = NULL; + PKIX_PL_OID *nssSignatureAlgId = NULL; + PKIX_PL_BigInt *crlNumber = NULL; + PKIX_List *crlEntryList = NULL; + PKIX_List *critExtOIDs = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *crlIssuerString = NULL; + PKIX_PL_String *lastUpdateString = NULL; + PKIX_PL_String *nextUpdateString = NULL; + PKIX_PL_String *nssSignatureAlgIdString = NULL; + PKIX_PL_String *crlNumberString = NULL; + PKIX_PL_String *crlEntryListString = NULL; + PKIX_PL_String *critExtOIDsString = NULL; + PKIX_PL_String *crlString = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString); + + asciiFormat = + "[\n" + "\tVersion: v%d\n" + "\tIssuer: %s\n" + "\tUpdate: [Last: %s\n" + "\t Next: %s]\n" + "\tSignatureAlgId: %s\n" + "\tCRL Number : %s\n" + "\n" + "\tEntry List: %s\n" + "\n" + "\tCritExtOIDs: %s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Version */ + PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext), + PKIX_CRLGETVERSIONFAILED); + + /* Issuer */ + PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext), + PKIX_CRLGETISSUERFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext), + PKIX_X500NAMETOSTRINGFAILED); + + /* This update - No Date object created, use nss data directly */ + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&(crl->nssSignedCrl->crl.lastUpdate), + &lastUpdateString, + plContext), + PKIX_DATETOSTRINGHELPERFAILED); + + /* Next update - No Date object created, use nss data directly */ + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&(crl->nssSignedCrl->crl.nextUpdate), + &nextUpdateString, + plContext), + PKIX_DATETOSTRINGHELPERFAILED); + + /* Signature Algorithm Id */ + PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId + (crl, &nssSignatureAlgId, plContext), + PKIX_CRLGETSIGNATUREALGIDFAILED); + + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)nssSignatureAlgId, + &nssSignatureAlgIdString, + plContext), + PKIX_OIDTOSTRINGFAILED); + + /* CRL Number */ + PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber + (crl, &crlNumber, plContext), + PKIX_CRLGETCRLNUMBERFAILED); + + PKIX_TOSTRING(crlNumber, &crlNumberString, plContext, + PKIX_BIGINTTOSTRINGFAILED); + + /* CRL Entries */ + PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext), + PKIX_CRLGETCRLENTRIESFAILED); + + PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* CriticalExtensionOIDs */ + PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs + (crl, &critExtOIDs, plContext), + PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED); + + PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&crlString, + plContext, + formatString, + crlVersion + 1, + crlIssuerString, + lastUpdateString, + nextUpdateString, + nssSignatureAlgIdString, + crlNumberString, + crlEntryListString, + critExtOIDsString), + PKIX_SPRINTFFAILED); + + *pString = crlString; + +cleanup: + + PKIX_DECREF(crlIssuer); + PKIX_DECREF(nssSignatureAlgId); + PKIX_DECREF(crlNumber); + PKIX_DECREF(crlEntryList); + PKIX_DECREF(critExtOIDs); + PKIX_DECREF(crlIssuerString); + PKIX_DECREF(lastUpdateString); + PKIX_DECREF(nextUpdateString); + PKIX_DECREF(nssSignatureAlgIdString); + PKIX_DECREF(crlNumberString); + PKIX_DECREF(crlEntryListString); + PKIX_DECREF(critExtOIDsString); + PKIX_DECREF(formatString); + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRL_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlString = NULL; + PKIX_PL_CRL *crl = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), + PKIX_OBJECTNOTCRL); + + crl = (PKIX_PL_CRL *) object; + + PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext), + PKIX_CRLTOSTRINGHELPERFAILED); + + *pString = crlString; + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRL_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CRL *crl = NULL; + PKIX_UInt32 certHash; + SECItem *crlDer = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), + PKIX_OBJECTNOTCRL); + + crl = (PKIX_PL_CRL *)object; + if (crl->adoptedDerCrl) { + crlDer = crl->adoptedDerCrl; + } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) { + crlDer = crl->nssSignedCrl->derCrl; + } + if (!crlDer || !crlDer->data) { + PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER); + } + + PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len, + &certHash, plContext), + PKIX_ERRORINHASH); + + *pHashcode = certHash; + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRL_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CRL *firstCrl = NULL; + PKIX_PL_CRL *secondCrl = NULL; + SECItem *crlDerOne = NULL, *crlDerTwo = NULL; + PKIX_UInt32 secondType; + + PKIX_ENTER(CRL, "pkix_pl_CRL_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CRL */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCRL); + + firstCrl = (PKIX_PL_CRL *)firstObject; + secondCrl = (PKIX_PL_CRL *)secondObject; + + /* + * Since we know firstObject is a CRL, if both references are + * identical, they must be equal + */ + if (firstCrl == secondCrl){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondCrl isn't a CRL, 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 *)secondCrl, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CRL_TYPE) goto cleanup; + + if (firstCrl->adoptedDerCrl) { + crlDerOne = firstCrl->adoptedDerCrl; + } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) { + crlDerOne = firstCrl->nssSignedCrl->derCrl; + } + + if (secondCrl->adoptedDerCrl) { + crlDerTwo = secondCrl->adoptedDerCrl; + } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) { + crlDerTwo = secondCrl->nssSignedCrl->derCrl; + } + + if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) { + *pResult = PKIX_TRUE; + } + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_CRL_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_pl_CRL_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE]; + + PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf"); + + entry->description = "CRL"; + entry->typeObjectSize = sizeof(PKIX_PL_CRL); + entry->destructor = pkix_pl_CRL_Destroy; + entry->equalsFunction = pkix_pl_CRL_Equals; + entry->hashcodeFunction = pkix_pl_CRL_Hashcode; + entry->toStringFunction = pkix_pl_CRL_ToString; + entry->duplicateFunction = pkix_duplicateImmutable; + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_VerifyUpdateTime( + PKIX_PL_CRL *crl, + PKIX_PL_Date *date, + PKIX_Boolean *pResult, + void *plContext) +{ + PRTime timeToCheck; + PRTime nextUpdate; + PRTime lastUpdate; + SECStatus status; + CERTCrl *nssCrl = NULL; + SECItem *nextUpdateDer = NULL; + PKIX_Boolean haveNextUpdate = PR_FALSE; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime"); + PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult); + + /* Can call this function only with der been adopted. */ + PORT_Assert(crl->adoptedDerCrl); + + nssCrl = &(crl->nssSignedCrl->crl); + timeToCheck = date->nssTime; + + /* nextUpdate can be NULL. Checking before using it */ + nextUpdateDer = &nssCrl->nextUpdate; + if (nextUpdateDer->data && nextUpdateDer->len) { + haveNextUpdate = PR_TRUE; + status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer); + if (status != SECSuccess) { + PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED); + } + } + + status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate)); + if (status != SECSuccess) { + PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED); + } + + if (!haveNextUpdate || nextUpdate < timeToCheck) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + if (lastUpdate <= timeToCheck) { + *pResult = PKIX_TRUE; + } else { + *pResult = PKIX_FALSE; + } + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL + * DESCRIPTION: + * + * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl" + * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails, + * a PKIX_Error is returned. + * + * PARAMETERS: + * "nssSignedCrl" + * Address of CERTSignedCrl. Must be non-NULL. + * "adoptedDerCrl" + * SECItem ponter that if not NULL is indicating that memory used + * for der should be adopted by crl that is about to be created. + * "pCRL" + * 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 CRL 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_pl_CRL_CreateWithSignedCRL( + CERTSignedCrl *nssSignedCrl, + SECItem *adoptedDerCrl, + SECItem *derGenName, + PKIX_PL_CRL **pCrl, + void *plContext) +{ + PKIX_PL_CRL *crl = NULL; + + PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL"); + PKIX_NULLCHECK_ONE(pCrl); + + /* create a PKIX_PL_CRL object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CRL_TYPE, + sizeof (PKIX_PL_CRL), + (PKIX_PL_Object **)&crl, + plContext), + PKIX_COULDNOTCREATECRLOBJECT); + + /* populate the nssSignedCrl field */ + crl->nssSignedCrl = nssSignedCrl; + crl->adoptedDerCrl = adoptedDerCrl; + crl->issuer = NULL; + crl->signatureAlgId = NULL; + crl->crlNumber = NULL; + crl->crlNumberAbsent = PKIX_FALSE; + crl->crlEntryList = NULL; + crl->critExtOids = NULL; + if (derGenName) { + crl->derGenName = + SECITEM_DupItem(derGenName); + if (!crl->derGenName) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + } + + *pCrl = crl; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(crl); + } + + PKIX_RETURN(CRL); +} + +/* --Public-CRL-Functions------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_Create( + PKIX_PL_ByteArray *byteArray, + PKIX_PL_CRL **pCrl, + void *plContext) +{ + CERTSignedCrl *nssSignedCrl = NULL; + SECItem derItem, *derCrl = NULL; + PKIX_PL_CRL *crl = NULL; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_Create"); + PKIX_NULLCHECK_TWO(byteArray, pCrl); + + if (byteArray->length == 0){ + PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING); + } + derItem.type = siBuffer; + derItem.data = byteArray->array; + derItem.len = byteArray->length; + derCrl = SECITEM_DupItem(&derItem); + if (!derCrl) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + nssSignedCrl = + CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE, + CRL_DECODE_DONT_COPY_DER | + CRL_DECODE_SKIP_ENTRIES); + if (!nssSignedCrl) { + PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED); + } + PKIX_CHECK( + pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL, + &crl, plContext), + PKIX_CRLCREATEWITHSIGNEDCRLFAILED); + nssSignedCrl = NULL; + derCrl = NULL; + *pCrl = crl; + +cleanup: + if (derCrl) { + SECITEM_FreeItem(derCrl, PR_TRUE); + } + if (nssSignedCrl) { + SEC_DestroyCrl(nssSignedCrl); + } + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_GetIssuer( + PKIX_PL_CRL *crl, + PKIX_PL_X500Name **pCRLIssuer, + void *plContext) +{ + PKIX_PL_String *crlString = NULL; + PKIX_PL_X500Name *issuer = NULL; + SECItem *derIssuerName = NULL; + CERTName *issuerName = NULL; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer); + + /* Can call this function only with der been adopted. */ + PORT_Assert(crl->adoptedDerCrl); + + /* if we don't have a cached copy from before, we create one */ + if (crl->issuer == NULL){ + + PKIX_OBJECT_LOCK(crl); + + if (crl->issuer == NULL) { + + issuerName = &crl->nssSignedCrl->crl.name; + derIssuerName = &crl->nssSignedCrl->crl.derName; + + PKIX_CHECK( + PKIX_PL_X500Name_CreateFromCERTName(derIssuerName, + issuerName, + &issuer, + plContext), + PKIX_X500NAMECREATEFROMCERTNAMEFAILED); + + /* save a cached copy in case it is asked for again */ + crl->issuer = issuer; + } + + PKIX_OBJECT_UNLOCK(crl); + + } + + PKIX_INCREF(crl->issuer); + + *pCRLIssuer = crl->issuer; + +cleanup: + + PKIX_DECREF(crlString); + + PKIX_RETURN(CRL); +} + + +/* + * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_GetCriticalExtensionOIDs( + PKIX_PL_CRL *crl, + PKIX_List **pExtensions, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_List *oidsList = NULL; + CERTCertExtension **extensions = NULL; + CERTCrl *nssSignedCrl = NULL; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions); + + /* Can call this function only with der been adopted. */ + PORT_Assert(crl->adoptedDerCrl); + + /* if we don't have a cached copy from before, we create one */ + if (crl->critExtOids == NULL) { + + PKIX_OBJECT_LOCK(crl); + + nssSignedCrl = &(crl->nssSignedCrl->crl); + extensions = nssSignedCrl->extensions; + + if (crl->critExtOids == NULL) { + + PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs + (extensions, &oidsList, plContext), + PKIX_GETCRITICALEXTENSIONOIDSFAILED); + + crl->critExtOids = oidsList; + } + + PKIX_OBJECT_UNLOCK(crl); + + } + + /* We should return a copy of the List since this list changes */ + PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext, + PKIX_OBJECTDUPLICATELISTFAILED); + +cleanup: + + PKIX_RETURN(CRL); +} + +/* + * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRL_VerifySignature( + PKIX_PL_CRL *crl, + PKIX_PL_PublicKey *pubKey, + void *plContext) +{ + PKIX_PL_CRL *cachedCrl = NULL; + PKIX_Error *verifySig = NULL; + PKIX_Error *cachedSig = NULL; + PKIX_Boolean crlEqual = PKIX_FALSE; + PKIX_Boolean crlInHash= PKIX_FALSE; + CERTSignedCrl *nssSignedCrl = NULL; + SECKEYPublicKey *nssPubKey = NULL; + CERTSignedData *tbsCrl = NULL; + void* wincx = NULL; + SECStatus status; + + PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature"); + PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey); + + /* Can call this function only with der been adopted. */ + PORT_Assert(crl->adoptedDerCrl); + + verifySig = PKIX_PL_HashTable_Lookup + (cachedCrlSigTable, + (PKIX_PL_Object *) pubKey, + (PKIX_PL_Object **) &cachedCrl, + plContext); + + if (cachedCrl != NULL && verifySig == NULL) { + /* Cached Signature Table lookup succeed */ + PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext, + PKIX_OBJECTEQUALSFAILED); + if (crlEqual == PKIX_TRUE) { + goto cleanup; + } + /* Different PubKey may hash to same value, skip add */ + crlInHash = PKIX_TRUE; + } + + nssSignedCrl = crl->nssSignedCrl; + tbsCrl = &nssSignedCrl->signatureWrap; + + PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n"); + nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); + if (!nssPubKey){ + PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); + } + + PKIX_CHECK(pkix_pl_NssContext_GetWincx + ((PKIX_PL_NssContext *)plContext, &wincx), + PKIX_NSSCONTEXTGETWINCXFAILED); + + PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n"); + status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx); + + if (status != SECSuccess) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); + } + + if (crlInHash == PKIX_FALSE) { + cachedSig = PKIX_PL_HashTable_Add + (cachedCrlSigTable, + (PKIX_PL_Object *) pubKey, + (PKIX_PL_Object *) crl, + plContext); + + if (cachedSig != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); + } + } + +cleanup: + + if (nssPubKey){ + PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n"); + SECKEY_DestroyPublicKey(nssPubKey); + nssPubKey = NULL; + } + + PKIX_DECREF(cachedCrl); + PKIX_DECREF(verifySig); + PKIX_DECREF(cachedSig); + + PKIX_RETURN(CRL); +} + +PKIX_Error* +PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl, + SECItem **derCrl, + void *plContext) +{ + PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl"); + *derCrl = crl->adoptedDerCrl; + crl->adoptedDerCrl = NULL; + + PKIX_RETURN(CRL); +} + +PKIX_Error* +PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl, + SECItem *derCrl, + void *plContext) +{ + PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl"); + if (crl->adoptedDerCrl) { + PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER); + } + crl->adoptedDerCrl = derCrl; +cleanup: + PKIX_RETURN(CRL); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h new file mode 100644 index 0000000000..a45059ea0d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h @@ -0,0 +1,48 @@ +/* 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_pl_crl.h + * + * CRL Object Type Definitions + * + */ + +#ifndef _PKIX_PL_CRL_H +#define _PKIX_PL_CRL_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_CRLStruct { + CERTSignedCrl *nssSignedCrl; + PKIX_PL_X500Name *issuer; + PKIX_PL_OID *signatureAlgId; + PKIX_PL_BigInt *crlNumber; + PKIX_Boolean crlNumberAbsent; + PKIX_List *crlEntryList; /* list of PKIX_PL_CRLEntry */ + PKIX_List *critExtOids; + SECItem *adoptedDerCrl; + SECItem *derGenName; /* der of general name which was used + * to download the crl. */ +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_CRL_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_CRL_CreateWithSignedCRL(CERTSignedCrl *nssSignedCrl, + SECItem *derCrl, + SECItem *derGenName, + PKIX_PL_CRL **pCrl, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_CRL_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c new file mode 100644 index 0000000000..4f29de2849 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c @@ -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_pl_crldp.c + * + * Crl DP Object Functions + * + */ + +#include "pkix_pl_crldp.h" + +static PKIX_Error * +pkix_pl_CrlDp_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + pkix_pl_CrlDp *crldp = NULL; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a default CRL checker state */ + PKIX_CHECK( + pkix_CheckType(object, PKIX_CRLDP_TYPE, plContext), + PKIX_OBJECTNOTCRLCHECKER); + + crldp = (pkix_pl_CrlDp *)object; + if (crldp->distPointType == relativeDistinguishedName) { + CERT_DestroyName(crldp->name.issuerName); + crldp->name.issuerName = NULL; + } + crldp->nssdp = NULL; +cleanup: + PKIX_RETURN(CRLCHECKER); +} + +/* + * FUNCTION: pkix_pl_CrlDp_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_CRLDP_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_pl_CrlDp_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLDP_TYPE]; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf"); + + entry->description = "CrlDistPoint"; + entry->typeObjectSize = sizeof(pkix_pl_CrlDp); + entry->destructor = pkix_pl_CrlDp_Destroy; + entry->duplicateFunction = pkix_duplicateImmutable; + + PKIX_RETURN(CRLCHECKER); +} + + + +PKIX_Error * +pkix_pl_CrlDp_Create( + const CRLDistributionPoint *dp, + const CERTName *certIssuerName, + pkix_pl_CrlDp **pPkixDP, + void *plContext) +{ + PLArenaPool *rdnArena = NULL; + CERTName *issuerNameCopy = NULL; + pkix_pl_CrlDp *dpl = NULL; + + /* Need to save the following info to update crl cache: + * - reasons if partitioned(but can not return revocation check + * success if not all crl are downloaded) + * - issuer name if different from issuer of the cert + * - url to upload a crl if needed. + * */ + PKIX_ENTER(CRLDP, "pkix_pl_CrlDp_Create"); + PKIX_NULLCHECK_ONE(dp); + + PKIX_CHECK( + PKIX_PL_Object_Alloc(PKIX_CRLDP_TYPE, + sizeof (pkix_pl_CrlDp), + (PKIX_PL_Object **)&dpl, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + dpl->nssdp = dp; + dpl->isPartitionedByReasonCode = PKIX_FALSE; + if (dp->reasons.data) { + dpl->isPartitionedByReasonCode = PKIX_TRUE; + } + if (dp->distPointType == generalName) { + dpl->distPointType = generalName; + dpl->name.fullName = dp->distPoint.fullName; + } else { + SECStatus rv; + const CERTName *issuerName = NULL; + const CERTRDN *relName = &dp->distPoint.relativeName; + + if (dp->crlIssuer) { + if (dp->crlIssuer->l.next) { + /* Violate RFC 5280: in this case crlIssuer + * should have only one name and should be + * a distinguish name. */ + PKIX_ERROR(PKIX_NOTCONFORMINGCRLDP); + } + issuerName = &dp->crlIssuer->name.directoryName; + } else { + issuerName = certIssuerName; + } + rdnArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!rdnArena) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + issuerNameCopy = (CERTName *)PORT_ArenaZNew(rdnArena, CERTName); + if (!issuerNameCopy) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + rv = CERT_CopyName(rdnArena, issuerNameCopy, (CERTName*)issuerName); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + rv = CERT_AddRDN(issuerNameCopy, (CERTRDN*)relName); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_ALLOCERROR); + } + dpl->distPointType = relativeDistinguishedName; + dpl->name.issuerName = issuerNameCopy; + rdnArena = NULL; + } + *pPkixDP = dpl; + dpl = NULL; + +cleanup: + if (rdnArena) { + PORT_FreeArena(rdnArena, PR_FALSE); + } + PKIX_DECREF(dpl); + + PKIX_RETURN(CRLDP); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h new file mode 100644 index 0000000000..49cd9d2cdf --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h @@ -0,0 +1,53 @@ +/* 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_pl_crldp.h + * + * Crp DP Object Definitions + * + */ +#include "pkix_pl_common.h" + +#ifndef _PKIX_PL_CRLDP_H +#define _PKIX_PL_CRLDP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* CRLDP object can not be used without holding a reference + * to the pkix certificate they belong to. The memory for dp der + * object is allocated on nssCert certificate - a member of + * PKIX_PL_Cert struct. */ +typedef struct pkix_pl_CrlDpStruct { + /* reference to decoded crldp that allocated on nssCert arena. */ + const CRLDistributionPoint *nssdp; + DistributionPointTypes distPointType; + union { + CERTGeneralName *fullName; + /* if dp is a relative name, the issuerName is a merged value + * of crlIssuer and a relative name. Must be destroyed by CrlDp + * destructor. */ + CERTName *issuerName; + } name; + PKIX_Boolean isPartitionedByReasonCode; +} pkix_pl_CrlDp; + + +PKIX_Error * +pkix_pl_CrlDp_RegisterSelf(void *plContext); + +/* Parses CRLDistributionPoint structure and creaetes + * pkix_pl_CrlDp object. */ +PKIX_Error * +pkix_pl_CrlDp_Create(const CRLDistributionPoint *dp, + const CERTName *certIssuerName, + pkix_pl_CrlDp **pPkixDP, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_CRLDP_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c new file mode 100644 index 0000000000..e2b3e02688 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c @@ -0,0 +1,880 @@ +/* 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_pl_crlentry.c + * + * CRLENTRY Function Definitions + * + */ + +#include "pkix_pl_crlentry.h" + +/* --Private-CRLEntry-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_CRLEntry_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRLEntry_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CRLEntry *crlEntry = NULL; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), + PKIX_OBJECTNOTCRLENTRY); + + crlEntry = (PKIX_PL_CRLEntry*)object; + + /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */ + crlEntry->userReasonCode = 0; + crlEntry->userReasonCodeAbsent = PKIX_FALSE; + crlEntry->nssCrlEntry = NULL; + PKIX_DECREF(crlEntry->serialNumber); + PKIX_DECREF(crlEntry->critExtOids); + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_ToString_Helper + * + * DESCRIPTION: + * Helper function that creates a string representation of the CRLEntry + * pointed to by "crlEntry" and stores it at "pString". + * + * PARAMETERS + * "crlEntry" + * Address of CRLEntry whose string representation is desired. + * Must be non-NULL. + * "pString" + * 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 CRLEntry 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_pl_CRLEntry_ToString_Helper( + PKIX_PL_CRLEntry *crlEntry, + PKIX_PL_String **pString, + void *plContext) +{ + char *asciiFormat = NULL; + PKIX_List *critExtOIDs = NULL; + PKIX_PL_String *crlEntryString = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *crlSerialNumberString = NULL; + PKIX_PL_String *crlRevocationDateString = NULL; + PKIX_PL_String *critExtOIDsString = NULL; + PKIX_Int32 reasonCode = 0; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper"); + PKIX_NULLCHECK_FOUR + (crlEntry, + crlEntry->serialNumber, + crlEntry->nssCrlEntry, + pString); + + asciiFormat = + "\n\t[\n" + "\tSerialNumber: %s\n" + "\tReasonCode: %d\n" + "\tRevocationDate: %s\n" + "\tCritExtOIDs: %s\n" + "\t]\n\t"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* SerialNumber */ + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)crlEntry->serialNumber, + &crlSerialNumberString, + plContext), + PKIX_BIGINTTOSTRINGHELPERFAILED); + + /* RevocationDate - No Date object created, use nss data directly */ + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&(crlEntry->nssCrlEntry->revocationDate), + &crlRevocationDateString, + plContext), + PKIX_DATETOSTRINGHELPERFAILED); + + /* CriticalExtensionOIDs */ + PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs + (crlEntry, &critExtOIDs, plContext), + PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED); + + PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, + PKIX_LISTTOSTRINGFAILED); + + /* Revocation Reason Code */ + PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode + (crlEntry, &reasonCode, plContext), + PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&crlEntryString, + plContext, + formatString, + crlSerialNumberString, + reasonCode, + crlRevocationDateString, + critExtOIDsString), + PKIX_SPRINTFFAILED); + + *pString = crlEntryString; + +cleanup: + + PKIX_DECREF(critExtOIDs); + PKIX_DECREF(crlSerialNumberString); + PKIX_DECREF(crlRevocationDateString); + PKIX_DECREF(critExtOIDsString); + PKIX_DECREF(formatString); + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRLEntry_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *crlEntryString = NULL; + PKIX_PL_CRLEntry *crlEntry = NULL; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), + PKIX_OBJECTNOTCRLENTRY); + + crlEntry = (PKIX_PL_CRLEntry *) object; + + PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper + (crlEntry, &crlEntryString, plContext), + PKIX_CRLENTRYTOSTRINGHELPERFAILED); + + *pString = crlEntryString; + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode + * DESCRIPTION: + * + * For each CRL Entry extension stored at NSS structure CERTCertExtension, + * get its derbyte data and do the hash. + * + * PARAMETERS + * "extensions" + * Address of arrray of CERTCertExtension whose hash value is desired. + * Must be non-NULL. + * "pHashValue" + * Address where the final hash value is returned. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditional Thread Safe + * Though the value of extensions once created is not supposed to change, + * it may be de-allocated while we are accessing it. But since we are + * validating the object, it is unlikely we or someone is de-allocating + * at the moment. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an OID 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_pl_CRLEntry_Extensions_Hashcode( + CERTCertExtension **extensions, + PKIX_UInt32 *pHashValue, + void *plContext) +{ + CERTCertExtension *extension = NULL; + PLArenaPool *arena = NULL; + PKIX_UInt32 extHash = 0; + PKIX_UInt32 hashValue = 0; + SECItem *derBytes = NULL; + SECItem *resultSecItem = NULL; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode"); + PKIX_NULLCHECK_TWO(extensions, pHashValue); + + if (extensions) { + + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + while (*extensions) { + + extension = *extensions++; + + PKIX_NULLCHECK_ONE(extension); + + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); + derBytes = PORT_ArenaZNew(arena, SECItem); + if (derBytes == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + PKIX_CRLENTRY_DEBUG + ("\t\tCalling SEC_ASN1EncodeItem\n"); + resultSecItem = SEC_ASN1EncodeItem + (arena, + derBytes, + extension, + CERT_CertExtensionTemplate); + + if (resultSecItem == NULL){ + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + PKIX_CHECK(pkix_hash + (derBytes->data, + derBytes->len, + &extHash, + plContext), + PKIX_HASHFAILED); + + hashValue += (extHash << 7); + + } + } + + *pHashValue = hashValue; + +cleanup: + + if (arena){ + /* Note that freeing the arena also frees derBytes */ + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); + PORT_FreeArena(arena, PR_FALSE); + arena = NULL; + } + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRLEntry_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + SECItem *nssDate = NULL; + PKIX_PL_CRLEntry *crlEntry = NULL; + PKIX_UInt32 crlEntryHash; + PKIX_UInt32 hashValue; + PKIX_Int32 reasonCode = 0; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), + PKIX_OBJECTNOTCRLENTRY); + + crlEntry = (PKIX_PL_CRLEntry *)object; + + PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry); + nssDate = &(crlEntry->nssCrlEntry->revocationDate); + + PKIX_NULLCHECK_ONE(nssDate->data); + + PKIX_CHECK(pkix_hash + ((const unsigned char *)nssDate->data, + nssDate->len, + &crlEntryHash, + plContext), + PKIX_ERRORGETTINGHASHCODE); + + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)crlEntry->serialNumber, + &hashValue, + plContext), + PKIX_OBJECTHASHCODEFAILED); + + crlEntryHash += (hashValue << 7); + + hashValue = 0; + + if (crlEntry->nssCrlEntry->extensions) { + + PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode + (crlEntry->nssCrlEntry->extensions, &hashValue, plContext), + PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED); + } + + crlEntryHash += (hashValue << 7); + + PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode + (crlEntry, &reasonCode, plContext), + PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); + + crlEntryHash += (reasonCode + 777) << 3; + + *pHashcode = crlEntryHash; + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals + * DESCRIPTION: + * + * Compare each extension's DERbyte data in "firstExtensions" with extension + * in "secondExtensions" in sequential order and store the result in + * "pResult". + * + * PARAMETERS + * "firstExtensions" + * Address of first NSS structure CERTCertExtension to be compared. + * Must be non-NULL. + * "secondExtensions" + * Address of second NSS structure CERTCertExtension to be compared. + * Must be non-NULL. + * "pResult" + * Address where the comparison result is returned. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Conditionally Thread Safe + * Though the value of extensions once created is not supposed to change, + * it may be de-allocated while we are accessing it. But since we are + * validating the object, it is unlikely we or someone is de-allocating + * at the moment. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an OID 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_pl_CRLEntry_Extensions_Equals( + CERTCertExtension **extensions1, + CERTCertExtension **extensions2, + PKIX_Boolean *pResult, + void *plContext) +{ + CERTCertExtension **firstExtensions; + CERTCertExtension **secondExtensions; + CERTCertExtension *firstExtension = NULL; + CERTCertExtension *secondExtension = NULL; + PLArenaPool *arena = NULL; + PKIX_Boolean cmpResult = PKIX_FALSE; + SECItem *firstDerBytes = NULL; + SECItem *secondDerBytes = NULL; + SECItem *firstResultSecItem = NULL; + SECItem *secondResultSecItem = NULL; + PKIX_UInt32 firstNumExt = 0; + PKIX_UInt32 secondNumExt = 0; + SECComparison secResult; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals"); + PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult); + + firstExtensions = extensions1; + secondExtensions = extensions2; + + if (firstExtensions) { + while (*firstExtensions) { + firstExtension = *firstExtensions++; + firstNumExt++; + } + } + + if (secondExtensions) { + while (*secondExtensions) { + secondExtension = *secondExtensions++; + secondNumExt++; + } + } + + if (firstNumExt != secondNumExt) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + if (firstNumExt == 0 && secondNumExt == 0) { + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* now have equal number, but non-zero extension items to compare */ + + firstExtensions = extensions1; + secondExtensions = extensions2; + + cmpResult = PKIX_TRUE; + + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + while (firstNumExt--) { + + firstExtension = *firstExtensions++; + secondExtension = *secondExtensions++; + + PKIX_NULLCHECK_TWO(firstExtension, secondExtension); + + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); + firstDerBytes = PORT_ArenaZNew(arena, SECItem); + if (firstDerBytes == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); + secondDerBytes = PORT_ArenaZNew(arena, SECItem); + if (secondDerBytes == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + PKIX_CRLENTRY_DEBUG + ("\t\tCalling SEC_ASN1EncodeItem\n"); + firstResultSecItem = SEC_ASN1EncodeItem + (arena, + firstDerBytes, + firstExtension, + CERT_CertExtensionTemplate); + + if (firstResultSecItem == NULL){ + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + PKIX_CRLENTRY_DEBUG + ("\t\tCalling SEC_ASN1EncodeItem\n"); + secondResultSecItem = SEC_ASN1EncodeItem + (arena, + secondDerBytes, + secondExtension, + CERT_CertExtensionTemplate); + + if (secondResultSecItem == NULL){ + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); + secResult = SECITEM_CompareItem + (firstResultSecItem, secondResultSecItem); + + if (secResult != SECEqual) { + cmpResult = PKIX_FALSE; + break; + } + + } + + *pResult = cmpResult; + +cleanup: + + if (arena){ + /* Note that freeing the arena also frees derBytes */ + PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); + PORT_FreeArena(arena, PR_FALSE); + arena = NULL; + } + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CRLEntry_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CRLEntry *firstCrlEntry = NULL; + PKIX_PL_CRLEntry *secondCrlEntry = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult = PKIX_FALSE; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CRLEntry */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCRLENTRY); + + firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject; + secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject; + + PKIX_NULLCHECK_TWO + (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry); + + /* + * Since we know firstObject is a CRLEntry, if both references are + * identical, they must be equal + */ + if (firstCrlEntry == secondCrlEntry){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondCrlEntry isn't a CRL Entry, 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 *)secondCrlEntry, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup; + + /* Compare userSerialNumber */ + PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); + if (SECITEM_CompareItem( + &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber), + &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber)) + != SECEqual) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + /* Compare revocationDate */ + PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); + if (SECITEM_CompareItem + (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry-> + revocationDate), + &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry-> + revocationDate)) + != SECEqual) { + *pResult = PKIX_FALSE; + goto cleanup; + } + + /* Compare Critical Extension List */ + PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals + (firstCrlEntry->nssCrlEntry->extensions, + secondCrlEntry->nssCrlEntry->extensions, + &cmpResult, + plContext), + PKIX_CRLENTRYEXTENSIONSEQUALSFAILED); + + if (cmpResult != PKIX_TRUE){ + *pResult = PKIX_FALSE; + goto cleanup; + } + + cmpResult = (firstCrlEntry->userReasonCode == + secondCrlEntry->userReasonCode); + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CRLEntry_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_pl_CRLEntry_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf"); + + entry.description = "CRLEntry"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry); + entry.destructor = pkix_pl_CRLEntry_Destroy; + entry.equalsFunction = pkix_pl_CRLEntry_Equals; + entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode; + entry.toStringFunction = pkix_pl_CRLEntry_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CRLENTRY_TYPE] = entry; + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_CreateEntry + * DESCRIPTION: + * + * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry" + * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable. + * + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * + * PARAMETERS: + * "nssCrlEntry" + * Address of CERTCrlEntry representing an NSS CRL entry. + * Must be non-NULL. + * "pCrlEntry" + * 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 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_pl_CRLEntry_CreateEntry( + CERTCrlEntry *nssCrlEntry, /* entry data to be created from */ + PKIX_PL_CRLEntry **pCrlEntry, + void *plContext) +{ + PKIX_PL_CRLEntry *crlEntry = NULL; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry"); + PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CRLENTRY_TYPE, + sizeof (PKIX_PL_CRLEntry), + (PKIX_PL_Object **)&crlEntry, + plContext), + PKIX_COULDNOTCREATECRLENTRYOBJECT); + + crlEntry->nssCrlEntry = nssCrlEntry; + crlEntry->serialNumber = NULL; + crlEntry->critExtOids = NULL; + crlEntry->userReasonCode = 0; + crlEntry->userReasonCodeAbsent = PKIX_FALSE; + + *pCrlEntry = crlEntry; + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: pkix_pl_CRLEntry_Create + * DESCRIPTION: + * + * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to + * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is + * NULL, this function stores an empty List at "pCrlEntryList". + * } + * PARAMETERS: + * "nssCrlEntries" + * Address of array of CERTCrlEntries representing NSS CRL entries. + * Can be NULL if CRL has no NSS CRL entries. + * "pCrlEntryList" + * 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 CRLEntry 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_pl_CRLEntry_Create( + CERTCrlEntry **nssCrlEntries, /* head of entry list */ + PKIX_List **pCrlEntryList, + void *plContext) +{ + PKIX_List *entryList = NULL; + PKIX_PL_CRLEntry *crlEntry = NULL; + CERTCrlEntry **entries = NULL; + SECItem serialNumberItem; + PKIX_PL_BigInt *serialNumber; + char *bytes = NULL; + PKIX_UInt32 length; + + PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create"); + PKIX_NULLCHECK_ONE(pCrlEntryList); + + entries = nssCrlEntries; + + PKIX_CHECK(PKIX_List_Create(&entryList, plContext), + PKIX_LISTCREATEFAILED); + + if (entries) { + while (*entries){ + PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry + (*entries, &crlEntry, plContext), + PKIX_COULDNOTCREATECRLENTRYOBJECT); + + /* Get Serial Number */ + serialNumberItem = (*entries)->serialNumber; + length = serialNumberItem.len; + bytes = (char *)serialNumberItem.data; + + PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes + (bytes, length, &serialNumber, plContext), + PKIX_BIGINTCREATEWITHBYTESFAILED); + + crlEntry->serialNumber = serialNumber; + crlEntry->nssCrlEntry = *entries; + + PKIX_CHECK(PKIX_List_AppendItem + (entryList, (PKIX_PL_Object *)crlEntry, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(crlEntry); + + entries++; + } + } + + *pCrlEntryList = entryList; + +cleanup: + PKIX_DECREF(crlEntry); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(entryList); + } + + PKIX_RETURN(CRLENTRY); +} + +/* --Public-CRLENTRY-Functions------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRLEntry_GetCRLEntryReasonCode ( + PKIX_PL_CRLEntry *crlEntry, + PKIX_Int32 *pReason, + void *plContext) +{ + SECStatus status; + CERTCRLEntryReasonCode nssReasonCode; + + PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode"); + PKIX_NULLCHECK_TWO(crlEntry, pReason); + + if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) { + + PKIX_OBJECT_LOCK(crlEntry); + + if (!crlEntry->userReasonCodeAbsent && + crlEntry->userReasonCode == 0) { + + /* reason code has not been cached in */ + PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n"); + status = CERT_FindCRLEntryReasonExten + (crlEntry->nssCrlEntry, &nssReasonCode); + + if (status == SECSuccess) { + crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode; + } else { + crlEntry->userReasonCodeAbsent = PKIX_TRUE; + } + } + + PKIX_OBJECT_UNLOCK(crlEntry); + + } + + *pReason = crlEntry->userReasonCode; + +cleanup: + + PKIX_RETURN(CRLENTRY); +} + +/* + * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_CRLEntry_GetCriticalExtensionOIDs ( + PKIX_PL_CRLEntry *crlEntry, + PKIX_List **pList, /* list of PKIX_PL_OID */ + void *plContext) +{ + PKIX_List *oidsList = NULL; + CERTCertExtension **extensions; + + PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs"); + PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList); + + /* if we don't have a cached copy from before, we create one */ + if (crlEntry->critExtOids == NULL) { + + PKIX_OBJECT_LOCK(crlEntry); + + if (crlEntry->critExtOids == NULL) { + + extensions = crlEntry->nssCrlEntry->extensions; + + PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs + (extensions, &oidsList, plContext), + PKIX_GETCRITICALEXTENSIONOIDSFAILED); + + crlEntry->critExtOids = oidsList; + } + + PKIX_OBJECT_UNLOCK(crlEntry); + + } + + /* We should return a copy of the List since this list changes */ + PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext, + PKIX_OBJECTDUPLICATELISTFAILED); + +cleanup: + + PKIX_RETURN(CRLENTRY); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h new file mode 100644 index 0000000000..9cdb6bc927 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h @@ -0,0 +1,46 @@ +/* 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_pl_crlentry.h + * + * CRL Entry Type Object Definitions + * + */ + +#ifndef _PKIX_PL_CRLENTRY_H +#define _PKIX_PL_CRLENTRY_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PKIX_PL_CRL_REASONCODE_NOTSET (-1) + +struct PKIX_PL_CRLEntryStruct { + CERTCrlEntry *nssCrlEntry; + PKIX_PL_BigInt *serialNumber; + PKIX_List *critExtOids; + PKIX_Int32 userReasonCode; + PKIX_Boolean userReasonCodeAbsent; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_CRLEntry_RegisterSelf(void *plContext); + +/* following functions are called by CRL only hence not public */ + +PKIX_Error * +pkix_pl_CRLEntry_Create( + CERTCrlEntry **nssCrlEntry, /* head of entry list */ + PKIX_List **pCrlEntryList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_CRLENTRY_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c new file mode 100644 index 0000000000..4b5016bd01 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c @@ -0,0 +1,466 @@ +/* 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_pl_date.c + * + * Date Object Definitions + * + */ + +#include "pkix_pl_date.h" + +/* --Private-Date-Functions------------------------------------- */ +/* + * FUNCTION: pkix_pl_Date_GetPRTime + * DESCRIPTION: + * + * Translates into a PRTime the Date embodied by the Date object pointed to + * by "date", and stores it at "pPRTime". + * + * PARAMETERS + * "date" + * Address of Date whose PRTime representation is desired. Must be + * non-NULL. + * "pPRTime" + * Address where PRTime value 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 Date 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_pl_Date_GetPRTime( + PKIX_PL_Date *date, + PRTime *pPRTime, + void *plContext) +{ + PKIX_ENTER(DATE, "PKIX_PL_Date_GetPRTime"); + PKIX_NULLCHECK_TWO(date, pPRTime); + + *pPRTime = date->nssTime; + + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_CreateFromPRTime + * DESCRIPTION: + * + * Creates a new Date from the PRTime whose value is "prtime", and stores the + * result at "pDate". + * + * PARAMETERS + * "prtime" + * The PRTime value to be embodied in the new Date object. + * "pDate" + * 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 Date 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_pl_Date_CreateFromPRTime( + PRTime prtime, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_PL_Date *date = NULL; + + PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime"); + PKIX_NULLCHECK_ONE(pDate); + + /* create a PKIX_PL_Date object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_DATE_TYPE, + sizeof (PKIX_PL_Date), + (PKIX_PL_Object **)&date, + plContext), + PKIX_COULDNOTCREATEOBJECT); + /* populate the nssTime field */ + date->nssTime = prtime; + *pDate = date; +cleanup: + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the SECItem pointed + * to by "nssTime" (which represents a date) and stores it at "pString". + * + * PARAMETERS + * "nssTime" + * Address of SECItem whose string representation is desired. + * Must be non-NULL. + * "pString" + * 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 Date 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_pl_Date_ToString_Helper( + SECItem *nssTime, + PKIX_PL_String **pString, + void *plContext) +{ + char *asciiDate = NULL; + + PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper"); + PKIX_NULLCHECK_TWO(nssTime, pString); + + switch (nssTime->type) { + case siUTCTime: + PKIX_PL_NSSCALLRV + (DATE, asciiDate, DER_UTCDayToAscii, (nssTime)); + if (!asciiDate){ + PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED); + } + break; + case siGeneralizedTime: + /* + * we don't currently have any way to create GeneralizedTime. + * this code is only here so that it will be in place when + * we do have the capability to create GeneralizedTime. + */ + PKIX_PL_NSSCALLRV + (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime)); + if (!asciiDate){ + PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED); + } + break; + default: + PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE); + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, asciiDate, 0, pString, plContext), + PKIX_STRINGCREATEFAILED); + +cleanup: + PR_Free(asciiDate); + + PKIX_RETURN(DATE); +} + + +/* + * FUNCTION: pkix_pl_Date_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Date_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ENTER(DATE, "pkix_pl_Date_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext), + PKIX_OBJECTNOTDATE); +cleanup: + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Date_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_Date *date = NULL; + SECItem nssTime = {siBuffer, NULL, 0}; + SECStatus rv; + + PKIX_ENTER(DATE, "pkix_pl_Date_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext), + PKIX_OBJECTNOTDATE); + + date = (PKIX_PL_Date *)object; + rv = DER_EncodeTimeChoice(NULL, &nssTime, date->nssTime); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED); + } + PKIX_CHECK(pkix_pl_Date_ToString_Helper + (&nssTime, pString, plContext), + PKIX_DATETOSTRINGHELPERFAILED); +cleanup: + if (nssTime.data) { + SECITEM_FreeItem(&nssTime, PR_FALSE); + } + + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Date_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_Date *date = NULL; + PKIX_UInt32 dateHash; + + PKIX_ENTER(DATE, "pkix_pl_Date_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext), + PKIX_OBJECTNOTDATE); + + date = (PKIX_PL_Date *)object; + + PKIX_CHECK(pkix_hash + ((const unsigned char *)&date->nssTime, + sizeof(date->nssTime), + &dateHash, + plContext), + PKIX_HASHFAILED); + + *pHashcode = dateHash; + +cleanup: + + PKIX_RETURN(DATE); + +} + +/* + * FUNCTION: pkix_pl_Date_Comparator + * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Date_Comparator( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PRTime firstTime; + PRTime secondTime; + SECComparison cmpResult; + + PKIX_ENTER(DATE, "pkix_pl_Date_Comparator"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_DATE_TYPE, plContext), + PKIX_ARGUMENTSNOTDATES); + + firstTime = ((PKIX_PL_Date *)firstObject)->nssTime; + secondTime = ((PKIX_PL_Date *)secondObject)->nssTime; + + if (firstTime == secondTime) + cmpResult = SECEqual; + else if (firstTime < secondTime) + cmpResult = SECLessThan; + else + cmpResult = SECGreaterThan; + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Date_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_ENTER(DATE, "pkix_pl_Date_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a Date */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_DATE_TYPE, plContext), + PKIX_FIRSTOBJECTNOTDATE); + + /* + * Since we know firstObject is a Date, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + *pResult = PKIX_FALSE; + pkixErrorResult = + pkix_pl_Date_Comparator(firstObject, secondObject, + pResult, plContext); + if (pkixErrorResult) { + PKIX_DECREF(pkixErrorResult); + } + +cleanup: + + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: pkix_pl_Date_RegisterSelf + * DESCRIPTION: + * Registers PKIX_DATE_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_pl_Date_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry* entry = &systemClasses[PKIX_DATE_TYPE]; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf"); + + entry->description = "Date"; + entry->typeObjectSize = sizeof(PKIX_PL_Date); + entry->destructor = pkix_pl_Date_Destroy; + entry->equalsFunction = pkix_pl_Date_Equals; + entry->hashcodeFunction = pkix_pl_Date_Hashcode; + entry->toStringFunction = pkix_pl_Date_ToString; + entry->comparator = pkix_pl_Date_Comparator; + entry->duplicateFunction = pkix_duplicateImmutable; + + PKIX_RETURN(DATE); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Date_Create_UTCTime( + PKIX_PL_String *stringRep, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_PL_Date *date = NULL; + char *asciiString = NULL; + PKIX_UInt32 escAsciiLength; + SECStatus rv; + PRTime time; + + PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime"); + PKIX_NULLCHECK_ONE(pDate); + + if (stringRep == NULL){ + PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n"); + time = PR_Now(); + } else { + /* convert the input PKIX_PL_String to PKIX_ESCASCII */ + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stringRep, + PKIX_ESCASCII, + (void **)&asciiString, + &escAsciiLength, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n"); + /* DER_AsciiToTime only supports UTCTime (2-digit years) */ + rv = DER_AsciiToTime(&time, asciiString); + if (rv != SECSuccess){ + PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED); + } + } + + /* create a PKIX_PL_Date object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_DATE_TYPE, + sizeof (PKIX_PL_Date), + (PKIX_PL_Object **)&date, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* populate the nssTime field */ + date->nssTime = time; + *pDate = date; + +cleanup: + PKIX_FREE(asciiString); + + PKIX_RETURN(DATE); +} + +/* + * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_Date_Create_CurrentOffBySeconds( + PKIX_Int32 secondsOffset, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_PL_Date *date = NULL; + PRTime time; + + PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds"); + PKIX_NULLCHECK_ONE(pDate); + + time = PR_Now() + PR_SecondsToInterval(secondsOffset); + /* create a PKIX_PL_Date object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_DATE_TYPE, + sizeof (PKIX_PL_Date), + (PKIX_PL_Object **)&date, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* populate the nssTime field */ + date->nssTime = time; + *pDate = date; + +cleanup: + PKIX_RETURN(DATE); +} + +PKIX_Error * +PKIX_PL_Date_CreateFromPRTime( + PRTime prtime, + PKIX_PL_Date **pDate, + void *plContext) +{ + PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime"); + PKIX_CHECK( + pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext), + PKIX_DATECREATEFROMPRTIMEFAILED); + +cleanup: + PKIX_RETURN(DATE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h new file mode 100644 index 0000000000..415597580a --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h @@ -0,0 +1,55 @@ +/* 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_pl_date.h + * + * Date Object Definitions + * + */ + +#ifndef _PKIX_PL_DATE_H +#define _PKIX_PL_DATE_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_DateStruct{ + PRTime nssTime; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_Date_ToString_Helper( + SECItem *nssTime, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error *pkix_pl_Date_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_Date_GetPRTime( + PKIX_PL_Date *date, + PRTime *pPRTime, + void *plContext); + +PKIX_Error * +pkix_pl_Date_CreateFromPRTime( + PRTime prtime, + PKIX_PL_Date **pDate, + void *plContext); + +PKIX_Error * +PKIX_PL_Date_CreateFromPRTime( + PRTime prtime, + PKIX_PL_Date **pDate, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_DATE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c new file mode 100644 index 0000000000..9e9a74c783 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c @@ -0,0 +1,873 @@ +/* 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_pl_generalname.c + * + * GeneralName Object Definitions + * + */ + +#include "pkix_pl_generalname.h" + +/* --Private-GeneralName-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_GeneralName_GetNssGeneralName + * DESCRIPTION: + * + * Retrieves the NSS representation of the PKIX_PL_GeneralName pointed by + * "genName" and stores it at "pNssGenName". The NSS data type CERTGeneralName + * is stored in this object when the object was created. + * + * PARAMETERS: + * "genName" + * Address of PKIX_PL_GeneralName. Must be non-NULL. + * "pNssGenName" + * Address where CERTGeneralName 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 GeneralName 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_pl_GeneralName_GetNssGeneralName( + PKIX_PL_GeneralName *genName, + CERTGeneralName **pNssGenName, + void *plContext) +{ + CERTGeneralName *nssGenName = NULL; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_GetNssGeneralName"); + PKIX_NULLCHECK_THREE(genName, pNssGenName, genName->nssGeneralNameList); + + nssGenName = genName->nssGeneralNameList->name; + + *pNssGenName = nssGenName; + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_OtherName_Create + * DESCRIPTION: + * + * Creates new OtherName which represents the CERTGeneralName pointed to by + * "nssAltName" and stores it at "pOtherName". + * + * PARAMETERS: + * "nssAltName" + * Address of CERTGeneralName. Must be non-NULL. + * "pOtherName" + * 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 GeneralName 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_pl_OtherName_Create( + CERTGeneralName *nssAltName, + OtherName **pOtherName, + void *plContext) +{ + OtherName *otherName = NULL; + SECItem secItemName; + SECItem secItemOID; + SECStatus rv; + + PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create"); + PKIX_NULLCHECK_TWO(nssAltName, pOtherName); + + PKIX_CHECK(PKIX_PL_Malloc + (sizeof (OtherName), (void **)&otherName, plContext), + PKIX_MALLOCFAILED); + + /* make a copy of the name field */ + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n"); + rv = SECITEM_CopyItem + (NULL, &otherName->name, &nssAltName->name.OthName.name); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + /* make a copy of the oid field */ + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n"); + rv = SECITEM_CopyItem + (NULL, &otherName->oid, &nssAltName->name.OthName.oid); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + *pOtherName = otherName; + +cleanup: + + if (otherName && PKIX_ERROR_RECEIVED){ + secItemName = otherName->name; + secItemOID = otherName->oid; + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&secItemName, PR_FALSE); + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&secItemOID, PR_FALSE); + + PKIX_FREE(otherName); + otherName = NULL; + } + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_DirectoryName_Create + * DESCRIPTION: + * + * Creates a new X500Name which represents the directoryName component of the + * CERTGeneralName pointed to by "nssAltName" and stores it at "pX500Name". + * + * PARAMETERS: + * "nssAltName" + * Address of CERTGeneralName. Must be non-NULL. + * "pX500Name" + * 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 GeneralName 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_pl_DirectoryName_Create( + CERTGeneralName *nssAltName, + PKIX_PL_X500Name **pX500Name, + void *plContext) +{ + PKIX_PL_X500Name *pkixDN = NULL; + CERTName *dirName = NULL; + PKIX_PL_String *pkixDNString = NULL; + char *utf8String = NULL; + + PKIX_ENTER(GENERALNAME, "pkix_pl_DirectoryName_Create"); + PKIX_NULLCHECK_TWO(nssAltName, pX500Name); + + dirName = &nssAltName->name.directoryName; + + PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName(NULL, dirName, + &pkixDN, plContext), + PKIX_X500NAMECREATEFROMCERTNAMEFAILED); + + *pX500Name = pkixDN; + +cleanup: + + PR_Free(utf8String); + PKIX_DECREF(pkixDNString); + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_Create + * DESCRIPTION: + * + * Creates new GeneralName which represents the CERTGeneralName pointed to by + * "nssAltName" and stores it at "pGenName". + * + * PARAMETERS: + * "nssAltName" + * Address of CERTGeneralName. Must be non-NULL. + * "pGenName" + * 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 GeneralName 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_pl_GeneralName_Create( + CERTGeneralName *nssAltName, + PKIX_PL_GeneralName **pGenName, + void *plContext) +{ + PKIX_PL_GeneralName *genName = NULL; + PKIX_PL_X500Name *pkixDN = NULL; + PKIX_PL_OID *pkixOID = NULL; + OtherName *otherName = NULL; + CERTGeneralNameList *nssGenNameList = NULL; + CERTGeneralNameType nameType; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create"); + PKIX_NULLCHECK_TWO(nssAltName, pGenName); + + /* create a PKIX_PL_GeneralName object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_GENERALNAME_TYPE, + sizeof (PKIX_PL_GeneralName), + (PKIX_PL_Object **)&genName, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + nameType = nssAltName->type; + + /* + * We use CERT_CreateGeneralNameList to create just one CERTGeneralName + * item for memory allocation reason. If we want to just create one + * item, we have to use the calling path CERT_NewGeneralName, then + * CERT_CopyOneGeneralName. With this calling path, if we pass + * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent + * call to CERT_CopyName, it assumes arena should be valid, hence + * segmentation error (not sure this is a NSS bug, certainly it is + * not consistent). But on the other hand, we don't want to keep an + * arena record here explicitely for every PKIX_PL_GeneralName. + * So I concluded it is better to use CERT_CreateGeneralNameList, + * which keeps an arena pointer in its data structure and also masks + * out details calls from this libpkix level. + */ + + PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n"); + nssGenNameList = CERT_CreateGeneralNameList(nssAltName); + + if (nssGenNameList == NULL) { + PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED); + } + + genName->nssGeneralNameList = nssGenNameList; + + /* initialize fields */ + genName->type = nameType; + genName->directoryName = NULL; + genName->OthName = NULL; + genName->other = NULL; + genName->oid = NULL; + + switch (nameType){ + case certOtherName: + + PKIX_CHECK(pkix_pl_OtherName_Create + (nssAltName, &otherName, plContext), + PKIX_OTHERNAMECREATEFAILED); + + genName->OthName = otherName; + break; + + case certDirectoryName: + + PKIX_CHECK(pkix_pl_DirectoryName_Create + (nssAltName, &pkixDN, plContext), + PKIX_DIRECTORYNAMECREATEFAILED); + + genName->directoryName = pkixDN; + break; + case certRegisterID: + PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other, + &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + + genName->oid = pkixOID; + break; + case certDNSName: + case certEDIPartyName: + case certIPAddress: + case certRFC822Name: + case certX400Address: + case certURI: + genName->other = SECITEM_DupItem(&nssAltName->name.other); + if (!genName->other) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + break; + default: + PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED); + } + + *pGenName = genName; + genName = NULL; + +cleanup: + PKIX_DECREF(genName); + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the GeneralName + * pointed to by "name" and stores it at "pString" Different mechanisms are + * used to create the string, depending on the type of the GeneralName. + * + * PARAMETERS + * "name" + * Address of GeneralName whose string representation is desired. + * Must be non-NULL. + * "pString" + * 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 GeneralName 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_pl_GeneralName_ToString_Helper( + PKIX_PL_GeneralName *name, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_X500Name *pkixDN = NULL; + PKIX_PL_OID *pkixOID = NULL; + char *x400AsciiName = NULL; + char *ediPartyName = NULL; + char *asciiName = NULL; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper"); + PKIX_NULLCHECK_TWO(name, pString); + + switch (name->type) { + case certRFC822Name: + case certDNSName: + case certURI: + /* + * Note that we can't use PKIX_ESCASCII here because + * name->other->data is not guaranteed to be null-terminated. + */ + + PKIX_NULLCHECK_ONE(name->other); + + PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8, + (name->other)->data, + (name->other)->len, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + break; + case certEDIPartyName: + /* XXX print out the actual bytes */ + ediPartyName = "EDIPartyName: <DER-encoded value>"; + PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, + ediPartyName, + 0, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + break; + case certX400Address: + /* XXX print out the actual bytes */ + x400AsciiName = "X400Address: <DER-encoded value>"; + PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, + x400AsciiName, + 0, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + break; + case certIPAddress: + PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii + (name->other, &asciiName, plContext), + PKIX_IPADDRBYTES2ASCIIFAILED); + + PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII, + asciiName, + 0, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + break; + case certOtherName: + PKIX_NULLCHECK_ONE(name->OthName); + + /* we only print type-id - don't know how to print value */ + /* XXX print out the bytes of the value */ + PKIX_CHECK(pkix_pl_oidBytes2Ascii + (&name->OthName->oid, &asciiName, plContext), + PKIX_OIDBYTES2ASCIIFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiName, + 0, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + break; + case certRegisterID: + pkixOID = name->oid; + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)pkixOID, pString, plContext), + PKIX_OIDTOSTRINGFAILED); + break; + case certDirectoryName: + pkixDN = name->directoryName; + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object *)pkixDN, pString, plContext), + PKIX_X500NAMETOSTRINGFAILED); + break; + default: + PKIX_ERROR + (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED); + } + +cleanup: + + PKIX_FREE(asciiName); + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_GeneralName_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_GeneralName *name = NULL; + SECItem secItemName; + SECItem secItemOID; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext), + PKIX_OBJECTNOTGENERALNAME); + + name = (PKIX_PL_GeneralName *)object; + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(name->other, PR_TRUE); + name->other = NULL; + + if (name->OthName){ + secItemName = name->OthName->name; + secItemOID = name->OthName->oid; + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&secItemName, PR_FALSE); + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&secItemOID, PR_FALSE); + + PKIX_FREE(name->OthName); + name->OthName = NULL; + } + + if (name->nssGeneralNameList != NULL) { + PKIX_GENERALNAME_DEBUG + ("\t\tCalling CERT_DestroyGeneralNameList).\n"); + CERT_DestroyGeneralNameList(name->nssGeneralNameList); + } + + PKIX_DECREF(name->directoryName); + PKIX_DECREF(name->oid); + +cleanup: + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_GeneralName_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *nameString = NULL; + PKIX_PL_GeneralName *name = NULL; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext), + PKIX_OBJECTNOTGENERALNAME); + + name = (PKIX_PL_GeneralName *)object; + + PKIX_CHECK(pkix_pl_GeneralName_ToString_Helper + (name, &nameString, plContext), + PKIX_GENERALNAMETOSTRINGHELPERFAILED); + + *pString = nameString; + +cleanup: + + + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_GeneralName_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_GeneralName *name = NULL; + PKIX_UInt32 firstHash, secondHash, nameHash; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext), + PKIX_OBJECTNOTGENERALNAME); + + name = (PKIX_PL_GeneralName *)object; + + switch (name->type) { + case certRFC822Name: + case certDNSName: + case certX400Address: + case certEDIPartyName: + case certURI: + case certIPAddress: + PKIX_NULLCHECK_ONE(name->other); + PKIX_CHECK(pkix_hash + ((const unsigned char *) + name->other->data, + name->other->len, + &nameHash, + plContext), + PKIX_HASHFAILED); + break; + case certRegisterID: + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *)name->oid, + &nameHash, + plContext), + PKIX_OIDHASHCODEFAILED); + break; + case certOtherName: + PKIX_NULLCHECK_ONE(name->OthName); + PKIX_CHECK(pkix_hash + ((const unsigned char *) + name->OthName->oid.data, + name->OthName->oid.len, + &firstHash, + plContext), + PKIX_HASHFAILED); + + PKIX_CHECK(pkix_hash + ((const unsigned char *) + name->OthName->name.data, + name->OthName->name.len, + &secondHash, + plContext), + PKIX_HASHFAILED); + + nameHash = firstHash + secondHash; + break; + case certDirectoryName: + PKIX_CHECK(PKIX_PL_Object_Hashcode + ((PKIX_PL_Object *) + name->directoryName, + &nameHash, + plContext), + PKIX_X500NAMEHASHCODEFAILED); + break; + } + + *pHashcode = nameHash; + +cleanup: + + PKIX_RETURN(GENERALNAME); + +} + +/* + * FUNCTION: pkix_pl_GeneralName_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_GeneralName_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_GeneralName *firstName = NULL; + PKIX_PL_GeneralName *secondName = NULL; + PKIX_UInt32 secondType; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a GeneralName */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_GENERALNAME_TYPE, plContext), + PKIX_FIRSTOBJECTNOTGENERALNAME); + + /* + * Since we know firstObject is a GeneralName, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a GeneralName, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_GENERALNAME_TYPE){ + goto cleanup; + } + + firstName = (PKIX_PL_GeneralName *)firstObject; + secondName = (PKIX_PL_GeneralName *)secondObject; + + if (firstName->type != secondName->type){ + goto cleanup; + } + + switch (firstName->type) { + case certRFC822Name: + case certDNSName: + case certX400Address: + case certEDIPartyName: + case certURI: + case certIPAddress: + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); + if (SECITEM_CompareItem(firstName->other, + secondName->other) != SECEqual) { + goto cleanup; + } + break; + case certRegisterID: + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstName->oid, + (PKIX_PL_Object *)secondName->oid, + pResult, + plContext), + PKIX_OIDEQUALSFAILED); + goto cleanup; + case certOtherName: + PKIX_NULLCHECK_TWO(firstName->OthName, secondName->OthName); + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); + if (SECITEM_CompareItem(&firstName->OthName->oid, + &secondName->OthName->oid) + != SECEqual || + SECITEM_CompareItem(&firstName->OthName->name, + &secondName->OthName->name) + != SECEqual) { + goto cleanup; + } + break; + case certDirectoryName: + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object *)firstName->directoryName, + (PKIX_PL_Object *)secondName->directoryName, + pResult, + plContext), + PKIX_X500NAMEEQUALSFAILED); + goto cleanup; + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(GENERALNAME); +} + +/* + * FUNCTION: pkix_pl_GeneralName_RegisterSelf + * DESCRIPTION: + * Registers PKIX_GENERALNAME_TYPE and 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_pl_GeneralName_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_RegisterSelf"); + + entry.description = "GeneralName"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_GeneralName); + entry.destructor = pkix_pl_GeneralName_Destroy; + entry.equalsFunction = pkix_pl_GeneralName_Equals; + entry.hashcodeFunction = pkix_pl_GeneralName_Hashcode; + entry.toStringFunction = pkix_pl_GeneralName_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_GENERALNAME_TYPE] = entry; + + PKIX_RETURN(GENERALNAME); +} + +/* --Public-Functions------------------------------------------------------- */ + +#ifdef BUILD_LIBPKIX_TESTS +/* + * FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_GeneralName_Create( + PKIX_UInt32 nameType, + PKIX_PL_String *stringRep, + PKIX_PL_GeneralName **pGName, + void *plContext) +{ + PKIX_PL_X500Name *pkixDN = NULL; + PKIX_PL_OID *pkixOID = NULL; + SECItem *secItem = NULL; + char *asciiString = NULL; + PKIX_UInt32 length = 0; + PKIX_PL_GeneralName *genName = NULL; + CERTGeneralName *nssGenName = NULL; + CERTGeneralNameList *nssGenNameList = NULL; + CERTName *nssCertName = NULL; + PLArenaPool *arena = NULL; + + PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create"); + PKIX_NULLCHECK_TWO(pGName, stringRep); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stringRep, + PKIX_ESCASCII, + (void **)&asciiString, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + /* Create a temporary CERTGeneralName */ + PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n"); + length = PL_strlen(asciiString); + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n"); + secItem = SECITEM_AllocItem(NULL, NULL, length); + PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy(secItem->data, asciiString, length); + PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n"); + nssGenName = CERT_NewGeneralName(arena, nameType); + if (nssGenName == NULL) { + PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED); + } + + switch (nameType) { + case certRFC822Name: + case certDNSName: + case certURI: + nssGenName->name.other = *secItem; + break; + + case certDirectoryName: + + PKIX_CHECK(PKIX_PL_X500Name_Create + (stringRep, &pkixDN, plContext), + PKIX_X500NAMECREATEFAILED); + + PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n"); + nssCertName = CERT_AsciiToName(asciiString); + nssGenName->name.directoryName = *nssCertName; + break; + + case certRegisterID: + PKIX_CHECK(PKIX_PL_OID_Create + (asciiString, &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + nssGenName->name.other = *secItem; + break; + default: + /* including IPAddress, EDIPartyName, OtherName, X400Address */ + PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE); + } + + /* create a PKIX_PL_GeneralName object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_GENERALNAME_TYPE, + sizeof (PKIX_PL_GeneralName), + (PKIX_PL_Object **)&genName, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* create a CERTGeneralNameList */ + nssGenName->type = nameType; + PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n"); + nssGenNameList = CERT_CreateGeneralNameList(nssGenName); + if (nssGenNameList == NULL) { + PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED); + } + genName->nssGeneralNameList = nssGenNameList; + + /* initialize fields */ + genName->type = nameType; + genName->directoryName = pkixDN; + genName->OthName = NULL; + genName->other = secItem; + genName->oid = pkixOID; + + *pGName = genName; +cleanup: + + PKIX_FREE(asciiString); + + if (nssCertName != NULL) { + PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n"); + CERT_DestroyName(nssCertName); + } + + if (arena){ /* will free nssGenName */ + PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(pkixDN); + PKIX_DECREF(pkixOID); + + PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + if (secItem){ + SECITEM_FreeItem(secItem, PR_TRUE); + secItem = NULL; + } + } + + PKIX_RETURN(GENERALNAME); +} + +#endif /* BUILD_LIBPKIX_TESTS */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h new file mode 100644 index 0000000000..3cb5264d51 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h @@ -0,0 +1,49 @@ +/* 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_pl_generalname.h + * + * GeneralName Object Definitions + * + */ + +#ifndef _PKIX_PL_GENERALNAME_H +#define _PKIX_PL_GENERALNAME_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_GeneralNameStruct{ + CERTGeneralNameList *nssGeneralNameList; + CERTGeneralNameType type; + PKIX_PL_X500Name *directoryName; + PKIX_PL_OID *oid; + OtherName *OthName; + SECItem *other; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_GeneralName_Create( + CERTGeneralName *nssAltName, + PKIX_PL_GeneralName **pGenName, + void *plContext); + +PKIX_Error * +pkix_pl_GeneralName_GetNssGeneralName( + PKIX_PL_GeneralName *genName, + CERTGeneralName **pNssGenName, + void *plContext); + +PKIX_Error *pkix_pl_GeneralName_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_GENERALNAME_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c new file mode 100644 index 0000000000..09b54a2be3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c @@ -0,0 +1,874 @@ +/* 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_pl_infoaccess.c + * + * InfoAccess Object Definitions + * + */ + +#include "pkix_pl_infoaccess.h" + +/* --Private-InfoAccess-Functions----------------------------------*/ + +/* + * FUNCTION: pkix_pl_InfoAccess_Create + * DESCRIPTION: + * + * This function creates an InfoAccess from the method provided in "method" and + * the GeneralName provided in "generalName" and stores the result at + * "pInfoAccess". + * + * PARAMETERS + * "method" + * The UInt32 value to be stored as the method field of the InfoAccess. + * "gName" + * The GeneralName to be stored as the gName field of the InfoAccess. + * Must be non-NULL. + * "pInfoAccess" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_pl_InfoAccess_Create( + PKIX_UInt32 method, + PKIX_PL_GeneralName *gName, + PKIX_PL_InfoAccess **pInfoAccess, + void *plContext) +{ + + PKIX_PL_InfoAccess *infoAccess = NULL; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Create"); + PKIX_NULLCHECK_TWO(gName, pInfoAccess); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_INFOACCESS_TYPE, + sizeof (PKIX_PL_InfoAccess), + (PKIX_PL_Object **)&infoAccess, + plContext), + PKIX_COULDNOTCREATEINFOACCESSOBJECT); + + infoAccess->method = method; + + PKIX_INCREF(gName); + infoAccess->location = gName; + + *pInfoAccess = infoAccess; + infoAccess = NULL; + +cleanup: + PKIX_DECREF(infoAccess); + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: pkix_pl_InfoAccess_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h) + */ +static PKIX_Error * +pkix_pl_InfoAccess_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_InfoAccess *infoAccess = NULL; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_INFOACCESS_TYPE, plContext), + PKIX_OBJECTNOTANINFOACCESS); + + infoAccess = (PKIX_PL_InfoAccess *)object; + + PKIX_DECREF(infoAccess->location); + +cleanup: + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: pkix_pl_InfoAccess_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h) + */ +static PKIX_Error * +pkix_pl_InfoAccess_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_InfoAccess *infoAccess; + PKIX_PL_String *infoAccessString = NULL; + char *asciiFormat = NULL; + char *asciiMethod = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *methodString = NULL; + PKIX_PL_String *locationString = NULL; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_INFOACCESS_TYPE, plContext), + PKIX_OBJECTNOTINFOACCESS); + + infoAccess = (PKIX_PL_InfoAccess *)object; + + asciiFormat = + "[" + "method:%s, " + "location:%s" + "]"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + switch(infoAccess->method) { + case PKIX_INFOACCESS_CA_ISSUERS: + asciiMethod = "caIssuers"; + break; + case PKIX_INFOACCESS_OCSP: + asciiMethod = "ocsp"; + break; + case PKIX_INFOACCESS_TIMESTAMPING: + asciiMethod = "timestamping"; + break; + case PKIX_INFOACCESS_CA_REPOSITORY: + asciiMethod = "caRepository"; + break; + default: + asciiMethod = "unknown"; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiMethod, + 0, + &methodString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING(infoAccess->location, &locationString, plContext, + PKIX_GENERALNAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&infoAccessString, + plContext, + formatString, + methodString, + locationString), + PKIX_SPRINTFFAILED); + + *pString = infoAccessString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(methodString); + PKIX_DECREF(locationString); + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: pkix_pl_InfoAccess_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h) + */ +static PKIX_Error * +pkix_pl_InfoAccess_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_InfoAccess *infoAccess = NULL; + PKIX_UInt32 infoAccessHash; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_INFOACCESS_TYPE, plContext), + PKIX_OBJECTNOTINFOACCESS); + + infoAccess = (PKIX_PL_InfoAccess *)object; + + PKIX_HASHCODE(infoAccess->location, &infoAccessHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + infoAccessHash += (infoAccess->method << 7); + + *pHashcode = infoAccessHash; + +cleanup: + + PKIX_RETURN(INFOACCESS); + +} + +/* + * FUNCTION: pkix_pl_InfoAccess_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h) + */ +static PKIX_Error * +pkix_pl_InfoAccess_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_InfoAccess *firstInfoAccess = NULL; + PKIX_PL_InfoAccess *secondInfoAccess = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a InfoAccess */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_INFOACCESS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTINFOACCESS); + + /* + * Since we know firstObject is a InfoAccess, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a InfoAccess, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_INFOACCESS_TYPE) goto cleanup; + + firstInfoAccess = (PKIX_PL_InfoAccess *)firstObject; + secondInfoAccess = (PKIX_PL_InfoAccess *)secondObject; + + *pResult = PKIX_FALSE; + + if (firstInfoAccess->method != secondInfoAccess->method) { + goto cleanup; + } + + PKIX_EQUALS(firstInfoAccess, secondInfoAccess, &cmpResult, plContext, + PKIX_OBJECTEQUALSFAILED); + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: pkix_pl_InfoAccess_RegisterSelf + * DESCRIPTION: + * Registers PKIX_INFOACCESS_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_pl_InfoAccess_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(INFOACCESS, + "pkix_pl_InfoAccess_RegisterSelf"); + + entry.description = "InfoAccess"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_InfoAccess); + entry.destructor = pkix_pl_InfoAccess_Destroy; + entry.equalsFunction = pkix_pl_InfoAccess_Equals; + entry.hashcodeFunction = pkix_pl_InfoAccess_Hashcode; + entry.toStringFunction = pkix_pl_InfoAccess_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_INFOACCESS_TYPE] = entry; + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: pkix_pl_InfoAccess_CreateList + * DESCRIPTION: + * + * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function + * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList". + * + * PARAMETERS + * "nssInfoAccess" + * The pointer array of CERTAuthInfoAccess that contains access data. + * May be NULL. + * "pInfoAccessList" + * Address where a list of PKIX_PL_InfoAccess 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_InfoAccess_CreateList( + CERTAuthInfoAccess **nssInfoAccess, + PKIX_List **pInfoAccessList, /* of PKIX_PL_InfoAccess */ + void *plContext) +{ + PKIX_List *infoAccessList = NULL; + PKIX_PL_InfoAccess *infoAccess = NULL; + PKIX_PL_GeneralName *location = NULL; + PKIX_UInt32 method; + int i; + + PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_CreateList"); + PKIX_NULLCHECK_ONE(pInfoAccessList); + + PKIX_CHECK(PKIX_List_Create(&infoAccessList, plContext), + PKIX_LISTCREATEFAILED); + + if (nssInfoAccess == NULL) { + goto cleanup; + } + + for (i = 0; nssInfoAccess[i] != NULL; i++) { + + if (nssInfoAccess[i]->location == NULL) { + continue; + } + + PKIX_CHECK(pkix_pl_GeneralName_Create + (nssInfoAccess[i]->location, &location, plContext), + PKIX_GENERALNAMECREATEFAILED); + + PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n"); + method = SECOID_FindOIDTag(&nssInfoAccess[i]->method); + /* Map NSS access method value into PKIX constant */ + switch(method) { + case SEC_OID_PKIX_CA_ISSUERS: + method = PKIX_INFOACCESS_CA_ISSUERS; + break; + case SEC_OID_PKIX_OCSP: + method = PKIX_INFOACCESS_OCSP; + break; + case SEC_OID_PKIX_TIMESTAMPING: + method = PKIX_INFOACCESS_TIMESTAMPING; + break; + case SEC_OID_PKIX_CA_REPOSITORY: + method = PKIX_INFOACCESS_CA_REPOSITORY; + break; + default: + PKIX_ERROR(PKIX_UNKNOWNINFOACCESSMETHOD); + } + + PKIX_CHECK(pkix_pl_InfoAccess_Create + (method, location, &infoAccess, plContext), + PKIX_INFOACCESSCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (infoAccessList, + (PKIX_PL_Object *)infoAccess, + plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(infoAccess); + PKIX_DECREF(location); + } + + *pInfoAccessList = infoAccessList; + infoAccessList = NULL; + +cleanup: + + PKIX_DECREF(infoAccessList); + PKIX_DECREF(infoAccess); + PKIX_DECREF(location); + + PKIX_RETURN(INFOACCESS); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_InfoAccess_GetMethod( + PKIX_PL_InfoAccess *infoAccess, + PKIX_UInt32 *pMethod, + void *plContext) +{ + PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetMethod"); + PKIX_NULLCHECK_TWO(infoAccess, pMethod); + + *pMethod = infoAccess->method; + + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_InfoAccess_GetLocation( + PKIX_PL_InfoAccess *infoAccess, + PKIX_PL_GeneralName **pLocation, + void *plContext) +{ + PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocation"); + PKIX_NULLCHECK_TWO(infoAccess, pLocation); + + PKIX_INCREF(infoAccess->location); + + *pLocation = infoAccess->location; + +cleanup: + PKIX_RETURN(INFOACCESS); +} + +/* + * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_InfoAccess_GetLocationType( + PKIX_PL_InfoAccess *infoAccess, + PKIX_UInt32 *pType, + void *plContext) +{ + PKIX_PL_String *locationString = NULL; + PKIX_UInt32 type = PKIX_INFOACCESS_LOCATION_UNKNOWN; + PKIX_UInt32 len = 0; + void *location = NULL; + + PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocationType"); + PKIX_NULLCHECK_TWO(infoAccess, pType); + + if (infoAccess->location != NULL) { + + PKIX_TOSTRING(infoAccess->location, &locationString, plContext, + PKIX_GENERALNAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (locationString, PKIX_ESCASCII, &location, &len, plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n"); +#ifndef NSS_PKIX_NO_LDAP + if (PORT_Strncmp(location, "ldap:", 5) == 0){ + type = PKIX_INFOACCESS_LOCATION_LDAP; + } else +#endif + if (PORT_Strncmp(location, "http:", 5) == 0){ + type = PKIX_INFOACCESS_LOCATION_HTTP; + } + } + + *pType = type; + +cleanup: + + PKIX_PL_Free(location, plContext); + PKIX_DECREF(locationString); + + PKIX_RETURN(INFOACCESS); +} + +#ifndef NSS_PKIX_NO_LDAP +/* + * FUNCTION: pkix_pl_InfoAccess_ParseTokens + * DESCRIPTION: + * + * This function parses the string beginning at "startPos" into tokens using + * the separator contained in "separator" and the terminator contained in + * "terminator", copying the tokens into space allocated from the arena + * pointed to by "arena". It stores in "tokens" a null-terminated array of + * pointers to those tokens. + * + * PARAMETERS + * "arena" + * Address of a PLArenaPool to be used in populating the LDAPLocation. + * Must be non-NULL. + * "startPos" + * The address of char string that contains a subset of ldap location. + * "tokens" + * The address of an array of char string for storing returned tokens. + * Must be non-NULL. + * "separator" + * The character that is taken as token separator. Must be non-NULL. + * "terminator" + * The character that is taken as parsing terminator. 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 InfoAccess 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_pl_InfoAccess_ParseTokens( + PLArenaPool *arena, + char **startPos, /* return update */ + char ***tokens, + char separator, + char terminator, + void *plContext) +{ + PKIX_UInt32 numFilters = 0; + char *endPos = NULL; + char **filterP = NULL; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseTokens"); + PKIX_NULLCHECK_THREE(arena, startPos, tokens); + + endPos = *startPos; + + /* First pass: parse to <terminator> to count number of components */ + numFilters = 0; + while (*endPos != terminator && *endPos != '\0') { + endPos++; + if (*endPos == separator) { + numFilters++; + } + } + + if (*endPos != terminator) { + PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED); + } + + /* Last component doesn't need a separator, although we allow it */ + if (endPos > *startPos && *(endPos-1) != separator) { + numFilters++; + } + + /* + * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter, + * and everything else for the base + */ + if (numFilters > 2) numFilters = 2; + + filterP = PORT_ArenaZNewArray(arena, char*, numFilters+1); + if (filterP == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + /* Second pass: parse to fill in components in token array */ + *tokens = filterP; + endPos = *startPos; + + while (numFilters) { + if (*endPos == separator || *endPos == terminator) { + PKIX_UInt32 len = endPos - *startPos; + char *p = PORT_ArenaZAlloc(arena, len+1); + if (p == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + PORT_Memcpy(p, *startPos, len); + p[len] = '\0'; + + *filterP = p; + filterP++; + numFilters--; + + separator = terminator; + + if (*endPos == '\0') { + *startPos = endPos; + break; + } else { + endPos++; + *startPos = endPos; + continue; + } + } + endPos++; + } + + *filterP = NULL; + +cleanup: + + PKIX_RETURN(INFOACCESS); +} + +static int +pkix_pl_HexDigitToInt( + int ch) +{ + if (isdigit(ch)) { + ch = ch - '0'; + } else if (isupper(ch)) { + ch = ch - 'A' + 10; + } else { + ch = ch - 'a' + 10; + } + return ch; +} + +/* + * Convert the "%" hex hex escape sequences in the URL 'location' in place. + */ +static void +pkix_pl_UnescapeURL( + char *location) +{ + const char *src; + char *dst; + + for (src = dst = location; *src != '\0'; src++, dst++) { + if (*src == '%' && isxdigit((unsigned char)*(src+1)) && + isxdigit((unsigned char)*(src+2))) { + *dst = pkix_pl_HexDigitToInt((unsigned char)*(src+1)); + *dst *= 16; + *dst += pkix_pl_HexDigitToInt((unsigned char)*(src+2)); + src += 2; + } else { + *dst = *src; + } + } + *dst = *src; /* the terminating null */ +} + +/* + * FUNCTION: pkix_pl_InfoAccess_ParseLocation + * DESCRIPTION: + * + * This function parses the GeneralName pointed to by "generalName" into the + * fields of the LDAPRequestParams pointed to by "request" and a domainName + * pointed to by "pDomainName", using the PLArenaPool pointed to by "arena" to + * allocate storage for the request components and for the domainName string. + * + * The expected GeneralName string should be in the format described by the + * following BNF: + * + * ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]? + * [caCertificate|crossCertificatPair|certificateRevocationList]; + * [binary|<other-type>] + * [[,caCertificate|crossCertificatPair|certificateRevocationList] + * [binary|<other-type>]]* + * + * PARAMETERS + * "gName" + * Address of the GeneralName whose LDAPLocation is to be parsed. Must be + * non-NULL. + * "arena" + * Address of PLArenaPool to be used for the domainName and for components + * of the LDAPRequest. Must be non-NULL. + * "request" + * Address of the LDAPRequestParams into which request components are + * stored. Must be non-NULL. + * *pDomainName" + * Address at which the domainName 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 an InfoAccess 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_pl_InfoAccess_ParseLocation( + PKIX_PL_GeneralName *gName, + PLArenaPool *arena, + LDAPRequestParams *request, + char **pDomainName, + void *plContext) +{ + PKIX_PL_String *locationString = NULL; + PKIX_UInt32 len = 0; + PKIX_UInt32 ncIndex = 0; + char *domainName = NULL; + char **avaArray = NULL; + char **attrArray = NULL; + char *attr = NULL; + char *locationAscii = NULL; + char *startPos = NULL; + char *endPos = NULL; + char *avaPtr = NULL; + LdapAttrMask attrBit = 0; + LDAPNameComponent **setOfNameComponent = NULL; + LDAPNameComponent *nameComponent = NULL; + + PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseLocation"); + PKIX_NULLCHECK_FOUR(gName, arena, request, pDomainName); + + PKIX_TOSTRING(gName, &locationString, plContext, + PKIX_GENERALNAMETOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (locationString, + PKIX_ESCASCII, + (void **)&locationAscii, + &len, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + pkix_pl_UnescapeURL(locationAscii); + + /* Skip "ldap:" */ + endPos = locationAscii; + while (*endPos != ':' && *endPos != '\0') { + endPos++; + } + if (*endPos == '\0') { + PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE); + } + + /* Skip "//" */ + endPos++; + if (*endPos != '\0' && *(endPos+1) != '0' && + *endPos == '/' && *(endPos+1) == '/') { + endPos += 2; + } else { + PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH); + } + + /* Get the server-site */ + startPos = endPos; + while(*endPos != '/' && *(endPos) != '\0') { + endPos++; + } + if (*endPos == '\0') { + PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE); + } + + len = endPos - startPos; + endPos++; + + domainName = PORT_ArenaZAlloc(arena, len + 1); + if (!domainName) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + PORT_Memcpy(domainName, startPos, len); + + domainName[len] = '\0'; + + *pDomainName = domainName; + + /* + * Get a list of AttrValueAssertions (such as + * "cn=CommonName, o=Organization, c=US" into a null-terminated array + */ + startPos = endPos; + PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens + (arena, + &startPos, + (char ***) &avaArray, + ',', + '?', + plContext), + PKIX_INFOACCESSPARSETOKENSFAILED); + + /* Count how many AVAs we have */ + for (len = 0; avaArray[len] != NULL; len++) {} + + if (len < 2) { + PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME); + } + + /* Use last name component for baseObject */ + request->baseObject = avaArray[len - 1]; + + /* Use only one component for filter. LDAP servers aren't too smart. */ + len = 2; /* Eliminate this when servers get smarter. */ + + avaArray[len - 1] = NULL; + + /* Get room for null-terminated array of (LdapNameComponent *) */ + setOfNameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent *, len); + if (setOfNameComponent == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + /* Get room for the remaining LdapNameComponents */ + nameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent, --len); + if (nameComponent == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + /* Convert remaining AVAs to LDAPNameComponents */ + for (ncIndex = 0; ncIndex < len; ncIndex ++) { + setOfNameComponent[ncIndex] = nameComponent; + avaPtr = avaArray[ncIndex]; + nameComponent->attrType = (unsigned char *)avaPtr; + while ((*avaPtr != '=') && (*avaPtr != '\0')) { + avaPtr++; + if (*avaPtr == '\0') { + PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ); + } + } + *(avaPtr++) = '\0'; + nameComponent->attrValue = (unsigned char *)avaPtr; + nameComponent++; + } + + setOfNameComponent[len] = NULL; + request->nc = setOfNameComponent; + + /* + * Get a list of AttrTypes (such as + * "caCertificate;binary, crossCertificatePair;binary") into + * a null-terminated array + */ + + PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens + (arena, + (char **) &startPos, + (char ***) &attrArray, + ',', + '\0', + plContext), + PKIX_INFOACCESSPARSETOKENSFAILED); + + /* Convert array of Attr Types into a bit mask */ + request->attributes = 0; + attr = attrArray[0]; + while (attr != NULL) { + PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit + (attr, &attrBit, plContext), + PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED); + request->attributes |= attrBit; + attr = *(++attrArray); + } + +cleanup: + + PKIX_PL_Free(locationAscii, plContext); + PKIX_DECREF(locationString); + + PKIX_RETURN(INFOACCESS); +} +#endif /* !NSS_PKIX_NO_LDAP */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h new file mode 100644 index 0000000000..e69d7b4139 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h @@ -0,0 +1,49 @@ +/* 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_pl_infoaccess.h + * + * InfoAccess Object Definitions + * + */ + +#ifndef _PKIX_PL_INFOACCESS_H +#define _PKIX_PL_INFOACCESS_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_InfoAccessStruct{ + PKIX_UInt32 method; + PKIX_PL_GeneralName *location; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_InfoAccess_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_InfoAccess_CreateList( + CERTAuthInfoAccess **authInfoAccess, + PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */ + void *plContext); + +#ifndef NSS_PKIX_NO_LDAP +PKIX_Error * +pkix_pl_InfoAccess_ParseLocation( + PKIX_PL_GeneralName *generalName, + PLArenaPool *arena, + LDAPRequestParams *request, + char **pDomainName, + void *plContext); +#endif /* !NSS_PKIX_NO_LDAP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_INFOACCESS_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c new file mode 100644 index 0000000000..1d0b61bb44 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c @@ -0,0 +1,1279 @@ +/* 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_pl_nameconstraints.c + * + * Name Constraints Object Functions Definitions + * + */ + +#include "pkix_pl_nameconstraints.h" + + +/* --Private-NameConstraints-Functions----------------------------- */ + +/* + * FUNCTION: pkix_pl_CertNameConstraints_GetPermitted + * DESCRIPTION: + * + * This function retrieve name constraints permitted list from NSS + * data in "nameConstraints" and returns a PKIX_PL_GeneralName list + * in "pPermittedList". + * + * PARAMETERS + * "nameConstraints" + * Address of CertNameConstraints which has a pointer to + * CERTNameConstraints data. Must be non-NULL. + * "pPermittedList" + * Address where returned permitted name list 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 NameConstraints 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_pl_CertNameConstraints_GetPermitted( + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_List **pPermittedList, + void *plContext) +{ + CERTNameConstraints *nssNameConstraints = NULL; + CERTNameConstraints **nssNameConstraintsList = NULL; + CERTNameConstraint *nssPermitted = NULL; + CERTNameConstraint *firstPermitted = NULL; + PKIX_List *permittedList = NULL; + PKIX_PL_GeneralName *name = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_GetPermitted"); + PKIX_NULLCHECK_TWO(nameConstraints, pPermittedList); + + /* + * nssNameConstraints is an array of CERTNameConstraints + * pointers where CERTNameConstraints keep its permitted and excluded + * lists as pointer array of CERTNameConstraint. + */ + + if (nameConstraints->permittedList == NULL) { + + PKIX_OBJECT_LOCK(nameConstraints); + + if (nameConstraints->permittedList == NULL) { + + PKIX_CHECK(PKIX_List_Create(&permittedList, plContext), + PKIX_LISTCREATEFAILED); + + numItems = nameConstraints->numNssNameConstraints; + nssNameConstraintsList = + nameConstraints->nssNameConstraintsList; + + for (i = 0; i < numItems; i++) { + + PKIX_NULLCHECK_ONE(nssNameConstraintsList); + nssNameConstraints = *(nssNameConstraintsList + i); + PKIX_NULLCHECK_ONE(nssNameConstraints); + + if (nssNameConstraints->permited != NULL) { + + nssPermitted = nssNameConstraints->permited; + firstPermitted = nssPermitted; + + do { + + PKIX_CHECK(pkix_pl_GeneralName_Create + (&nssPermitted->name, &name, plContext), + PKIX_GENERALNAMECREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (permittedList, + (PKIX_PL_Object *)name, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(name); + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_GetNextNameConstraint\n"); + nssPermitted = CERT_GetNextNameConstraint + (nssPermitted); + + } while (nssPermitted != firstPermitted); + + } + } + + PKIX_CHECK(PKIX_List_SetImmutable(permittedList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + nameConstraints->permittedList = permittedList; + + } + + PKIX_OBJECT_UNLOCK(nameConstraints); + + } + + PKIX_INCREF(nameConstraints->permittedList); + + *pPermittedList = nameConstraints->permittedList; + +cleanup: + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_GetExcluded + * DESCRIPTION: + * + * This function retrieve name constraints excluded list from NSS + * data in "nameConstraints" and returns a PKIX_PL_GeneralName list + * in "pExcludedList". + * + * PARAMETERS + * "nameConstraints" + * Address of CertNameConstraints which has a pointer to NSS data. + * Must be non-NULL. + * "pPermittedList" + * Address where returned excluded name list 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 NameConstraints 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_pl_CertNameConstraints_GetExcluded( + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_List **pExcludedList, + void *plContext) +{ + CERTNameConstraints *nssNameConstraints = NULL; + CERTNameConstraints **nssNameConstraintsList = NULL; + CERTNameConstraint *nssExcluded = NULL; + CERTNameConstraint *firstExcluded = NULL; + PKIX_List *excludedList = NULL; + PKIX_PL_GeneralName *name = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_GetExcluded"); + PKIX_NULLCHECK_TWO(nameConstraints, pExcludedList); + + if (nameConstraints->excludedList == NULL) { + + PKIX_OBJECT_LOCK(nameConstraints); + + if (nameConstraints->excludedList == NULL) { + + PKIX_CHECK(PKIX_List_Create(&excludedList, plContext), + PKIX_LISTCREATEFAILED); + + numItems = nameConstraints->numNssNameConstraints; + nssNameConstraintsList = + nameConstraints->nssNameConstraintsList; + + for (i = 0; i < numItems; i++) { + + PKIX_NULLCHECK_ONE(nssNameConstraintsList); + nssNameConstraints = *(nssNameConstraintsList + i); + PKIX_NULLCHECK_ONE(nssNameConstraints); + + if (nssNameConstraints->excluded != NULL) { + + nssExcluded = nssNameConstraints->excluded; + firstExcluded = nssExcluded; + + do { + + PKIX_CHECK(pkix_pl_GeneralName_Create + (&nssExcluded->name, &name, plContext), + PKIX_GENERALNAMECREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (excludedList, + (PKIX_PL_Object *)name, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(name); + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_GetNextNameConstraint\n"); + nssExcluded = CERT_GetNextNameConstraint + (nssExcluded); + + } while (nssExcluded != firstExcluded); + + } + + } + PKIX_CHECK(PKIX_List_SetImmutable(excludedList, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + nameConstraints->excludedList = excludedList; + + } + + PKIX_OBJECT_UNLOCK(nameConstraints); + } + + PKIX_INCREF(nameConstraints->excludedList); + + *pExcludedList = nameConstraints->excludedList; + +cleanup: + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_CheckNameSpaceNssNames + * DESCRIPTION: + * + * This function checks if CERTGeneralNames in "nssSubjectNames" comply + * with the permitted and excluded names in "nameConstraints". It returns + * PKIX_TRUE in "pCheckPass", if the Names satify the name space of the + * permitted list and if the Names are not in the excluded list. Otherwise, + * it returns PKIX_FALSE. + * + * PARAMETERS + * "nssSubjectNames" + * List of CERTGeneralName that nameConstraints verification is based on. + * "nameConstraints" + * Address of CertNameConstraints that provides lists of permitted + * and excluded names. Must be non-NULL. + * "pCheckPass" + * Address where PKIX_TRUE is returned if the all names in "nameList" are + * valid. + * "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 NameConstraints 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_pl_CertNameConstraints_CheckNameSpaceNssNames( + CERTGeneralName *nssSubjectNames, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean *pCheckPass, + void *plContext) +{ + CERTNameConstraints **nssNameConstraintsList = NULL; + CERTNameConstraints *nssNameConstraints = NULL; + CERTGeneralName *nssMatchName = NULL; + PLArenaPool *arena = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + SECStatus status = SECSuccess; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_CheckNameSpaceNssNames"); + PKIX_NULLCHECK_THREE(nssSubjectNames, nameConstraints, pCheckPass); + + *pCheckPass = PKIX_TRUE; + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + nssMatchName = nssSubjectNames; + nssNameConstraintsList = nameConstraints->nssNameConstraintsList; + + /* + * CERTNameConstraint items in each permitted or excluded list + * is verified as OR condition. That means, if one item matched, + * then the checking on the remaining items on the list is skipped. + * (see NSS cert_CompareNameWithConstraints(...)). + * Items on PKIX_PL_NameConstraint's nssNameConstraints are verified + * as AND condition. PKIX_PL_NameConstraint keeps an array of pointers + * of CERTNameConstraints resulting from merging multiple + * PKIX_PL_NameConstraints. Since each CERTNameConstraint are created + * for different entity, a union condition of these entities then is + * performed. + */ + + do { + + numItems = nameConstraints->numNssNameConstraints; + + for (i = 0; i < numItems; i++) { + + PKIX_NULLCHECK_ONE(nssNameConstraintsList); + nssNameConstraints = *(nssNameConstraintsList + i); + PKIX_NULLCHECK_ONE(nssNameConstraints); + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_CheckNameSpace\n"); + status = CERT_CheckNameSpace + (arena, nssNameConstraints, nssMatchName); + if (status != SECSuccess) { + break; + } + + } + + if (status != SECSuccess) { + break; + } + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_GetNextGeneralName\n"); + nssMatchName = CERT_GetNextGeneralName(nssMatchName); + + } while (nssMatchName != nssSubjectNames); + + if (status == SECFailure) { + + *pCheckPass = PKIX_FALSE; + } + +cleanup: + + if (arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_NameConstraints_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertNameConstraints_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext), + PKIX_OBJECTNOTCERTNAMECONSTRAINTS); + + nameConstraints = (PKIX_PL_CertNameConstraints *)object; + + PKIX_CHECK(PKIX_PL_Free + (nameConstraints->nssNameConstraintsList, plContext), + PKIX_FREEFAILED); + + if (nameConstraints->arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(nameConstraints->arena, PR_FALSE); + nameConstraints->arena = NULL; + } + + PKIX_DECREF(nameConstraints->permittedList); + PKIX_DECREF(nameConstraints->excludedList); + +cleanup: + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the object + * NameConstraints and stores it at "pString". + * + * PARAMETERS + * "nameConstraints" + * Address of CertNameConstraints whose string representation is + * desired. Must be non-NULL. + * "pString" + * Address where string 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 NameConstraints 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_pl_CertNameConstraints_ToString_Helper( + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_PL_String **pString, + void *plContext) +{ + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_List *permittedList = NULL; + PKIX_List *excludedList = NULL; + PKIX_PL_String *permittedListString = NULL; + PKIX_PL_String *excludedListString = NULL; + PKIX_PL_String *nameConstraintsString = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_ToString_Helper"); + PKIX_NULLCHECK_TWO(nameConstraints, pString); + + asciiFormat = + "[\n" + "\t\tPermitted Name: %s\n" + "\t\tExcluded Name: %s\n" + "\t]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted + (nameConstraints, &permittedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED); + + PKIX_TOSTRING(permittedList, &permittedListString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded + (nameConstraints, &excludedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED); + + PKIX_TOSTRING(excludedList, &excludedListString, plContext, + PKIX_LISTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&nameConstraintsString, + plContext, + formatString, + permittedListString, + excludedListString), + PKIX_SPRINTFFAILED); + + *pString = nameConstraintsString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(permittedList); + PKIX_DECREF(excludedList); + PKIX_DECREF(permittedListString); + PKIX_DECREF(excludedListString); + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertNameConstraints_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *nameConstraintsString = NULL; + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType( + object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext), + PKIX_OBJECTNOTCERTNAMECONSTRAINTS); + + nameConstraints = (PKIX_PL_CertNameConstraints *)object; + + PKIX_CHECK(pkix_pl_CertNameConstraints_ToString_Helper + (nameConstraints, &nameConstraintsString, plContext), + PKIX_CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED); + + *pString = nameConstraintsString; + +cleanup: + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertNameConstraints_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + PKIX_List *permittedList = NULL; + PKIX_List *excludedList = NULL; + PKIX_UInt32 permitHash = 0; + PKIX_UInt32 excludeHash = 0; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType + (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext), + PKIX_OBJECTNOTCERTNAMECONSTRAINTS); + + nameConstraints = (PKIX_PL_CertNameConstraints *)object; + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted + (nameConstraints, &permittedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED); + + PKIX_HASHCODE(permittedList, &permitHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded + (nameConstraints, &excludedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED); + + PKIX_HASHCODE(excludedList, &excludeHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + *pHashcode = (((permitHash << 7) + excludeHash) << 7) + + nameConstraints->numNssNameConstraints; + +cleanup: + + PKIX_DECREF(permittedList); + PKIX_DECREF(excludedList); + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_CertNameConstraints_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_CertNameConstraints *firstNC = NULL; + PKIX_PL_CertNameConstraints *secondNC = NULL; + PKIX_List *firstPermittedList = NULL; + PKIX_List *secondPermittedList = NULL; + PKIX_List *firstExcludedList = NULL; + PKIX_List *secondExcludedList = NULL; + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult = PKIX_FALSE; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a CertNameConstraints */ + PKIX_CHECK(pkix_CheckType + (firstObject, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext), + PKIX_FIRSTOBJECTNOTCERTNAMECONSTRAINTS); + + firstNC = (PKIX_PL_CertNameConstraints *)firstObject; + secondNC = (PKIX_PL_CertNameConstraints *)secondObject; + + /* + * Since we know firstObject is a CertNameConstraints, if both + * references are identical, they must be equal + */ + if (firstNC == secondNC){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondNC isn't a CertNameConstraints, 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 *)secondNC, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + if (secondType != PKIX_CERTNAMECONSTRAINTS_TYPE) { + goto cleanup; + } + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted + (firstNC, &firstPermittedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED); + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted + (secondNC, &secondPermittedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED); + + PKIX_EQUALS + (firstPermittedList, secondPermittedList, &cmpResult, plContext, + PKIX_OBJECTEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded + (firstNC, &firstExcludedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED); + + PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded + (secondNC, &secondExcludedList, plContext), + PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED); + + PKIX_EQUALS + (firstExcludedList, secondExcludedList, &cmpResult, plContext, + PKIX_OBJECTEQUALSFAILED); + + if (cmpResult != PKIX_TRUE) { + goto cleanup; + } + + /* + * numNssNameConstraints is not checked because it is basically a + * merge count, it cannot determine the data equality. + */ + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_DECREF(firstPermittedList); + PKIX_DECREF(secondPermittedList); + PKIX_DECREF(firstExcludedList); + PKIX_DECREF(secondExcludedList); + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_RegisterSelf + * DESCRIPTION: + * Registers PKIX_CERTNAMECONSTRAINTS_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_pl_CertNameConstraints_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_RegisterSelf"); + + entry.description = "CertNameConstraints"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_CertNameConstraints); + entry.destructor = pkix_pl_CertNameConstraints_Destroy; + entry.equalsFunction = pkix_pl_CertNameConstraints_Equals; + entry.hashcodeFunction = pkix_pl_CertNameConstraints_Hashcode; + entry.toStringFunction = pkix_pl_CertNameConstraints_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_CERTNAMECONSTRAINTS_TYPE] = entry; + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_Create_Helper + * + * DESCRIPTION: + * This function retrieves name constraints in "nssNameConstraints", + * converts and stores the result in a PKIX_PL_CertNameConstraints object. + * + * PARAMETERS + * "nssNameConstraints" + * Address of CERTNameConstraints that contains this object's data. + * Must be non-NULL. + * "pNameConstraints" + * Address where object pointer will be stored. Must be non-NULL. + * A NULL value will be returned if there is no Name Constraints extension. + * "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 NameConstraints 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_pl_CertNameConstraints_Create_Helper( + CERTNameConstraints *nssNameConstraints, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + CERTNameConstraints **nssNameConstraintPtr = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_Create_Helper"); + PKIX_NULLCHECK_TWO(nssNameConstraints, pNameConstraints); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CERTNAMECONSTRAINTS_TYPE, + sizeof (PKIX_PL_CertNameConstraints), + (PKIX_PL_Object **)&nameConstraints, + plContext), + PKIX_COULDNOTCREATECERTNAMECONSTRAINTSOBJECT); + + PKIX_CHECK(PKIX_PL_Malloc + (sizeof (CERTNameConstraint *), + (void *)&nssNameConstraintPtr, + plContext), + PKIX_MALLOCFAILED); + + nameConstraints->numNssNameConstraints = 1; + nameConstraints->nssNameConstraintsList = nssNameConstraintPtr; + *nssNameConstraintPtr = nssNameConstraints; + + nameConstraints->permittedList = NULL; + nameConstraints->excludedList = NULL; + nameConstraints->arena = NULL; + + *pNameConstraints = nameConstraints; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(nameConstraints); + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_Create + * + * DESCRIPTION: + * function that allocates and initialize the object CertNameConstraints. + * + * PARAMETERS + * "nssCert" + * Address of CERT that contains this object's data. + * Must be non-NULL. + * "pNameConstraints" + * Address where object pointer will be stored. Must be non-NULL. + * A NULL value will be returned if there is no Name Constraints extension. + * "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 NameConstraints 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_pl_CertNameConstraints_Create( + CERTCertificate *nssCert, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + CERTNameConstraints *nssNameConstraints = NULL; + PLArenaPool *arena = NULL; + SECStatus status; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Create"); + PKIX_NULLCHECK_THREE(nssCert, pNameConstraints, nssCert->arena); + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_FindNameConstraintsExten\n"); + status = CERT_FindNameConstraintsExten + (arena, nssCert, &nssNameConstraints); + + if (status != SECSuccess) { + PKIX_ERROR(PKIX_DECODINGCERTNAMECONSTRAINTSFAILED); + } + + if (nssNameConstraints == NULL) { + *pNameConstraints = NULL; + /* we free the arnea here because PKIX_ERROR_RECEIVED + * may not be set. Setting arena to NULL makes sure + * we don't try to free it again (and makes scanners + * happy). */ + if (arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + arena = NULL; + } + goto cleanup; + } + + PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper + (nssNameConstraints, &nameConstraints, plContext), + PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED); + + nameConstraints->arena = arena; + + *pNameConstraints = nameConstraints; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + if (arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_CreateByMerge + * + * DESCRIPTION: + * + * This function allocates and creates a PKIX_PL_NameConstraint object + * for merging. It also allocates CERTNameConstraints data space for the + * merged NSS NameConstraints data. + * + * PARAMETERS + * "pNameConstraints" + * Address where object pointer will be stored 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 NameConstraints 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_pl_CertNameConstraints_CreateByMerge( + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + CERTNameConstraints *nssNameConstraints = NULL; + PLArenaPool *arena = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_CreateByMerge"); + PKIX_NULLCHECK_ONE(pNameConstraints); + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n"); + nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints); + if (nssNameConstraints == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + nssNameConstraints->permited = NULL; + nssNameConstraints->excluded = NULL; + nssNameConstraints->DERPermited = NULL; + nssNameConstraints->DERExcluded = NULL; + + PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper + (nssNameConstraints, &nameConstraints, plContext), + PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED); + + nameConstraints->arena = arena; + + *pNameConstraints = nameConstraints; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + if (arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_CopyNssNameConstraints + * + * DESCRIPTION: + * + * This function allocates and copies data to a NSS CERTNameConstraints from + * the NameConstraints given by "srcNC" and stores the result at "pDestNC". It + * copies items on both the permitted and excluded lists, but not the + * DERPermited and DERExcluded. + * + * PARAMETERS + * "arena" + * Memory pool where object data is allocated from. Must be non-NULL. + * "srcNC" + * Address of the NameConstraints to copy from. Must be non-NULL. + * "pDestNC" + * Address where new copied object is stored 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 NameConstraints 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_pl_CertNameConstraints_CopyNssNameConstraints( + PLArenaPool *arena, + CERTNameConstraints *srcNC, + CERTNameConstraints **pDestNC, + void *plContext) +{ + CERTNameConstraints *nssNameConstraints = NULL; + CERTNameConstraint *nssNameConstraintHead = NULL; + CERTNameConstraint *nssCurrent = NULL; + CERTNameConstraint *nssCopyTo = NULL; + CERTNameConstraint *nssCopyFrom = NULL; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "pkix_pl_CertNameConstraints_CopyNssNameConstraints"); + PKIX_NULLCHECK_THREE(arena, srcNC, pDestNC); + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n"); + nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints); + if (nssNameConstraints == NULL) { + PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); + } + + if (srcNC->permited) { + + nssCopyFrom = srcNC->permited; + + do { + + nssCopyTo = NULL; + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_CopyNameConstraint).\n"); + nssCopyTo = CERT_CopyNameConstraint + (arena, nssCopyTo, nssCopyFrom); + if (nssCopyTo == NULL) { + PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED); + } + if (nssCurrent == NULL) { + nssCurrent = nssNameConstraintHead = nssCopyTo; + } else { + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_AddNameConstraint).\n"); + nssCurrent = CERT_AddNameConstraint + (nssCurrent, nssCopyTo); + } + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_GetNextNameConstrain).\n"); + nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom); + + } while (nssCopyFrom != srcNC->permited); + + nssNameConstraints->permited = nssNameConstraintHead; + } + + if (srcNC->excluded) { + + nssCurrent = NULL; + nssCopyFrom = srcNC->excluded; + + do { + + /* + * Cannot use CERT_DupGeneralNameList, which just increments + * refcount. We need our own copy since arena is for each + * PKIX_PL_NameConstraints. Perhaps contribute this code + * as CERT_CopyGeneralNameList (in the future). + */ + nssCopyTo = NULL; + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_CopyNameConstraint).\n"); + nssCopyTo = CERT_CopyNameConstraint + (arena, nssCopyTo, nssCopyFrom); + if (nssCopyTo == NULL) { + PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED); + } + if (nssCurrent == NULL) { + nssCurrent = nssNameConstraintHead = nssCopyTo; + } else { + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_AddNameConstraint).\n"); + nssCurrent = CERT_AddNameConstraint + (nssCurrent, nssCopyTo); + } + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_GetNextNameConstrain).\n"); + nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom); + + } while (nssCopyFrom != srcNC->excluded); + + nssNameConstraints->excluded = nssNameConstraintHead; + } + + *pDestNC = nssNameConstraints; + +cleanup: + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* + * FUNCTION: pkix_pl_CertNameConstraints_Merge + * + * DESCRIPTION: + * + * This function merges two NameConstraints pointed to by "firstNC" and + * "secondNC" and stores the result in "pMergedNC". + * + * PARAMETERS + * "firstNC" + * Address of the first NameConstraints to be merged. Must be non-NULL. + * "secondNC" + * Address of the second NameConstraints to be merged. Must be non-NULL. + * "pMergedNC" + * Address where the merge result is stored 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 NameConstraints 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_pl_CertNameConstraints_Merge( + PKIX_PL_CertNameConstraints *firstNC, + PKIX_PL_CertNameConstraints *secondNC, + PKIX_PL_CertNameConstraints **pMergedNC, + void *plContext) +{ + PKIX_PL_CertNameConstraints *nameConstraints = NULL; + CERTNameConstraints **nssNCto = NULL; + CERTNameConstraints **nssNCfrom = NULL; + CERTNameConstraints *nssNameConstraints = NULL; + PKIX_UInt32 numNssItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Merge"); + PKIX_NULLCHECK_THREE(firstNC, secondNC, pMergedNC); + + PKIX_CHECK(pkix_pl_CertNameConstraints_CreateByMerge + (&nameConstraints, plContext), + PKIX_CERTNAMECONSTRAINTSCREATEBYMERGEFAILED); + + /* Merge NSSCertConstraint lists */ + + numNssItems = firstNC->numNssNameConstraints + + secondNC->numNssNameConstraints; + + /* Free the default space (only one entry) allocated by create */ + PKIX_CHECK(PKIX_PL_Free + (nameConstraints->nssNameConstraintsList, plContext), + PKIX_FREEFAILED); + + /* Reallocate the size we need */ + PKIX_CHECK(PKIX_PL_Malloc + (numNssItems * sizeof (CERTNameConstraint *), + (void *)&nssNCto, + plContext), + PKIX_MALLOCFAILED); + + nameConstraints->nssNameConstraintsList = nssNCto; + + nssNCfrom = firstNC->nssNameConstraintsList; + + for (i = 0; i < firstNC->numNssNameConstraints; i++) { + + PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints + (nameConstraints->arena, + *nssNCfrom, + &nssNameConstraints, + plContext), + PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED); + + *nssNCto = nssNameConstraints; + + nssNCto++; + nssNCfrom++; + } + + nssNCfrom = secondNC->nssNameConstraintsList; + + for (i = 0; i < secondNC->numNssNameConstraints; i++) { + + PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints + (nameConstraints->arena, + *nssNCfrom, + &nssNameConstraints, + plContext), + PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED); + + *nssNCto = nssNameConstraints; + + nssNCto++; + nssNCfrom++; + } + + nameConstraints->numNssNameConstraints = numNssItems; + nameConstraints->permittedList = NULL; + nameConstraints->excludedList = NULL; + + *pMergedNC = nameConstraints; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(nameConstraints); + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} + +/* --Public-NameConstraints-Functions-------------------------------- */ + +/* + * FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace + * (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_CertNameConstraints_CheckNamesInNameSpace( + PKIX_List *nameList, /* List of PKIX_PL_GeneralName */ + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean *pCheckPass, + void *plContext) +{ + CERTNameConstraints **nssNameConstraintsList = NULL; + CERTNameConstraints *nssNameConstraints = NULL; + CERTGeneralName *nssMatchName = NULL; + PLArenaPool *arena = NULL; + PKIX_PL_GeneralName *name = NULL; + PKIX_UInt32 numNameItems = 0; + PKIX_UInt32 numNCItems = 0; + PKIX_UInt32 i, j; + SECStatus status = SECSuccess; + + PKIX_ENTER(CERTNAMECONSTRAINTS, + "PKIX_PL_CertNameConstraints_CheckNamesInNameSpace"); + PKIX_NULLCHECK_TWO(nameConstraints, pCheckPass); + + *pCheckPass = PKIX_TRUE; + + if (nameList != NULL) { + + PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n"); + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + nssNameConstraintsList = + nameConstraints->nssNameConstraintsList; + PKIX_NULLCHECK_ONE(nssNameConstraintsList); + numNCItems = nameConstraints->numNssNameConstraints; + + PKIX_CHECK(PKIX_List_GetLength + (nameList, &numNameItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numNameItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (nameList, + i, + (PKIX_PL_Object **) &name, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_pl_GeneralName_GetNssGeneralName + (name, &nssMatchName, plContext), + PKIX_GENERALNAMEGETNSSGENERALNAMEFAILED); + + PKIX_DECREF(name); + + for (j = 0; j < numNCItems; j++) { + + nssNameConstraints = *(nssNameConstraintsList + j); + PKIX_NULLCHECK_ONE(nssNameConstraints); + + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling CERT_CheckNameSpace\n"); + status = CERT_CheckNameSpace + (arena, nssNameConstraints, nssMatchName); + if (status != SECSuccess) { + break; + } + + } + + if (status != SECSuccess) { + break; + } + + } + } + + if (status == SECFailure) { + *pCheckPass = PKIX_FALSE; + } + +cleanup: + + if (arena){ + PKIX_CERTNAMECONSTRAINTS_DEBUG + ("\t\tCalling PORT_FreeArena).\n"); + PORT_FreeArena(arena, PR_FALSE); + } + + PKIX_RETURN(CERTNAMECONSTRAINTS); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h new file mode 100644 index 0000000000..2f305ac10a --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.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_pl_nameconstraints.h + * + * Name Constraints Object Definitions + * + */ + +#ifndef _PKIX_PL_NAMECONSTRAINTS_H +#define _PKIX_PL_NAMECONSTRAINTS_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_CertNameConstraintsStruct { + PLArenaPool *arena; + CERTNameConstraints **nssNameConstraintsList; + PKIX_UInt32 numNssNameConstraints; + PKIX_List *permittedList; /* list of PKIX_PL_GeneralName */ + PKIX_List *excludedList; /* list of PKIX_PL_GeneralName */ +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_CertNameConstraints_RegisterSelf(void *plContext); + +PKIX_Error *pkix_pl_CertNameConstraints_Create( + CERTCertificate *nssCert, + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext); + +PKIX_Error * +pkix_pl_CertNameConstraints_CreateWithNames( + PKIX_List *names, /* List of PKIX_PL_GeneralName */ + PKIX_PL_CertNameConstraints **pNameConstraints, + void *plContext); + +PKIX_Error * +pkix_pl_CertNameConstraints_CheckNameSpaceNssNames( + CERTGeneralName *nssSubjectNames, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean *pCheckPass, + void *plContext); + +PKIX_Error * +pkix_pl_CertNameConstraints_CheckNameSpacePkixNames( + PKIX_List *nameList, + PKIX_PL_CertNameConstraints *nameConstraints, + PKIX_Boolean *pCheckPass, + void *plContext); + + +PKIX_Error *pkix_pl_CertNameConstraints_Merge( + PKIX_PL_CertNameConstraints *firstNC, + PKIX_PL_CertNameConstraints *secondNC, + PKIX_PL_CertNameConstraints **pMergedNC, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_NAMECONSTRAINTS_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c new file mode 100644 index 0000000000..679811dec1 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c @@ -0,0 +1,251 @@ +/* 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_pl_ocspcertid.c + * + * Certificate ID Object for OCSP + * + */ + +#include "pkix_pl_ocspcertid.h" + +/* --Private-Cert-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_OcspCertID_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspCertID_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_OcspCertID *certID = NULL; + + PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPCERTID_TYPE, plContext), + PKIX_OBJECTNOTOCSPCERTID); + + certID = (PKIX_PL_OcspCertID *)object; + + if (certID->certID) { + CERT_DestroyOCSPCertID(certID->certID); + } + +cleanup: + + PKIX_RETURN(OCSPCERTID); +} + +/* + * FUNCTION: pkix_pl_OcspCertID_RegisterSelf + * DESCRIPTION: + * Registers PKIX_PUBLICKEY_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_pl_OcspCertID_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_RegisterSelf"); + + entry.description = "OcspCertID"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_OcspCertID); + entry.destructor = pkix_pl_OcspCertID_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + systemClasses[PKIX_OCSPCERTID_TYPE] = entry; + + PKIX_RETURN(OCSPCERTID); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_OcspCertID_Create + * DESCRIPTION: + * + * This function creates an OcspCertID for a given certificate, + * to be used with OCSP transactions. + * + * If a Date is provided in "validity" it may be used in the search for the + * issuer of "cert" but has no effect on the request itself. + * + * PARAMETERS: + * "cert" + * Address of the Cert for which an OcspCertID is to be created. Must be + * non-NULL. + * "validity" + * Address of the Date for which the Cert's validity is to be determined. + * May be NULL. + * "object" + * 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 an OcspCertID 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_PL_OcspCertID_Create( + PKIX_PL_Cert *cert, + PKIX_PL_Date *validity, + PKIX_PL_OcspCertID **object, + void *plContext) +{ + PKIX_PL_OcspCertID *cid = NULL; + PRTime time = 0; + + PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_Create"); + PKIX_NULLCHECK_TWO(cert, object); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_OCSPCERTID_TYPE, + sizeof (PKIX_PL_OcspCertID), + (PKIX_PL_Object **)&cid, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + if (validity != NULL) { + PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), + PKIX_DATEGETPRTIMEFAILED); + } else { + time = PR_Now(); + } + + cid->certID = CERT_CreateOCSPCertID(cert->nssCert, time); + if (!cid->certID) { + PKIX_ERROR(PKIX_COULDNOTCREATEOBJECT); + } + + *object = cid; + cid = NULL; +cleanup: + PKIX_DECREF(cid); + PKIX_RETURN(OCSPCERTID); +} + +/* + * FUNCTION: PKIX_PL_OcspCertID_GetFreshCacheStatus + * DESCRIPTION: + * + * This function may return cached OCSP results for the provided + * certificate, but only if stored information is still considered to be + * fresh. + * + * PARAMETERS + * "cid" + * A certificate ID as used by OCSP + * "validity" + * Optional date parameter to request validity for a specifc time. + * "hasFreshStatus" + * Output parameter, if the function successed to find fresh cached + * information, this will be set to true. Must be non-NULL. + * "statusIsGood" + * The good/bad result stored in the cache. Must be non-NULL. + * "missingResponseError" + * If OCSP status is "bad", this variable may indicate the exact + * reason why the previous OCSP request had failed. + * "plContext" + * Platform-specific context pointer. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an OcspCertID 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_PL_OcspCertID_GetFreshCacheStatus( + PKIX_PL_OcspCertID *cid, + PKIX_PL_Date *validity, + PKIX_Boolean *hasFreshStatus, + PKIX_Boolean *statusIsGood, + SECErrorCodes *missingResponseError, + void *plContext) +{ + PRTime time = 0; + SECStatus rv; + SECStatus rvOcsp; + OCSPFreshness freshness; + + PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_GetFreshCacheStatus"); + PKIX_NULLCHECK_THREE(cid, hasFreshStatus, statusIsGood); + + if (validity != NULL) { + PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), + PKIX_DATEGETPRTIMEFAILED); + } else { + time = PR_Now(); + } + + rv = ocsp_GetCachedOCSPResponseStatus( + cid->certID, time, PR_TRUE, /*ignoreGlobalOcspFailureSetting*/ + &rvOcsp, missingResponseError, &freshness); + + *hasFreshStatus = (rv == SECSuccess && freshness == ocspFresh); + if (*hasFreshStatus) { + *statusIsGood = (rvOcsp == SECSuccess); + } +cleanup: + PKIX_RETURN(OCSPCERTID); +} + +/* + * FUNCTION: PKIX_PL_OcspCertID_RememberOCSPProcessingFailure + * DESCRIPTION: + * + * Information about the current failure associated to the given certID + * will be remembered in the cache, potentially allowing future calls + * to prevent repetitive OCSP requests. + * After this function got called, it may no longer be safe to + * use the provided cid parameter, because ownership might have been + * transfered to the cache. This status will be recorded inside the + * cid object. + * + * PARAMETERS + * "cid" + * The certificate ID associated to a failed OCSP processing. + * "plContext" + * Platform-specific context pointer. + * RETURNS: + * Returns NULL if the function succeeds. + * Returns an OcspCertID 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_PL_OcspCertID_RememberOCSPProcessingFailure( + PKIX_PL_OcspCertID *cid, + void *plContext) +{ + PRBool certIDWasConsumed = PR_FALSE; + + PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_RememberOCSPProcessingFailure"); + PKIX_NULLCHECK_TWO(cid, cid->certID); + + cert_RememberOCSPProcessingFailure(cid->certID, &certIDWasConsumed); + + if (certIDWasConsumed) { + cid->certID = NULL; + } + + PKIX_RETURN(OCSPCERTID); +} + diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h new file mode 100644 index 0000000000..772a12b25f --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h @@ -0,0 +1,53 @@ +/* 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_pl_ocspcertid.h + * + * Public Key Object Definitions + * + */ + +#ifndef _PKIX_PL_OCSPCERTID_H +#define _PKIX_PL_OCSPCERTID_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_OcspCertIDStruct { + CERTOCSPCertID *certID; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_OcspCertID_RegisterSelf(void *plContext); + +PKIX_Error * +PKIX_PL_OcspCertID_Create( + PKIX_PL_Cert *cert, + PKIX_PL_Date *validity, + PKIX_PL_OcspCertID **object, + void *plContext); + +PKIX_Error * +PKIX_PL_OcspCertID_GetFreshCacheStatus( + PKIX_PL_OcspCertID *cid, + PKIX_PL_Date *validity, + PKIX_Boolean *hasFreshStatus, + PKIX_Boolean *statusIsGood, + SECErrorCodes *missingResponseError, + void *plContext); + +PKIX_Error * +PKIX_PL_OcspCertID_RememberOCSPProcessingFailure( + PKIX_PL_OcspCertID *cid, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_OCSPCERTID_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c new file mode 100644 index 0000000000..28b6953a76 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c @@ -0,0 +1,441 @@ +/* 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_pl_ocsprequest.c + * + */ + +#include "pkix_pl_ocsprequest.h" + +/* --Private-OcspRequest-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_OcspRequest_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspRequest_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_OcspRequest *ocspReq = NULL; + + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext), + PKIX_OBJECTNOTOCSPREQUEST); + + ocspReq = (PKIX_PL_OcspRequest *)object; + + if (ocspReq->decoded != NULL) { + CERT_DestroyOCSPRequest(ocspReq->decoded); + } + + if (ocspReq->encoded != NULL) { + SECITEM_FreeItem(ocspReq->encoded, PR_TRUE); + } + + if (ocspReq->location != NULL) { + PORT_Free(ocspReq->location); + } + + PKIX_DECREF(ocspReq->cert); + PKIX_DECREF(ocspReq->validity); + PKIX_DECREF(ocspReq->signerCert); + +cleanup: + + PKIX_RETURN(OCSPREQUEST); +} + +/* + * FUNCTION: pkix_pl_OcspRequest_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspRequest_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_UInt32 certHash = 0; + PKIX_UInt32 dateHash = 0; + PKIX_UInt32 extensionHash = 0; + PKIX_UInt32 signerHash = 0; + PKIX_PL_OcspRequest *ocspRq = NULL; + + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext), + PKIX_OBJECTNOTOCSPREQUEST); + + ocspRq = (PKIX_PL_OcspRequest *)object; + + *pHashcode = 0; + + PKIX_HASHCODE(ocspRq->cert, &certHash, plContext, + PKIX_CERTHASHCODEFAILED); + + PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext, + PKIX_DATEHASHCODEFAILED); + + if (ocspRq->addServiceLocator == PKIX_TRUE) { + extensionHash = 0xff; + } + + PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext, + PKIX_CERTHASHCODEFAILED); + + *pHashcode = (((((extensionHash << 8) | certHash) << 8) | + dateHash) << 8) | signerHash; + +cleanup: + + PKIX_RETURN(OCSPREQUEST); + +} + +/* + * FUNCTION: pkix_pl_OcspRequest_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspRequest_Equals( + PKIX_PL_Object *firstObj, + PKIX_PL_Object *secondObj, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Boolean match = PKIX_FALSE; + PKIX_UInt32 secondType = 0; + PKIX_PL_OcspRequest *firstReq = NULL; + PKIX_PL_OcspRequest *secondReq = NULL; + + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals"); + PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); + + /* test that firstObj is a OcspRequest */ + PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext), + PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST); + + /* + * Since we know firstObj is a OcspRequest, if both references are + * identical, they must be equal + */ + if (firstObj == secondObj){ + match = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObj isn't a OcspRequest, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObj, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_OCSPREQUEST_TYPE) { + goto cleanup; + } + + firstReq = (PKIX_PL_OcspRequest *)firstObj; + secondReq = (PKIX_PL_OcspRequest *)secondObj; + + if (firstReq->addServiceLocator != secondReq->addServiceLocator) { + goto cleanup; + } + + PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext, + PKIX_CERTEQUALSFAILED); + + if (match == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext, + PKIX_DATEEQUALSFAILED); + + if (match == PKIX_FALSE) { + goto cleanup; + } + + PKIX_EQUALS + (firstReq->signerCert, secondReq->signerCert, &match, plContext, + PKIX_CERTEQUALSFAILED); + +cleanup: + + *pResult = match; + + PKIX_RETURN(OCSPREQUEST); +} + +/* + * FUNCTION: pkix_pl_OcspRequest_RegisterSelf + * DESCRIPTION: + * Registers PKIX_OCSPREQUEST_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_pl_OcspRequest_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf"); + + entry.description = "OcspRequest"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest); + entry.destructor = pkix_pl_OcspRequest_Destroy; + entry.equalsFunction = pkix_pl_OcspRequest_Equals; + entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_OCSPREQUEST_TYPE] = entry; + + PKIX_RETURN(OCSPREQUEST); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_OcspRequest_Create + * DESCRIPTION: + * + * This function creates an OcspRequest to be used in validating the Cert + * pointed to by "cert" and storing the result at "pRequest". If a URI + * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no + * URI is found, PKIX_FALSE is stored. + * + * If a Date is provided in "validity" it may be used in the search for the + * issuer of "cert" but has no effect on the request itself. If + * "addServiceLocator" is TRUE, the AddServiceLocator extension will be + * included in the Request. If "signerCert" is provided it will be used to sign + * the Request. (Note: this signed request feature is not currently supported.) + * + * PARAMETERS: + * "cert" + * Address of the Cert for which an OcspRequest is to be created. Must be + * non-NULL. + * "validity" + * Address of the Date for which the Cert's validity is to be determined. + * May be NULL. + * "signerCert" + * Address of the Cert to be used, if present, in signing the request. + * May be NULL. + * "pRequest" + * 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 an OcspRequest 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_pl_OcspRequest_Create( + PKIX_PL_Cert *cert, + PKIX_PL_OcspCertID *cid, + PKIX_PL_Date *validity, + PKIX_PL_Cert *signerCert, + PKIX_UInt32 methodFlags, + PKIX_Boolean *pURIFound, + PKIX_PL_OcspRequest **pRequest, + void *plContext) +{ + PKIX_PL_OcspRequest *ocspRequest = NULL; + + CERTCertDBHandle *handle = NULL; + SECStatus rv = SECFailure; + SECItem *encoding = NULL; + CERTOCSPRequest *certRequest = NULL; + PRTime time = 0; + PRBool addServiceLocatorExtension = PR_FALSE; + CERTCertificate *nssCert = NULL; + CERTCertificate *nssSignerCert = NULL; + char *location = NULL; + PRErrorCode locError = 0; + PKIX_Boolean canUseDefaultSource = PKIX_FALSE; + + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create"); + PKIX_NULLCHECK_TWO(cert, pRequest); + + /* create a PKIX_PL_OcspRequest object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_OCSPREQUEST_TYPE, + sizeof (PKIX_PL_OcspRequest), + (PKIX_PL_Object **)&ocspRequest, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + PKIX_INCREF(cert); + ocspRequest->cert = cert; + + PKIX_INCREF(validity); + ocspRequest->validity = validity; + + PKIX_INCREF(signerCert); + ocspRequest->signerCert = signerCert; + + ocspRequest->decoded = NULL; + ocspRequest->encoded = NULL; + + ocspRequest->location = NULL; + + nssCert = cert->nssCert; + + /* + * Does this Cert have an Authority Information Access extension with + * the URI of an OCSP responder? + */ + handle = CERT_GetDefaultCertDB(); + + if (!(methodFlags & PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE)) { + canUseDefaultSource = PKIX_TRUE; + } + location = ocsp_GetResponderLocation(handle, nssCert, + canUseDefaultSource, + &addServiceLocatorExtension); + if (location == NULL) { + locError = PORT_GetError(); + if (locError == SEC_ERROR_EXTENSION_NOT_FOUND || + locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) { + PORT_SetError(0); + *pURIFound = PKIX_FALSE; + goto cleanup; + } + PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI); + } + + ocspRequest->location = location; + *pURIFound = PKIX_TRUE; + + if (signerCert != NULL) { + nssSignerCert = signerCert->nssCert; + } + + if (validity != NULL) { + PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), + PKIX_DATEGETPRTIMEFAILED); + } else { + time = PR_Now(); + } + + certRequest = cert_CreateSingleCertOCSPRequest( + cid->certID, cert->nssCert, time, + addServiceLocatorExtension, nssSignerCert); + + ocspRequest->decoded = certRequest; + + if (certRequest == NULL) { + PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST); + } + + rv = CERT_AddOCSPAcceptableResponses( + certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE); + + if (rv == SECFailure) { + PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST); + } + + encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL); + + ocspRequest->encoded = encoding; + + *pRequest = ocspRequest; + ocspRequest = NULL; + +cleanup: + PKIX_DECREF(ocspRequest); + + PKIX_RETURN(OCSPREQUEST); +} + +/* + * FUNCTION: pkix_pl_OcspRequest_GetEncoded + * DESCRIPTION: + * + * This function obtains the encoded message from the OcspRequest pointed to + * by "request", storing the result at "pRequest". + * + * PARAMETERS + * "request" + * The address of the OcspRequest whose encoded message is to be + * retrieved. Must be non-NULL. + * "pRequest" + * The address at which is stored the address of the encoded message. 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_pl_OcspRequest_GetEncoded( + PKIX_PL_OcspRequest *request, + SECItem **pRequest, + void *plContext) +{ + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded"); + PKIX_NULLCHECK_TWO(request, pRequest); + + *pRequest = request->encoded; + + PKIX_RETURN(OCSPREQUEST); +} + +/* + * FUNCTION: pkix_pl_OcspRequest_GetLocation + * DESCRIPTION: + * + * This function obtains the location from the OcspRequest pointed to + * by "request", storing the result at "pLocation". + * + * PARAMETERS + * "request" + * The address of the OcspRequest whose encoded message is to be + * retrieved. Must be non-NULL. + * "pLocation" + * The address at which is stored the address of the location. 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_pl_OcspRequest_GetLocation( + PKIX_PL_OcspRequest *request, + char **pLocation, + void *plContext) +{ + PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation"); + PKIX_NULLCHECK_TWO(request, pLocation); + + *pLocation = request->location; + + PKIX_RETURN(OCSPREQUEST); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h new file mode 100644 index 0000000000..fa79266eec --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h @@ -0,0 +1,61 @@ +/* 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_pl_ocsprequest.h + * + * OcspRequest Object Definitions + * + */ + +#ifndef _PKIX_PL_OCSPREQUEST_H +#define _PKIX_PL_OCSPREQUEST_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_OcspRequestStruct{ + PKIX_PL_Cert *cert; + PKIX_PL_Date *validity; + PKIX_Boolean addServiceLocator; + PKIX_PL_Cert *signerCert; + CERTOCSPRequest *decoded; + SECItem *encoded; + char *location; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_OcspRequest_Create( + PKIX_PL_Cert *cert, + PKIX_PL_OcspCertID *cid, + PKIX_PL_Date *validity, + PKIX_PL_Cert *signerCert, + PKIX_UInt32 methodFlags, + PKIX_Boolean *pURIFound, + PKIX_PL_OcspRequest **pRequest, + void *plContext); + +PKIX_Error * +pkix_pl_OcspRequest_GetEncoded( + PKIX_PL_OcspRequest *request, + SECItem **pRequest, + void *plContext); + +PKIX_Error * +pkix_pl_OcspRequest_GetLocation( + PKIX_PL_OcspRequest *request, + char **pLocation, + void *plContext); + +PKIX_Error *pkix_pl_OcspRequest_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_OCSPREQUEST_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c new file mode 100644 index 0000000000..fa41f8102e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c @@ -0,0 +1,1069 @@ +/* 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_pl_ocspresponse.c + * + */ + +#include "pkix_pl_ocspresponse.h" + +/* ----Public functions------------------------------------- */ +/* + * This is the libpkix replacement for CERT_VerifyOCSPResponseSignature. + * It is used if it has been set as the verifyFcn member of ocspChecker. + */ +PKIX_Error * +PKIX_PL_OcspResponse_UseBuildChain( + PKIX_PL_Cert *signerCert, + PKIX_PL_Date *producedAt, + PKIX_ProcessingParams *procParams, + void **pNBIOContext, + void **pState, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext) +{ + PKIX_ProcessingParams *caProcParams = NULL; + PKIX_PL_Date *date = NULL; + PKIX_ComCertSelParams *certSelParams = NULL; + PKIX_CertSelector *certSelector = NULL; + void *nbioContext = NULL; + PKIX_Error *buildError = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_OcspResponse_UseBuildChain"); + PKIX_NULLCHECK_THREE(signerCert, producedAt, procParams); + PKIX_NULLCHECK_THREE(pNBIOContext, pState, pBuildResult); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + /* Are we resuming after a WOULDBLOCK return, or starting anew ? */ + if (nbioContext == NULL) { + /* Starting anew */ + PKIX_CHECK(PKIX_PL_Object_Duplicate + ((PKIX_PL_Object *)procParams, + (PKIX_PL_Object **)&caProcParams, + plContext), + PKIX_OBJECTDUPLICATEFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_SetDate(procParams, date, plContext), + PKIX_PROCESSINGPARAMSSETDATEFAILED); + + /* create CertSelector with target certificate in params */ + + PKIX_CHECK(PKIX_CertSelector_Create + (NULL, NULL, &certSelector, plContext), + PKIX_CERTSELECTORCREATEFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_Create + (&certSelParams, plContext), + PKIX_COMCERTSELPARAMSCREATEFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_SetCertificate + (certSelParams, signerCert, plContext), + PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED); + + PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams + (certSelector, certSelParams, plContext), + PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); + + PKIX_CHECK(PKIX_ProcessingParams_SetTargetCertConstraints + (caProcParams, certSelector, plContext), + PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED); + } + + buildError = PKIX_BuildChain + (caProcParams, + &nbioContext, + pState, + pBuildResult, + pVerifyTree, + plContext); + + /* non-null nbioContext means the build would block */ + if (nbioContext != NULL) { + + *pNBIOContext = nbioContext; + + /* no buildResult means the build has failed */ + } else if (buildError) { + pkixErrorResult = buildError; + buildError = NULL; + } else { + PKIX_DECREF(*pState); + } + +cleanup: + + PKIX_DECREF(caProcParams); + PKIX_DECREF(date); + PKIX_DECREF(certSelParams); + PKIX_DECREF(certSelector); + + PKIX_RETURN(OCSPRESPONSE); +} + +/* --Private-OcspResponse-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_OcspResponse_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspResponse_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_OcspResponse *ocspRsp = NULL; + const SEC_HttpClientFcn *httpClient = NULL; + const SEC_HttpClientFcnV1 *hcv1 = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext), + PKIX_OBJECTNOTANOCSPRESPONSE); + + ocspRsp = (PKIX_PL_OcspResponse *)object; + + if (ocspRsp->nssOCSPResponse != NULL) { + CERT_DestroyOCSPResponse(ocspRsp->nssOCSPResponse); + ocspRsp->nssOCSPResponse = NULL; + } + + if (ocspRsp->signerCert != NULL) { + CERT_DestroyCertificate(ocspRsp->signerCert); + ocspRsp->signerCert = NULL; + } + + httpClient = (const SEC_HttpClientFcn *)(ocspRsp->httpClient); + + if (httpClient && (httpClient->version == 1)) { + + hcv1 = &(httpClient->fcnTable.ftable1); + + if (ocspRsp->sessionRequest != NULL) { + (*hcv1->freeFcn)(ocspRsp->sessionRequest); + ocspRsp->sessionRequest = NULL; + } + + if (ocspRsp->serverSession != NULL) { + (*hcv1->freeSessionFcn)(ocspRsp->serverSession); + ocspRsp->serverSession = NULL; + } + } + + if (ocspRsp->arena != NULL) { + PORT_FreeArena(ocspRsp->arena, PR_FALSE); + ocspRsp->arena = NULL; + } + + PKIX_DECREF(ocspRsp->producedAtDate); + PKIX_DECREF(ocspRsp->pkixSignerCert); + PKIX_DECREF(ocspRsp->request); + +cleanup: + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspResponse_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_OcspResponse *ocspRsp = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext), + PKIX_OBJECTNOTANOCSPRESPONSE); + + ocspRsp = (PKIX_PL_OcspResponse *)object; + + if (ocspRsp->encodedResponse->data == NULL) { + *pHashcode = 0; + } else { + PKIX_CHECK(pkix_hash + (ocspRsp->encodedResponse->data, + ocspRsp->encodedResponse->len, + pHashcode, + plContext), + PKIX_HASHFAILED); + } + +cleanup: + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OcspResponse_Equals( + PKIX_PL_Object *firstObj, + PKIX_PL_Object *secondObj, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType = 0; + PKIX_UInt32 firstLen = 0; + PKIX_UInt32 i = 0; + PKIX_PL_OcspResponse *rsp1 = NULL; + PKIX_PL_OcspResponse *rsp2 = NULL; + const unsigned char *firstData = NULL; + const unsigned char *secondData = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Equals"); + PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); + + /* test that firstObj is a OcspResponse */ + PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPRESPONSE_TYPE, plContext), + PKIX_FIRSTOBJARGUMENTNOTANOCSPRESPONSE); + + /* + * Since we know firstObj is a OcspResponse, if both references are + * identical, they must be equal + */ + if (firstObj == secondObj){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObj isn't a OcspResponse, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_OCSPRESPONSE_TYPE) { + goto cleanup; + } + + rsp1 = (PKIX_PL_OcspResponse *)firstObj; + rsp2 = (PKIX_PL_OcspResponse *)secondObj; + + /* If either lacks an encoded string, they cannot be compared */ + firstData = (const unsigned char *)rsp1->encodedResponse->data; + secondData = (const unsigned char *)rsp2->encodedResponse->data; + if ((firstData == NULL) || (secondData == NULL)) { + goto cleanup; + } + + firstLen = rsp1->encodedResponse->len; + + if (firstLen != rsp2->encodedResponse->len) { + goto cleanup; + } + + for (i = 0; i < firstLen; i++) { + if (*firstData++ != *secondData++) { + goto cleanup; + } + } + + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_RegisterSelf + * DESCRIPTION: + * Registers PKIX_OCSPRESPONSE_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_pl_OcspResponse_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OCSPRESPONSE_TYPE]; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_RegisterSelf"); + + entry->description = "OcspResponse"; + entry->typeObjectSize = sizeof(PKIX_PL_OcspResponse); + entry->destructor = pkix_pl_OcspResponse_Destroy; + entry->equalsFunction = pkix_pl_OcspResponse_Equals; + entry->hashcodeFunction = pkix_pl_OcspResponse_Hashcode; + entry->duplicateFunction = pkix_duplicateImmutable; + + PKIX_RETURN(OCSPRESPONSE); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_OcspResponse_Create + * DESCRIPTION: + * + * This function transmits the OcspRequest pointed to by "request" and obtains + * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient + * supports non-blocking I/O this function may store a non-NULL value at + * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should + * make a subsequent call with the same value in "pNBIOContext" and + * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may + * occur; the caller should persist until a return occurs with NULL stored at + * "pNBIOContext". + * + * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client + * to which the OCSP query is sent. If none is supplied, the default responder + * is used. + * + * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to + * verify the Cert received from the responder as the signer. If none is + * supplied, the default verification function is used. + * + * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK + * return, and the caller is permitted to supply NULL. + * + * PARAMETERS + * "request" + * Address of the OcspRequest for which a response is desired. + * "httpMethod" + * GET or POST + * "responder" + * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP + * query. + * "verifyFcn" + * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be + * used to verify the Cert of the OCSP responder. + * "pNBIOContext" + * Address at which platform-dependent information is stored for handling + * of non-blocking I/O. Must be non-NULL. + * "pOcspResponse" + * The address where the created OcspResponse 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 an OcspResponse 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_pl_OcspResponse_Create( + PKIX_PL_OcspRequest *request, + const char *httpMethod, + void *responder, + PKIX_PL_VerifyCallback verifyFcn, + void **pNBIOContext, + PKIX_PL_OcspResponse **pResponse, + void *plContext) +{ + void *nbioContext = NULL; + PKIX_PL_OcspResponse *ocspResponse = NULL; + const SEC_HttpClientFcn *httpClient = NULL; + const SEC_HttpClientFcnV1 *hcv1 = NULL; + SECStatus rv = SECFailure; + char *location = NULL; + char *hostname = NULL; + char *path = NULL; + char *responseContentType = NULL; + PRUint16 port = 0; + SEC_HTTP_SERVER_SESSION serverSession = NULL; + SEC_HTTP_REQUEST_SESSION sessionRequest = NULL; + SECItem *encodedRequest = NULL; + PRUint16 responseCode = 0; + char *responseData = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create"); + PKIX_NULLCHECK_TWO(pNBIOContext, pResponse); + + if (!strcmp(httpMethod, "GET") && !strcmp(httpMethod, "POST")) { + PKIX_ERROR(PKIX_INVALIDOCSPHTTPMETHOD); + } + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; + + if (nbioContext != NULL) { + + ocspResponse = *pResponse; + PKIX_NULLCHECK_ONE(ocspResponse); + + httpClient = ocspResponse->httpClient; + serverSession = ocspResponse->serverSession; + sessionRequest = ocspResponse->sessionRequest; + PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest); + + } else { + PKIX_UInt32 timeout = + ((PKIX_PL_NssContext*)plContext)->timeoutSeconds; + + PKIX_NULLCHECK_ONE(request); + + PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded + (request, &encodedRequest, plContext), + PKIX_OCSPREQUESTGETENCODEDFAILED); + + /* prepare initial message to HTTPClient */ + + /* Is there a default responder and is it enabled? */ + if (responder) { + httpClient = (const SEC_HttpClientFcn *)responder; + } else { + httpClient = SEC_GetRegisteredHttpClient(); + } + + if (httpClient && (httpClient->version == 1)) { + char *fullGetPath = NULL; + const char *sessionPath = NULL; + PRBool usePOST = !strcmp(httpMethod, "POST"); + + hcv1 = &(httpClient->fcnTable.ftable1); + + PKIX_CHECK(pkix_pl_OcspRequest_GetLocation + (request, &location, plContext), + PKIX_OCSPREQUESTGETLOCATIONFAILED); + + /* parse location -> hostname, port, path */ + rv = CERT_ParseURL(location, &hostname, &port, &path); + if (rv == SECFailure || hostname == NULL || path == NULL) { + PKIX_ERROR(PKIX_URLPARSINGFAILED); + } + + rv = (*hcv1->createSessionFcn)(hostname, port, + &serverSession); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OCSPSERVERERROR); + } + + if (usePOST) { + sessionPath = path; + } else { + /* calculate, are we allowed to use GET? */ + enum { max_get_request_size = 255 }; /* defined by RFC2560 */ + char b64ReqBuf[max_get_request_size+1]; + size_t base64size; + size_t slashLengthIfNeeded = 0; + size_t pathLength; + PRInt32 urlEncodedBufLength; + size_t getURLLength; + char *walkOutput = NULL; + + pathLength = strlen(path); + if (path[pathLength-1] != '/') { + slashLengthIfNeeded = 1; + } + base64size = (((encodedRequest->len +2)/3) * 4); + if (base64size > max_get_request_size) { + PKIX_ERROR(PKIX_OCSPGETREQUESTTOOBIG); + } + memset(b64ReqBuf, 0, sizeof(b64ReqBuf)); + PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, b64ReqBuf); + urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL); + getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded; + fullGetPath = (char*)PORT_Alloc(getURLLength); + if (!fullGetPath) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + strcpy(fullGetPath, path); + walkOutput = fullGetPath + pathLength; + if (walkOutput > fullGetPath && slashLengthIfNeeded) { + strcpy(walkOutput, "/"); + ++walkOutput; + } + ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput); + sessionPath = fullGetPath; + } + + rv = (*hcv1->createFcn)(serverSession, "http", + sessionPath, httpMethod, + PR_SecondsToInterval(timeout), + &sessionRequest); + sessionPath = NULL; + if (fullGetPath) { + PORT_Free(fullGetPath); + fullGetPath = NULL; + } + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OCSPSERVERERROR); + } + + if (usePOST) { + rv = (*hcv1->setPostDataFcn)(sessionRequest, + (char *)encodedRequest->data, + encodedRequest->len, + "application/ocsp-request"); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OCSPSERVERERROR); + } + } + + /* create a PKIX_PL_OcspResponse object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_OCSPRESPONSE_TYPE, + sizeof (PKIX_PL_OcspResponse), + (PKIX_PL_Object **)&ocspResponse, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + PKIX_INCREF(request); + ocspResponse->request = request; + ocspResponse->httpClient = httpClient; + ocspResponse->serverSession = serverSession; + serverSession = NULL; + ocspResponse->sessionRequest = sessionRequest; + sessionRequest = NULL; + ocspResponse->verifyFcn = verifyFcn; + ocspResponse->handle = CERT_GetDefaultCertDB(); + ocspResponse->encodedResponse = NULL; + ocspResponse->arena = NULL; + ocspResponse->producedAt = 0; + ocspResponse->producedAtDate = NULL; + ocspResponse->pkixSignerCert = NULL; + ocspResponse->nssOCSPResponse = NULL; + ocspResponse->signerCert = NULL; + } + } + + /* begin or resume IO to HTTPClient */ + if (httpClient && (httpClient->version == 1)) { + PRUint32 responseDataLen = + ((PKIX_PL_NssContext*)plContext)->maxResponseLength; + + hcv1 = &(httpClient->fcnTable.ftable1); + + rv = (*hcv1->trySendAndReceiveFcn)(ocspResponse->sessionRequest, + (PRPollDesc **)&nbioContext, + &responseCode, + (const char **)&responseContentType, + NULL, /* responseHeaders */ + (const char **)&responseData, + &responseDataLen); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OCSPSERVERERROR); + } + /* responseContentType is a pointer to the null-terminated + * string returned by httpclient. Memory allocated for context + * type will be freed with freeing of the HttpClient struct. */ + if (PORT_Strcasecmp(responseContentType, + "application/ocsp-response")) { + PKIX_ERROR(PKIX_OCSPSERVERERROR); + } + if (nbioContext != NULL) { + *pNBIOContext = nbioContext; + goto cleanup; + } + if (responseCode != 200) { + PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE); + } + ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (ocspResponse->arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + ocspResponse->encodedResponse = SECITEM_AllocItem + (ocspResponse->arena, NULL, responseDataLen); + if (ocspResponse->encodedResponse == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + PORT_Memcpy(ocspResponse->encodedResponse->data, + responseData, responseDataLen); + } + *pResponse = ocspResponse; + ocspResponse = NULL; + +cleanup: + + if (path != NULL) { + PORT_Free(path); + } + if (hostname != NULL) { + PORT_Free(hostname); + } + if (ocspResponse) { + PKIX_DECREF(ocspResponse); + } + if (serverSession) { + hcv1->freeSessionFcn(serverSession); + } + if (sessionRequest) { + hcv1->freeFcn(sessionRequest); + } + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_Decode + * DESCRIPTION: + * + * This function decodes the DER data contained in the OcspResponse pointed to + * by "response", storing PKIX_TRUE at "pPassed" if the decoding was + * successful, and PKIX_FALSE otherwise. + * + * PARAMETERS + * "response" + * The address of the OcspResponse whose DER data is to be decoded. Must + * be non-NULL. + * "pPassed" + * Address at which the Boolean result is stored. Must be non-NULL. + * "pReturnCode" + * Address at which the SECErrorCodes 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 an OcspResponse 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_pl_OcspResponse_Decode( + PKIX_PL_OcspResponse *response, + PKIX_Boolean *pPassed, + SECErrorCodes *pReturnCode, + void *plContext) +{ + + PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_Decode"); + PKIX_NULLCHECK_TWO(response, response->encodedResponse); + + response->nssOCSPResponse = + CERT_DecodeOCSPResponse(response->encodedResponse); + + if (response->nssOCSPResponse != NULL) { + *pPassed = PKIX_TRUE; + *pReturnCode = 0; + } else { + *pPassed = PKIX_FALSE; + *pReturnCode = PORT_GetError(); + } + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_GetStatus + * DESCRIPTION: + * + * This function checks the response status of the OcspResponse pointed to + * by "response", storing PKIX_TRUE at "pPassed" if the responder understood + * the request and considered it valid, and PKIX_FALSE otherwise. + * + * PARAMETERS + * "response" + * The address of the OcspResponse whose status is to be retrieved. Must + * be non-NULL. + * "pPassed" + * Address at which the Boolean 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 an OcspResponse 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_pl_OcspResponse_GetStatus( + PKIX_PL_OcspResponse *response, + PKIX_Boolean *pPassed, + SECErrorCodes *pReturnCode, + void *plContext) +{ + SECStatus rv = SECFailure; + + PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_GetStatus"); + PKIX_NULLCHECK_FOUR(response, response->nssOCSPResponse, pPassed, pReturnCode); + + rv = CERT_GetOCSPResponseStatus(response->nssOCSPResponse); + + if (rv == SECSuccess) { + *pPassed = PKIX_TRUE; + *pReturnCode = 0; + } else { + *pPassed = PKIX_FALSE; + *pReturnCode = PORT_GetError(); + } + + PKIX_RETURN(OCSPRESPONSE); +} + + +static PKIX_Error* +pkix_pl_OcspResponse_VerifyResponse( + PKIX_PL_OcspResponse *response, + PKIX_ProcessingParams *procParams, + SECCertUsage certUsage, + void **state, + PKIX_BuildResult **buildResult, + void **pNBIOContext, + void *plContext) +{ + SECStatus rv = SECFailure; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifyResponse"); + + if (response->verifyFcn != NULL) { + void *lplContext = NULL; + + PKIX_CHECK( + PKIX_PL_NssContext_Create(((SECCertificateUsage)1) << certUsage, + PKIX_FALSE, NULL, &lplContext), + PKIX_NSSCONTEXTCREATEFAILED); + + PKIX_CHECK( + (response->verifyFcn)((PKIX_PL_Object*)response->pkixSignerCert, + NULL, response->producedAtDate, + procParams, pNBIOContext, + state, buildResult, + NULL, lplContext), + PKIX_CERTVERIFYKEYUSAGEFAILED); + rv = SECSuccess; + } else { + /* checkSig is !isRoot */ + PRBool checkSig = response->signerCert->isRoot ? PR_FALSE : PR_TRUE; + rv = CERT_VerifyCert(response->handle, response->signerCert, checkSig, + certUsage, response->producedAt, NULL, NULL); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_CERTVERIFYKEYUSAGEFAILED); + } + } + +cleanup: + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); + } + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_VerifySignature + * DESCRIPTION: + * + * This function verifies the ocspResponse signature field in the OcspResponse + * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification + * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an + * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode. + * + * PARAMETERS + * "response" + * The address of the OcspResponse whose signature field is to be + * retrieved. Must be non-NULL. + * "cert" + * The address of the Cert for which the OCSP query was made. Must be + * non-NULL. + * "procParams" + * Address of ProcessingParams used to initialize the ExpirationChecker + * and TargetCertChecker. Must be non-NULL. + * "pPassed" + * Address at which the Boolean result is stored. Must be non-NULL. + * "pNBIOContext" + * Address at which the NBIOContext is stored indicating whether the + * checking 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 an OcspResponse 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_pl_OcspResponse_VerifySignature( + PKIX_PL_OcspResponse *response, + PKIX_PL_Cert *cert, + PKIX_ProcessingParams *procParams, + PKIX_Boolean *pPassed, + void **pNBIOContext, + void *plContext) +{ + SECStatus rv = SECFailure; + CERTOCSPResponse *nssOCSPResponse = NULL; + CERTCertificate *issuerCert = NULL; + PKIX_BuildResult *buildResult = NULL; + void *nbio = NULL; + void *state = NULL; + + ocspSignature *signature = NULL; + ocspResponseData *tbsData = NULL; + SECItem *tbsResponseDataDER = NULL; + + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature"); + PKIX_NULLCHECK_FOUR(response, cert, pPassed, pNBIOContext); + + nbio = *pNBIOContext; + *pNBIOContext = NULL; + + nssOCSPResponse = response->nssOCSPResponse; + if (nssOCSPResponse == NULL) { + PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); + goto cleanup; + } + + tbsData = + ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER); + + signature = ocsp_GetResponseSignature(nssOCSPResponse); + + + /* Are we resuming after a WOULDBLOCK response? */ + if (nbio == NULL) { + /* No, this is a new query */ + + issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(), + certUsageAnyCA); + + /* + * If this signature has already gone through verification, + * just return the cached result. + */ + if (signature->wasChecked) { + if (signature->status == SECSuccess) { + response->signerCert = + CERT_DupCertificate(signature->cert); + } else { + PORT_SetError(signature->failureReason); + goto cleanup; + } + } + + response->signerCert = + ocsp_GetSignerCertificate(response->handle, tbsData, + signature, issuerCert); + + if (response->signerCert == NULL) { + if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) { + /* Make the error a little more specific. */ + PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT); + } + goto cleanup; + } + PKIX_CHECK( + PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert, + &(response->pkixSignerCert), + plContext), + PKIX_CERTCREATEWITHNSSCERTFAILED); + + /* + * We could mark this true at the top of this function, or + * always below at "finish", but if the problem was just that + * we could not find the signer's cert, leave that as if the + * signature hasn't been checked. Maybe a subsequent call will + * have better luck. + */ + signature->wasChecked = PR_TRUE; + + /* + * We are about to verify the signer certificate; we need to + * specify *when* that certificate must be valid -- for our + * purposes we expect it to be valid when the response was + * signed. The value of "producedAt" is the signing time. + */ + rv = DER_GeneralizedTimeToTime(&response->producedAt, + &tbsData->producedAt); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE); + goto cleanup; + } + + /* + * We need producedAtDate and pkixSignerCert if we are calling a + * user-supplied verification function. Let's put their + * creation before the code that gets repeated when + * non-blocking I/O is used. + */ + + PKIX_CHECK( + pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt, + &(response->producedAtDate), + plContext), + PKIX_DATECREATEFROMPRTIMEFAILED); + + } + + /* + * Just because we have a cert does not mean it is any good; check + * it for validity, trust and usage. Use the caller-supplied + * verification function, if one was supplied. + */ + if (ocsp_CertIsOCSPDefaultResponder(response->handle, + response->signerCert)) { + rv = SECSuccess; + } else { + SECCertUsage certUsage; + if (CERT_IsCACert(response->signerCert, NULL)) { + certUsage = certUsageAnyCA; + } else { + certUsage = certUsageStatusResponder; + } + PKIX_CHECK_ONLY_FATAL( + pkix_pl_OcspResponse_VerifyResponse(response, procParams, + certUsage, &state, + &buildResult, &nbio, + plContext), + PKIX_CERTVERIFYKEYUSAGEFAILED); + if (pkixTempErrorReceived) { + rv = SECFailure; + goto cleanup; + } + if (nbio != NULL) { + *pNBIOContext = nbio; + goto cleanup; + } + } + + rv = ocsp_VerifyResponseSignature(response->signerCert, signature, + tbsResponseDataDER, NULL); + +cleanup: + if (rv == SECSuccess) { + *pPassed = PKIX_TRUE; + } else { + *pPassed = PKIX_FALSE; + } + + if (signature) { + if (signature->wasChecked) { + signature->status = rv; + } + + if (rv != SECSuccess) { + signature->failureReason = PORT_GetError(); + if (response->signerCert != NULL) { + CERT_DestroyCertificate(response->signerCert); + response->signerCert = NULL; + } + } else { + /* Save signer's certificate in signature. */ + signature->cert = CERT_DupCertificate(response->signerCert); + } + } + + if (issuerCert) + CERT_DestroyCertificate(issuerCert); + + PKIX_RETURN(OCSPRESPONSE); +} + +/* + * FUNCTION: pkix_pl_OcspResponse_GetStatusForCert + * DESCRIPTION: + * + * This function checks the revocation status of the Cert for which the + * OcspResponse was obtained, storing PKIX_TRUE at "pPassed" if the Cert has + * not been revoked and PKIX_FALSE otherwise. + * + * PARAMETERS + * "response" + * The address of the OcspResponse whose certificate status is to be + * retrieved. Must be non-NULL. + * "pPassed" + * Address at which the Boolean result is stored. Must be non-NULL. + * "pReturnCode" + * Address at which the SECErrorCodes 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 an OcspResponse 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_pl_OcspResponse_GetStatusForCert( + PKIX_PL_OcspCertID *cid, + PKIX_PL_OcspResponse *response, + PKIX_Boolean allowCachingOfFailures, + PKIX_PL_Date *validity, + PKIX_Boolean *pPassed, + SECErrorCodes *pReturnCode, + void *plContext) +{ + PRTime time = 0; + SECStatus rv = SECFailure; + CERTOCSPSingleResponse *single = NULL; + + PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_GetStatusForCert"); + PKIX_NULLCHECK_THREE(response, pPassed, pReturnCode); + + /* + * It is an error to call this function except following a successful + * return from pkix_pl_OcspResponse_VerifySignature, which would have + * set response->signerCert. + */ + PKIX_NULLCHECK_TWO(response->signerCert, response->request); + PKIX_NULLCHECK_TWO(cid, cid->certID); + + if (validity != NULL) { + PKIX_Error *er = pkix_pl_Date_GetPRTime(validity, &time, plContext); + PKIX_DECREF(er); + } + if (!time) { + time = PR_Now(); + } + + rv = ocsp_GetVerifiedSingleResponseForCertID(response->handle, + response->nssOCSPResponse, + cid->certID, + response->signerCert, + time, &single); + if (rv == SECSuccess) { + /* + * Check whether the status says revoked, and if so + * how that compares to the time value passed into this routine. + */ + rv = ocsp_CertHasGoodStatus(single->certStatus, time); + } + + if (rv == SECSuccess || allowCachingOfFailures) { + /* allowed to update the cache */ + PRBool certIDWasConsumed = PR_FALSE; + + if (single) { + ocsp_CacheSingleResponse(cid->certID,single, + &certIDWasConsumed); + } else { + cert_RememberOCSPProcessingFailure(cid->certID, + &certIDWasConsumed); + } + + if (certIDWasConsumed) { + cid->certID = NULL; + } + } + + if (rv == SECSuccess) { + *pPassed = PKIX_TRUE; + *pReturnCode = 0; + } else { + *pPassed = PKIX_FALSE; + *pReturnCode = PORT_GetError(); + } + + PKIX_RETURN(OCSPRESPONSE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h new file mode 100644 index 0000000000..dcf88c9603 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h @@ -0,0 +1,106 @@ +/* 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_pl_ocspresponse.h + * + * OcspResponse Object Definitions + * + */ + +#ifndef _PKIX_PL_OCSPRESPONSE_H +#define _PKIX_PL_OCSPRESPONSE_H + +#include "pkix_pl_common.h" +#include "pkix_pl_ocspcertid.h" +#include "hasht.h" +#include "cryptohi.h" +#include "ocspti.h" +#include "ocspi.h" +#include "plbase64.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_OCSP_RESPONSE_LEN (64*1024) + +struct PKIX_PL_OcspResponseStruct{ + PLArenaPool *arena; + const PKIX_PL_OcspRequest *request; + const SEC_HttpClientFcn *httpClient; + SEC_HTTP_SERVER_SESSION serverSession; + SEC_HTTP_REQUEST_SESSION sessionRequest; + PKIX_PL_VerifyCallback verifyFcn; + SECItem *encodedResponse; + CERTCertDBHandle *handle; + PRTime producedAt; + PKIX_PL_Date *producedAtDate; + PKIX_PL_Cert *pkixSignerCert; + CERTOCSPResponse *nssOCSPResponse; + CERTCertificate *signerCert; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_OcspResponse_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_OcspResponse_Create( + PKIX_PL_OcspRequest *request, + const char *httpMechanism, + void *responder, + PKIX_PL_VerifyCallback verifyFcn, + void **pNBIOContext, + PKIX_PL_OcspResponse **pResponse, + void *plContext); + +PKIX_Error * +pkix_pl_OcspResponse_Decode( + PKIX_PL_OcspResponse *response, + PKIX_Boolean *passed, + SECErrorCodes *pReturnCode, + void *plContext); + +PKIX_Error * +pkix_pl_OcspResponse_GetStatus( + PKIX_PL_OcspResponse *response, + PKIX_Boolean *passed, + SECErrorCodes *pReturnCode, + void *plContext); + +PKIX_Error * +pkix_pl_OcspResponse_VerifySignature( + PKIX_PL_OcspResponse *response, + PKIX_PL_Cert *cert, + PKIX_ProcessingParams *procParams, + PKIX_Boolean *pPassed, + void **pNBIOContext, + void *plContext); + +PKIX_Error * +pkix_pl_OcspResponse_GetStatusForCert( + PKIX_PL_OcspCertID *cid, + PKIX_PL_OcspResponse *response, + PKIX_Boolean allowCachingOfFailures, + PKIX_PL_Date *validity, + PKIX_Boolean *pPassed, + SECErrorCodes *pReturnCode, + void *plContext); + +PKIX_Error * +PKIX_PL_OcspResponse_UseBuildChain( + PKIX_PL_Cert *signerCert, + PKIX_PL_Date *producedAt, + PKIX_ProcessingParams *procParams, + void **pNBIOContext, + void **pState, + PKIX_BuildResult **pBuildResult, + PKIX_VerifyNode **pVerifyTree, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_OCSPRESPONSE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c new file mode 100644 index 0000000000..2dfe9a9c2c --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c @@ -0,0 +1,489 @@ +/* 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_pl_publickey.c + * + * Certificate Object Functions + * + */ + +#include "pkix_pl_publickey.h" + +/* --Private-Cert-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_PublicKey_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the PublicKey + * pointed to by "pkixPubKey" and stores it at "pString". + * + * PARAMETERS + * "pkixPubKey" + * Address of PublicKey whose string representation is desired. + * Must be non-NULL. + * "pString" + * 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 PublicKey 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_pl_PublicKey_ToString_Helper( + PKIX_PL_PublicKey *pkixPubKey, + PKIX_PL_String **pString, + void *plContext) +{ + SECAlgorithmID algorithm; + SECOidTag pubKeyTag; + char *asciiOID = NULL; + PKIX_Boolean freeAsciiOID = PKIX_FALSE; + SECItem oidBytes; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper"); + PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString); + + /* + * XXX for now, we print out public key algorithm's + * description - add params and bytes later + */ + + /* + * If the algorithm OID is known to NSS, + * we print out the ASCII description that is + * registered with NSS. Otherwise, if unknown, + * we print out the OID numbers (eg. "1.2.840.3") + */ + + algorithm = pkixPubKey->nssSPKI->algorithm; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n"); + pubKeyTag = SECOID_GetAlgorithmTag(&algorithm); + if (pubKeyTag != SEC_OID_UNKNOWN){ + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling SECOID_FindOIDTagDescription).\n"); + asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag); + if (!asciiOID){ + PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); + } + } else { /* pubKeyTag == SEC_OID_UNKNOWN */ + oidBytes = algorithm.algorithm; + PKIX_CHECK(pkix_pl_oidBytes2Ascii + (&oidBytes, &asciiOID, plContext), + PKIX_OIDBYTES2ASCIIFAILED); + freeAsciiOID = PKIX_TRUE; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext), + PKIX_UNABLETOCREATEPSTRING); + +cleanup: + + /* + * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii + */ + if (freeAsciiOID){ + PKIX_FREE(asciiOID); + } + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_DestroySPKI + * DESCRIPTION: + * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to + * by "nssSPKI". + * PARAMETERS + * "nssSPKI" + * Address of CERTSubjectPublicKeyInfo. 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 Object 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_pl_DestroySPKI( + CERTSubjectPublicKeyInfo *nssSPKI, + void *plContext) +{ + PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI"); + + PKIX_NULLCHECK_ONE(nssSPKI); + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n"); + SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE); + + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); + SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE); + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_PublicKey *pubKey = NULL; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy"); + + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pubKey = (PKIX_PL_PublicKey *)object; + + if (pubKey->nssSPKI) { + + PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext), + PKIX_DESTROYSPKIFAILED); + + PKIX_FREE(pubKey->nssSPKI); + } + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_PublicKey *pkixPubKey = NULL; + PKIX_PL_String *pubKeyString = NULL; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pkixPubKey = (PKIX_PL_PublicKey *)object; + + PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper + (pkixPubKey, &pubKeyString, plContext), + PKIX_PUBLICKEYTOSTRINGHELPERFAILED); + + *pString = pubKeyString; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_PublicKey *pkixPubKey = NULL; + SECItem algOID; + SECItem algParams; + SECItem nssPubKey; + PKIX_UInt32 algOIDHash; + PKIX_UInt32 algParamsHash; + PKIX_UInt32 pubKeyHash; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_OBJECTNOTPUBLICKEY); + + pkixPubKey = (PKIX_PL_PublicKey *)object; + + PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI); + + algOID = pkixPubKey->nssSPKI->algorithm.algorithm; + algParams = pkixPubKey->nssSPKI->algorithm.parameters; + nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey; + + PKIX_CHECK(pkix_hash + (algOID.data, algOID.len, &algOIDHash, plContext), + PKIX_HASHFAILED); + + PKIX_CHECK(pkix_hash + (algParams.data, algParams.len, &algParamsHash, plContext), + PKIX_HASHFAILED); + + PKIX_CHECK(pkix_hash + (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext), + PKIX_HASHFAILED); + + *pHashcode = pubKeyHash; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + + +/* + * FUNCTION: pkix_pl_PublicKey_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_PublicKey_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_PublicKey *firstPKIXPubKey = NULL; + PKIX_PL_PublicKey *secondPKIXPubKey = NULL; + CERTSubjectPublicKeyInfo *firstSPKI = NULL; + CERTSubjectPublicKeyInfo *secondSPKI = NULL; + SECComparison cmpResult; + PKIX_UInt32 secondType; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is a PublicKey */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext), + PKIX_FIRSTOBJECTNOTPUBLICKEY); + + /* + * Since we know firstObject is a PublicKey, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't a PublicKey, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup; + + firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject); + secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject; + + firstSPKI = firstPKIXPubKey->nssSPKI; + secondSPKI = secondPKIXPubKey->nssSPKI; + + PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI); + + PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID, + (&firstSPKI->algorithm, &secondSPKI->algorithm)); + + if (cmpResult == SECEqual){ + PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); + cmpResult = SECITEM_CompareItem + (&firstSPKI->subjectPublicKey, + &secondSPKI->subjectPublicKey); + } + + *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: pkix_pl_PublicKey_RegisterSelf + * DESCRIPTION: + * Registers PKIX_PUBLICKEY_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_pl_PublicKey_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf"); + + entry.description = "PublicKey"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_PublicKey); + entry.destructor = pkix_pl_PublicKey_Destroy; + entry.equalsFunction = pkix_pl_PublicKey_Equals; + entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode; + entry.toStringFunction = pkix_pl_PublicKey_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + systemClasses[PKIX_PUBLICKEY_TYPE] = entry; + + PKIX_RETURN(PUBLICKEY); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PublicKey_NeedsDSAParameters( + PKIX_PL_PublicKey *pubKey, + PKIX_Boolean *pNeedsParams, + void *plContext) +{ + CERTSubjectPublicKeyInfo *nssSPKI = NULL; + KeyType pubKeyType; + PKIX_Boolean needsParams = PKIX_FALSE; + + PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters"); + PKIX_NULLCHECK_TWO(pubKey, pNeedsParams); + + nssSPKI = pubKey->nssSPKI; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + pubKeyType = CERT_GetCertKeyType(nssSPKI); + if (!pubKeyType){ + PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY); + } + + if ((pubKeyType == dsaKey) && + (nssSPKI->algorithm.parameters.len == 0)){ + needsParams = PKIX_TRUE; + } + + *pNeedsParams = needsParams; + +cleanup: + + PKIX_RETURN(PUBLICKEY); +} + +/* + * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey + * (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_PublicKey_MakeInheritedDSAPublicKey( + PKIX_PL_PublicKey *firstKey, + PKIX_PL_PublicKey *secondKey, + PKIX_PL_PublicKey **pResultKey, + void *plContext) +{ + CERTSubjectPublicKeyInfo *firstSPKI = NULL; + CERTSubjectPublicKeyInfo *secondSPKI = NULL; + CERTSubjectPublicKeyInfo *thirdSPKI = NULL; + PKIX_PL_PublicKey *resultKey = NULL; + KeyType firstPubKeyType; + KeyType secondPubKeyType; + SECStatus rv; + + PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey"); + PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey); + PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI); + + firstSPKI = firstKey->nssSPKI; + secondSPKI = secondKey->nssSPKI; + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + firstPubKeyType = CERT_GetCertKeyType(firstSPKI); + if (!firstPubKeyType){ + PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY); + } + + PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); + secondPubKeyType = CERT_GetCertKeyType(secondSPKI); + if (!secondPubKeyType){ + PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY); + } + + if ((firstPubKeyType == dsaKey) && + (firstSPKI->algorithm.parameters.len == 0)){ + if (secondPubKeyType != dsaKey) { + PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY); + } else if (secondSPKI->algorithm.parameters.len == 0) { + PKIX_ERROR + (PKIX_SECONDKEYDSAPUBLICKEY); + } else { + PKIX_CHECK(PKIX_PL_Calloc + (1, + sizeof (CERTSubjectPublicKeyInfo), + (void **)&thirdSPKI, + plContext), + PKIX_CALLOCFAILED); + + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling" + "SECKEY_CopySubjectPublicKeyInfo).\n"); + rv = SECKEY_CopySubjectPublicKeyInfo + (NULL, thirdSPKI, firstSPKI); + if (rv != SECSuccess) { + PKIX_ERROR + (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED); + } + + PKIX_PUBLICKEY_DEBUG + ("\t\tCalling SECITEM_CopyItem).\n"); + rv = SECITEM_CopyItem(NULL, + &thirdSPKI->algorithm.parameters, + &secondSPKI->algorithm.parameters); + + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + /* create a PKIX_PL_PublicKey object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_PUBLICKEY_TYPE, + sizeof (PKIX_PL_PublicKey), + (PKIX_PL_Object **)&resultKey, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* populate the SPKI field */ + resultKey->nssSPKI = thirdSPKI; + *pResultKey = resultKey; + } + } else { + *pResultKey = NULL; + } + +cleanup: + + if (thirdSPKI && PKIX_ERROR_RECEIVED){ + PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext), + PKIX_DESTROYSPKIFAILED); + PKIX_FREE(thirdSPKI); + } + + PKIX_RETURN(PUBLICKEY); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h new file mode 100644 index 0000000000..8918859d2d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.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_pl_publickey.h + * + * Public Key Object Definitions + * + */ + +#ifndef _PKIX_PL_PUBLICKEY_H +#define _PKIX_PL_PUBLICKEY_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_PublicKeyStruct { + CERTSubjectPublicKeyInfo *nssSPKI; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_PublicKey_RegisterSelf(void *plContext); + +PKIX_Error * +PKIX_PL_PublicKey_NeedsDSAParameters( + PKIX_PL_PublicKey *pubKey, + PKIX_Boolean *pNeedsParams, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_PUBLICKEY_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c new file mode 100644 index 0000000000..e37439cf01 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c @@ -0,0 +1,667 @@ +/* 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_pl_x500name.c + * + * X500Name Object Functions + * + */ + +#include "pkix_pl_x500name.h" + +/* --Private-X500Name-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_X500Name_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_X500Name_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_X500Name *name = NULL; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), + PKIX_OBJECTNOTANX500NAME); + + name = (PKIX_PL_X500Name *)object; + + /* PORT_FreeArena will destroy arena, and, allocated on it, CERTName + * and SECItem */ + if (name->arena) { + PORT_FreeArena(name->arena, PR_FALSE); + name->arena = NULL; + } + +cleanup: + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_X500Name_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_X500Name *name = NULL; + char *string = NULL; + PKIX_UInt32 strLength = 0; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), + PKIX_OBJECTNOTANX500NAME); + + name = (PKIX_PL_X500Name *)object; + string = CERT_NameToAscii(&name->nssDN); + if (!string){ + PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED); + } + strLength = PL_strlen(string); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, string, strLength, pString, plContext), + PKIX_STRINGCREATEFAILED); + +cleanup: + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_X500Name_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_X500Name *name = NULL; + SECItem *derBytes = NULL; + PKIX_UInt32 nameHash; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), + PKIX_OBJECTNOTANX500NAME); + + name = (PKIX_PL_X500Name *)object; + + /* we hash over the bytes in the DER encoding */ + + derBytes = &name->derName; + + PKIX_CHECK(pkix_hash + (derBytes->data, derBytes->len, &nameHash, plContext), + PKIX_HASHFAILED); + + *pHashcode = nameHash; + +cleanup: + + PKIX_RETURN(X500NAME); +} + + +/* + * FUNCTION: pkix_pl_X500Name_Equals + * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_X500Name_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* test that firstObject is an X500Name */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_X500NAME_TYPE, plContext), + PKIX_FIRSTOBJECTARGUMENTNOTANX500NAME); + + /* + * Since we know firstObject is an X500Name, if both references are + * identical, they must be equal + */ + if (firstObject == secondObject){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If secondObject isn't an X500Name, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_X500NAME_TYPE) goto cleanup; + + PKIX_CHECK( + PKIX_PL_X500Name_Match((PKIX_PL_X500Name *)firstObject, + (PKIX_PL_X500Name *)secondObject, + pResult, plContext), + PKIX_X500NAMEMATCHFAILED); + +cleanup: + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_RegisterSelf + * DESCRIPTION: + * Registers PKIX_X500NAME_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_pl_X500Name_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_RegisterSelf"); + + entry.description = "X500Name"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_X500Name); + entry.destructor = pkix_pl_X500Name_Destroy; + entry.equalsFunction = pkix_pl_X500Name_Equals; + entry.hashcodeFunction = pkix_pl_X500Name_Hashcode; + entry.toStringFunction = pkix_pl_X500Name_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_X500NAME_TYPE] = entry; + + PKIX_RETURN(X500NAME); +} + +#ifdef BUILD_LIBPKIX_TESTS +/* + * FUNCTION: pkix_pl_X500Name_CreateFromUtf8 + * + * DESCRIPTION: + * Creates an X500Name object from the RFC1485 string representation pointed + * to by "stringRep", and stores the result at "pName". If the string cannot + * be successfully converted, a non-fatal error is returned. + * + * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed to be + * called only by pkix tests programs. + * + * PARAMETERS: + * "stringRep" + * Address of the RFC1485 string to be converted. Must be non-NULL. + * "pName" + * Address where the X500Name 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 an X500NAME 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_pl_X500Name_CreateFromUtf8( + char *stringRep, + PKIX_PL_X500Name **pName, + void *plContext) +{ + PKIX_PL_X500Name *x500Name = NULL; + PLArenaPool *arena = NULL; + CERTName *nssDN = NULL; + SECItem *resultSecItem = NULL; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_CreateFromUtf8"); + PKIX_NULLCHECK_TWO(pName, stringRep); + + nssDN = CERT_AsciiToName(stringRep); + if (nssDN == NULL) { + PKIX_ERROR(PKIX_COULDNOTCREATENSSDN); + } + + arena = nssDN->arena; + + /* create a PKIX_PL_X500Name object */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_X500NAME_TYPE, + sizeof (PKIX_PL_X500Name), + (PKIX_PL_Object **)&x500Name, + plContext), + PKIX_COULDNOTCREATEX500NAMEOBJECT); + + /* populate the nssDN field */ + x500Name->arena = arena; + x500Name->nssDN.arena = arena; + x500Name->nssDN.rdns = nssDN->rdns; + + resultSecItem = + SEC_ASN1EncodeItem(arena, &x500Name->derName, nssDN, + CERT_NameTemplate); + + if (resultSecItem == NULL){ + PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); + } + + *pName = x500Name; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + if (x500Name) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name, + plContext); + } else if (nssDN) { + CERT_DestroyName(nssDN); + } + } + + PKIX_RETURN(X500NAME); +} +#endif /* BUILD_LIBPKIX_TESTS */ + +/* + * FUNCTION: pkix_pl_X500Name_GetCERTName + * + * DESCRIPTION: + * + * Returns the pointer to CERTName member of X500Name structure. + * + * Returned pointed should not be freed.2 + * + * PARAMETERS: + * "xname" + * Address of X500Name whose OrganizationName is to be extracted. Must be + * non-NULL. + * "pCERTName" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_X500Name_GetCERTName( + PKIX_PL_X500Name *xname, + CERTName **pCERTName, + void *plContext) +{ + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCERTName"); + PKIX_NULLCHECK_TWO(xname, pCERTName); + + *pCERTName = &xname->nssDN; + + PKIX_RETURN(X500NAME); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName (see comments in pkix_pl_pki.h) + */ + +PKIX_Error * +PKIX_PL_X500Name_CreateFromCERTName( + SECItem *derName, + CERTName *name, + PKIX_PL_X500Name **pName, + void *plContext) +{ + PLArenaPool *arena = NULL; + SECStatus rv = SECFailure; + PKIX_PL_X500Name *x500Name = NULL; + + PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_CreateFromCERTName"); + PKIX_NULLCHECK_ONE(pName); + if (derName == NULL && name == NULL) { + PKIX_ERROR(PKIX_NULLARGUMENT); + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_X500NAME_TYPE, + sizeof (PKIX_PL_X500Name), + (PKIX_PL_Object **)&x500Name, + plContext), + PKIX_COULDNOTCREATEX500NAMEOBJECT); + + x500Name->arena = arena; + x500Name->nssDN.arena = NULL; + + if (derName != NULL) { + rv = SECITEM_CopyItem(arena, &x500Name->derName, derName); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + } + + if (name != NULL) { + rv = CERT_CopyName(arena, &x500Name->nssDN, name); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_CERTCOPYNAMEFAILED); + } + } else { + rv = SEC_QuickDERDecodeItem(arena, &x500Name->nssDN, + CERT_NameTemplate, + &x500Name->derName); + if (rv == SECFailure) { + PKIX_ERROR(PKIX_SECQUICKDERDECODERFAILED); + } + } + + *pName = x500Name; + +cleanup: + if (PKIX_ERROR_RECEIVED) { + if (x500Name) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name, + plContext); + } else if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + } + + PKIX_RETURN(X500NAME); +} + +#ifdef BUILD_LIBPKIX_TESTS +/* + * FUNCTION: PKIX_PL_X500Name_Create (see comments in pkix_pl_pki.h) + * + * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed + * to be called only by pkix tests programs. + */ +PKIX_Error * +PKIX_PL_X500Name_Create( + PKIX_PL_String *stringRep, + PKIX_PL_X500Name **pName, + void *plContext) +{ + char *utf8String = NULL; + PKIX_UInt32 utf8Length = 0; + + PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Create"); + PKIX_NULLCHECK_TWO(pName, stringRep); + + /* + * convert the input PKIX_PL_String to PKIX_UTF8_NULL_TERM. + * we need to use this format specifier because + * CERT_AsciiToName expects a NULL-terminated UTF8 string. + * Since UTF8 allow NUL characters in the middle of the + * string, this is buggy. However, as a workaround, using + * PKIX_UTF8_NULL_TERM gives us a NULL-terminated UTF8 string. + */ + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stringRep, + PKIX_UTF8_NULL_TERM, + (void **)&utf8String, + &utf8Length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_CHECK( + pkix_pl_X500Name_CreateFromUtf8(utf8String, + pName, plContext), + PKIX_X500NAMECREATEFROMUTF8FAILED); + +cleanup: + PKIX_FREE(utf8String); + + PKIX_RETURN(X500NAME); +} +#endif /* BUILD_LIBPKIX_TESTS */ + +/* + * FUNCTION: PKIX_PL_X500Name_Match (see comments in pkix_pl_pki.h) + */ +PKIX_Error * +PKIX_PL_X500Name_Match( + PKIX_PL_X500Name *firstX500Name, + PKIX_PL_X500Name *secondX500Name, + PKIX_Boolean *pResult, + void *plContext) +{ + SECItem *firstDerName = NULL; + SECItem *secondDerName = NULL; + SECComparison cmpResult; + + PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Match"); + PKIX_NULLCHECK_THREE(firstX500Name, secondX500Name, pResult); + + if (firstX500Name == secondX500Name){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + firstDerName = &firstX500Name->derName; + secondDerName = &secondX500Name->derName; + + PKIX_NULLCHECK_TWO(firstDerName->data, secondDerName->data); + + cmpResult = SECITEM_CompareItem(firstDerName, secondDerName); + if (cmpResult != SECEqual) { + cmpResult = CERT_CompareName(&firstX500Name->nssDN, + &secondX500Name->nssDN); + } + + *pResult = (cmpResult == SECEqual); + +cleanup: + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_GetSECName + * + * DESCRIPTION: + * Returns a copy of CERTName DER representation allocated on passed in arena. + * If allocation on arena can not be done, NULL is stored at "pSECName". + * + * PARAMETERS: + * "xname" + * Address of X500Name whose CERTName flag is to be encoded. Must be + * non-NULL. + * "arena" + * Address of the PLArenaPool to be used in the encoding, and in which + * "pSECName" will be allocated. Must be non-NULL. + * "pSECName" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_X500Name_GetDERName( + PKIX_PL_X500Name *xname, + PLArenaPool *arena, + SECItem **pDERName, + void *plContext) +{ + SECItem *derName = NULL; + + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetDERName"); + + PKIX_NULLCHECK_THREE(xname, arena, pDERName); + + /* Return NULL is X500Name was not created from DER */ + if (xname->derName.data == NULL) { + *pDERName = NULL; + goto cleanup; + } + + derName = SECITEM_ArenaDupItem(arena, &xname->derName); + if (derName == NULL) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + *pDERName = derName; +cleanup: + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_GetCommonName + * + * DESCRIPTION: + * Extracts the CommonName component of the X500Name object pointed to by + * "xname", and stores the result at "pCommonName". If the CommonName cannot + * be successfully extracted, NULL is stored at "pCommonName". + * + * The returned string must be freed with PORT_Free. + * + * PARAMETERS: + * "xname" + * Address of X500Name whose CommonName is to be extracted. Must be + * non-NULL. + * "pCommonName" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_X500Name_GetCommonName( + PKIX_PL_X500Name *xname, + unsigned char **pCommonName, + void *plContext) +{ + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCommonName"); + PKIX_NULLCHECK_TWO(xname, pCommonName); + + *pCommonName = (unsigned char *)CERT_GetCommonName(&xname->nssDN); + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_GetCountryName + * + * DESCRIPTION: + * Extracts the CountryName component of the X500Name object pointed to by + * "xname", and stores the result at "pCountryName". If the CountryName cannot + * be successfully extracted, NULL is stored at "pCountryName". + * + * The returned string must be freed with PORT_Free. + * + * PARAMETERS: + * "xname" + * Address of X500Name whose CountryName is to be extracted. Must be + * non-NULL. + * "pCountryName" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_X500Name_GetCountryName( + PKIX_PL_X500Name *xname, + unsigned char **pCountryName, + void *plContext) +{ + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCountryName"); + PKIX_NULLCHECK_TWO(xname, pCountryName); + + *pCountryName = (unsigned char*)CERT_GetCountryName(&xname->nssDN); + + PKIX_RETURN(X500NAME); +} + +/* + * FUNCTION: pkix_pl_X500Name_GetOrgName + * + * DESCRIPTION: + * Extracts the OrganizationName component of the X500Name object pointed to by + * "xname", and stores the result at "pOrgName". If the OrganizationName cannot + * be successfully extracted, NULL is stored at "pOrgName". + * + * The returned string must be freed with PORT_Free. + * + * PARAMETERS: + * "xname" + * Address of X500Name whose OrganizationName is to be extracted. Must be + * non-NULL. + * "pOrgName" + * Address where 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_pl_X500Name_GetOrgName( + PKIX_PL_X500Name *xname, + unsigned char **pOrgName, + void *plContext) +{ + PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetOrgName"); + PKIX_NULLCHECK_TWO(xname, pOrgName); + + *pOrgName = (unsigned char*)CERT_GetOrgName(&xname->nssDN); + + PKIX_RETURN(X500NAME); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h new file mode 100644 index 0000000000..a62bdb82d5 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.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_pl_x500name.h + * + * X500Name Object Type Definitions + * + */ + +#ifndef _PKIX_PL_X500NAME_H +#define _PKIX_PL_X500NAME_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct PKIX_PL_X500NameStruct{ + PLArenaPool *arena; /* X500Name arena. Shared arena with nssDN + * and derName */ + CERTName nssDN; + SECItem derName; /* adding DER encoded CERTName to the structure + * to avoid unnecessary name encoding when pass + * der name to cert finder */ +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_pl_X500Name_RegisterSelf(void *plContext); + +PKIX_Error *pkix_pl_X500Name_GetDERName( + PKIX_PL_X500Name *xname, + PLArenaPool *arena, + SECItem **pSECName, + void *plContext); + +#ifdef BUILD_LIBPKIX_TESTS +PKIX_Error * pkix_pl_X500Name_CreateFromUtf8( + char *stringRep, + PKIX_PL_X500Name **pName, + void *plContext); +#endif /* BUILD_LIBPKIX_TESTS */ + +PKIX_Error *pkix_pl_X500Name_GetCommonName( + PKIX_PL_X500Name *xname, + unsigned char **pCommonName, + void *plContext); + +PKIX_Error * +pkix_pl_X500Name_GetCountryName( + PKIX_PL_X500Name *xname, + unsigned char **pCountryName, + void *plContext); + +PKIX_Error * +pkix_pl_X500Name_GetOrgName( + PKIX_PL_X500Name *xname, + unsigned char **pOrgName, + void *plContext); + +PKIX_Error * +pkix_pl_X500Name_GetCERTName( + PKIX_PL_X500Name *xname, + CERTName **pCERTName, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_X500NAME_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile new file mode 100644 index 0000000000..2b4b1574ab --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile @@ -0,0 +1,47 @@ +#! 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_pl_nss/system/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp new file mode 100644 index 0000000000..a2f759441e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/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_pl_nss_system_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_pl_bigint.h', + 'pkix_pl_bytearray.h', + 'pkix_pl_common.h', + 'pkix_pl_hashtable.h', + 'pkix_pl_lifecycle.h', + 'pkix_pl_mem.h', + 'pkix_pl_monitorlock.h', + 'pkix_pl_mutex.h', + 'pkix_pl_object.h', + 'pkix_pl_oid.h', + 'pkix_pl_primhash.h', + 'pkix_pl_rwlock.h', + 'pkix_pl_string.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn new file mode 100644 index 0000000000..a143a03eed --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn @@ -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/. +CORE_DEPTH = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_pl_common.h \ + pkix_pl_mem.h \ + pkix_pl_object.h \ + pkix_pl_string.h \ + pkix_pl_primhash.h \ + pkix_pl_bigint.h \ + pkix_pl_mutex.h \ + pkix_pl_bytearray.h \ + pkix_pl_lifecycle.h \ + pkix_pl_oid.h \ + pkix_pl_hashtable.h \ + pkix_pl_rwlock.h \ + pkix_pl_monitorlock.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_pl_bigint.c \ + pkix_pl_bytearray.c \ + pkix_pl_common.c \ + pkix_pl_error.c \ + pkix_pl_hashtable.c \ + pkix_pl_lifecycle.c \ + pkix_pl_mem.c \ + pkix_pl_monitorlock.c \ + pkix_pl_mutex.c \ + pkix_pl_object.c \ + pkix_pl_oid.c \ + pkix_pl_primhash.c \ + pkix_pl_rwlock.c \ + pkix_pl_string.c \ + $(NULL) + +LIBRARY_NAME = pkixsystem +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c new file mode 100644 index 0000000000..cd8e15ee4b --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c @@ -0,0 +1,398 @@ +/* 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_pl_bigint.c + * + * BigInt Object Functions + * + */ + +#include "pkix_pl_bigint.h" + +/* --Private-Big-Int-Functions------------------------------------ */ + +/* + * FUNCTION: pkix_pl_BigInt_Comparator + * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_BigInt_Comparator( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_BigInt *firstBigInt = NULL; + PKIX_PL_BigInt *secondBigInt = NULL; + char *firstPtr = NULL; + char *secondPtr = NULL; + PKIX_UInt32 firstLen, secondLen; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext), + PKIX_ARGUMENTSNOTBIGINTS); + + /* It's safe to cast */ + firstBigInt = (PKIX_PL_BigInt*)firstObject; + secondBigInt = (PKIX_PL_BigInt*)secondObject; + + *pResult = 0; + firstPtr = firstBigInt->dataRep; + secondPtr = secondBigInt->dataRep; + firstLen = firstBigInt->length; + secondLen = secondBigInt->length; + + if (firstLen < secondLen) { + *pResult = -1; + } else if (firstLen > secondLen) { + *pResult = 1; + } else if (firstLen == secondLen) { + PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n"); + *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen); + } + +cleanup: + + PKIX_RETURN(BIGINT); +} + +/* + * FUNCTION: pkix_pl_BigInt_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_BigInt_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_BigInt *bigInt = NULL; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext), + PKIX_OBJECTNOTBIGINT); + + bigInt = (PKIX_PL_BigInt*)object; + + PKIX_FREE(bigInt->dataRep); + bigInt->dataRep = NULL; + bigInt->length = 0; + +cleanup: + + PKIX_RETURN(BIGINT); +} + + +/* + * FUNCTION: pkix_pl_BigInt_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_BigInt_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_BigInt *bigInt = NULL; + char *outputText = NULL; + PKIX_UInt32 i, j, lengthChars; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext), + PKIX_OBJECTNOTBIGINT); + + bigInt = (PKIX_PL_BigInt*)object; + + /* number of chars = 2 * (number of bytes) + null terminator */ + lengthChars = (bigInt->length * 2) + 1; + + PKIX_CHECK(PKIX_PL_Malloc + (lengthChars, (void **)&outputText, plContext), + PKIX_MALLOCFAILED); + + for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){ + outputText[j] = pkix_i2hex + ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4)); + outputText[j+1] = pkix_i2hex + ((char) (*(bigInt->dataRep+i) & 0x0f)); + } + + outputText[lengthChars-1] = '\0'; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + outputText, + 0, + pString, + plContext), + PKIX_STRINGCREATEFAILED); + +cleanup: + + PKIX_FREE(outputText); + + PKIX_RETURN(BIGINT); +} + + +/* + * FUNCTION: pkix_pl_BigInt_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_BigInt_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_BigInt *bigInt = NULL; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext), + PKIX_OBJECTNOTBIGINT); + + bigInt = (PKIX_PL_BigInt*)object; + + PKIX_CHECK(pkix_hash + ((void *)bigInt->dataRep, + bigInt->length, + pHashcode, + plContext), + PKIX_HASHFAILED); + +cleanup: + + PKIX_RETURN(BIGINT); +} + +/* + * FUNCTION: pkix_pl_BigInt_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_BigInt_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Int32 cmpResult = 0; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext), + PKIX_FIRSTOBJECTNOTBIGINT); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + *pResult = PKIX_FALSE; + + if (secondType != PKIX_BIGINT_TYPE) goto cleanup; + + PKIX_CHECK(pkix_pl_BigInt_Comparator + (first, second, &cmpResult, plContext), + PKIX_BIGINTCOMPARATORFAILED); + + *pResult = (cmpResult == 0); + +cleanup: + + PKIX_RETURN(BIGINT); +} + +/* + * FUNCTION: pkix_pl_BigInt_RegisterSelf + * DESCRIPTION: + * Registers PKIX_BIGINT_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_pl_BigInt_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf"); + + entry.description = "BigInt"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_BigInt); + entry.destructor = pkix_pl_BigInt_Destroy; + entry.equalsFunction = pkix_pl_BigInt_Equals; + entry.hashcodeFunction = pkix_pl_BigInt_Hashcode; + entry.toStringFunction = pkix_pl_BigInt_ToString; + entry.comparator = pkix_pl_BigInt_Comparator; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_BIGINT_TYPE] = entry; + + PKIX_RETURN(BIGINT); +} + +/* + * FUNCTION: pkix_pl_BigInt_CreateWithBytes + * DESCRIPTION: + * + * Creates a new BigInt of size "length" representing the array of bytes + * pointed to by "bytes" and stores it at "pBigInt". The caller should make + * sure that the first byte is not 0x00 (unless it is the the only byte). + * This function does not do that checking. + * + * Once created, a PKIX_PL_BigInt object is immutable. + * + * PARAMETERS: + * "bytes" + * Address of array of bytes. Must be non-NULL. + * "length" + * Length of the array. Must be non-zero. + * "pBigInt" + * 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_pl_BigInt_CreateWithBytes( + char *bytes, + PKIX_UInt32 length, + PKIX_PL_BigInt **pBigInt, + void *plContext) +{ + PKIX_PL_BigInt *bigInt = NULL; + + PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes"); + PKIX_NULLCHECK_TWO(pBigInt, bytes); + + if (length == 0) { + PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID) + } + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_BIGINT_TYPE, + sizeof (PKIX_PL_BigInt), + (PKIX_PL_Object **)&bigInt, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + PKIX_CHECK(PKIX_PL_Malloc + (length, (void **)&(bigInt->dataRep), plContext), + PKIX_MALLOCFAILED); + + PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy(bigInt->dataRep, bytes, length); + + bigInt->length = length; + + *pBigInt = bigInt; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(bigInt); + } + + PKIX_RETURN(BIGINT); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_BigInt_Create( + PKIX_PL_String *stringRep, + PKIX_PL_BigInt **pBigInt, + void *plContext) +{ + PKIX_PL_BigInt *bigInt = NULL; + char *asciiString = NULL; + PKIX_UInt32 lengthBytes; + PKIX_UInt32 lengthString; + PKIX_UInt32 i; + char currChar; + + PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create"); + PKIX_NULLCHECK_TWO(pBigInt, stringRep); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (stringRep, + PKIX_ESCASCII, + (void **)&asciiString, + &lengthString, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + if ((lengthString == 0) || ((lengthString % 2) != 0)){ + PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH); + } + + if (lengthString != 2){ + if ((asciiString[0] == '0') && (asciiString[1] == '0')){ + PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00); + } + } + + for (i = 0; i < lengthString; i++) { + currChar = asciiString[i]; + if (!PKIX_ISXDIGIT(currChar)){ + PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT); + } + } + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_BIGINT_TYPE, + sizeof (PKIX_PL_BigInt), + (PKIX_PL_Object **)&bigInt, + plContext), + PKIX_COULDNOTCREATEOBJECT); + + /* number of bytes = 0.5 * (number of chars) */ + lengthBytes = lengthString/2; + + PKIX_CHECK(PKIX_PL_Malloc + (lengthBytes, (void **)&(bigInt->dataRep), plContext), + PKIX_MALLOCFAILED); + + for (i = 0; i < lengthString; i += 2){ + (bigInt->dataRep)[i/2] = + (pkix_hex2i(asciiString[i])<<4) | + pkix_hex2i(asciiString[i+1]); + } + + bigInt->length = lengthBytes; + + *pBigInt = bigInt; + +cleanup: + + PKIX_FREE(asciiString); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(bigInt); + } + + PKIX_RETURN(BIGINT); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h new file mode 100644 index 0000000000..b3df808a8d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.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_pl_bigint.h + * + * Bigint Object Definitions + * + */ + +#ifndef _PKIX_PL_BIGINT_H +#define _PKIX_PL_BIGINT_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_BigIntStruct { + char *dataRep; + PKIX_UInt32 length; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_BigInt_CreateWithBytes( + char *bytes, + PKIX_UInt32 length, + PKIX_PL_BigInt **pBigInt, + void *plContext); + +PKIX_Error *pkix_pl_BigInt_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_BIGINT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c new file mode 100644 index 0000000000..0a2e9c08f3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c @@ -0,0 +1,504 @@ +/* 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_pl_bytearray.c + * + * ByteArray Object Functions + * + */ + +#include "pkix_pl_bytearray.h" + +/* --Private-ByteArray-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_ByteArray_ToHexString + * DESCRIPTION: + * + * Creates a hex-String representation of the ByteArray pointed to by "array" + * and stores the result at "pString". The hex-String consists of hex-digit + * pairs separated by spaces, and the entire string enclosed within square + * brackets, e.g. [43 61 6E 20 79 6F 75 20 72 65 61 64 20 74 68 69 73 3F]. + * A zero-length ByteArray is represented as []. + * PARAMETERS + * "array" + * ByteArray to be represented by the hex-String; must be non-NULL + * "pString" + * Address where String 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_pl_ByteArray_ToHexString( + PKIX_PL_ByteArray *array, + PKIX_PL_String **pString, + void *plContext) +{ + char *tempText = NULL; + char *stringText = NULL; /* "[XX XX XX ...]" */ + PKIX_UInt32 i, outputLen, bufferSize; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToHexString"); + PKIX_NULLCHECK_TWO(array, pString); + + if ((array->length) == 0) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "[]", 0, pString, plContext), + PKIX_COULDNOTCREATESTRING); + } else { + /* + * Allocate space for format string + * '[' + "XX" + (n-1)*" XX" + ']' + '\0' + */ + bufferSize = 2 + (3*(array->length)); + + PKIX_CHECK(PKIX_PL_Malloc + (bufferSize, (void **)&stringText, plContext), + PKIX_COULDNOTALLOCATEMEMORY); + + stringText[0] = 0; + outputLen = 0; + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n"); + tempText = PR_smprintf + ("[%02X", (0x0FF&((char *)(array->array))[0])); + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n"); + outputLen += PL_strlen(tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n"); + stringText = PL_strcat(stringText, tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n"); + PR_smprintf_free(tempText); + + for (i = 1; i < array->length; i++) { + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n"); + tempText = PR_smprintf + (" %02X", (0x0FF&((char *)(array->array))[i])); + + if (tempText == NULL){ + PKIX_ERROR(PKIX_PRSMPRINTFFAILED); + } + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n"); + outputLen += PL_strlen(tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n"); + stringText = PL_strcat(stringText, tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n"); + PR_smprintf_free(tempText); + tempText = NULL; + } + + stringText[outputLen++] = ']'; + stringText[outputLen] = 0; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + stringText, + 0, + pString, + plContext), + PKIX_COULDNOTCREATESTRING); + } + +cleanup: + + PKIX_FREE(stringText); + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_Comparator + * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) + * + * NOTE: + * It is not clear that this definition of comparing byte arrays makes + * sense. It does allow you to tell whether two blocks of memory are + * identical, so we only use it for the Equals function (i.e. we don't + * register it as a Compare function for ByteArray). + */ +static PKIX_Error * +pkix_pl_ByteArray_Comparator( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_ByteArray *firstByteArray = NULL; + PKIX_PL_ByteArray *secondByteArray = NULL; + unsigned char *firstData = NULL; + unsigned char *secondData = NULL; + PKIX_UInt32 i; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Comparator"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_BYTEARRAY_TYPE, plContext), + PKIX_ARGUMENTSNOTBYTEARRAYS); + + /* It's safe to cast */ + firstByteArray = (PKIX_PL_ByteArray *)firstObject; + secondByteArray = (PKIX_PL_ByteArray *)secondObject; + + *pResult = 0; + firstData = (unsigned char *)firstByteArray->array; + secondData = (unsigned char *)secondByteArray->array; + + if (firstByteArray->length < secondByteArray->length) { + *pResult = -1; + } else if (firstByteArray->length > secondByteArray->length) { + *pResult = 1; + } else if (firstByteArray->length == secondByteArray->length) { + /* Check if both array contents are identical */ + for (i = 0; + (i < firstByteArray->length) && (*pResult == 0); + i++) { + if (firstData[i] < secondData[i]) { + *pResult = -1; + } else if (firstData[i] > secondData[i]) { + *pResult = 1; + } + } + } + +cleanup: + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_ByteArray_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_ByteArray *array = NULL; + char *tempText = NULL; + char *stringText = NULL; /* "[OOO, OOO, ... OOO]" */ + PKIX_UInt32 i, outputLen, bufferSize; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext), + PKIX_OBJECTNOTBYTEARRAY); + + array = (PKIX_PL_ByteArray *)object; + + if ((array->length) == 0) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "[]", 0, pString, plContext), + PKIX_COULDNOTCREATESTRING); + } else { + /* Allocate space for "XXX, ". */ + bufferSize = 2+5*array->length; + + /* Allocate space for format string */ + PKIX_CHECK(PKIX_PL_Malloc + (bufferSize, (void **)&stringText, plContext), + PKIX_MALLOCFAILED); + + stringText[0] = 0; + outputLen = 0; + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n"); + tempText = + PR_smprintf + ("[%03u", (0x0FF&((char *)(array->array))[0])); + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n"); + outputLen += PL_strlen(tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n"); + stringText = PL_strcat(stringText, tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n"); + PR_smprintf_free(tempText); + + for (i = 1; i < array->length; i++) { + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n"); + tempText = PR_smprintf + (", %03u", + (0x0FF&((char *)(array->array))[i])); + + if (tempText == NULL){ + PKIX_ERROR(PKIX_PRSMPRINTFFAILED); + } + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n"); + outputLen += PL_strlen(tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n"); + stringText = PL_strcat(stringText, tempText); + + PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n"); + PR_smprintf_free(tempText); + tempText = NULL; + } + + stringText[outputLen++] = ']'; + stringText[outputLen] = 0; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, stringText, 0, pString, plContext), + PKIX_STRINGCREATEFAILED); + + } + +cleanup: + + PKIX_FREE(stringText); + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_ByteArray_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Int32 cmpResult = 0; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + /* Sanity check: Test that "first" is a ByteArray */ + PKIX_CHECK(pkix_CheckType(first, PKIX_BYTEARRAY_TYPE, plContext), + PKIX_FIRSTARGUMENTNOTBYTEARRAY); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + /* If types differ, then we will return false */ + *pResult = PKIX_FALSE; + + /* Second type may not be a BA */ + if (secondType != PKIX_BYTEARRAY_TYPE) goto cleanup; + + /* It's safe to cast here */ + PKIX_CHECK(pkix_pl_ByteArray_Comparator + (first, second, &cmpResult, plContext), + PKIX_BYTEARRAYCOMPARATORFAILED); + + /* ByteArrays are equal iff Comparator Result is 0 */ + *pResult = (cmpResult == 0); + +cleanup: + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_ByteArray_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_ByteArray *array = NULL; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext), + PKIX_OBJECTNOTBYTEARRAY); + + array = (PKIX_PL_ByteArray*)object; + + PKIX_FREE(array->array); + array->array = NULL; + array->length = 0; + +cleanup: + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_ByteArray_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_ByteArray *array = NULL; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext), + PKIX_OBJECTNOTBYTEARRAY); + + array = (PKIX_PL_ByteArray*)object; + + PKIX_CHECK(pkix_hash + ((const unsigned char *)array->array, + array->length, + pHashcode, + plContext), + PKIX_HASHFAILED); + +cleanup: + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: pkix_pl_ByteArray_RegisterSelf + * DESCRIPTION: + * Registers PKIX_BYTEARRAY_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_pl_ByteArray_RegisterSelf(void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_RegisterSelf"); + + entry.description = "ByteArray"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_ByteArray); + entry.destructor = pkix_pl_ByteArray_Destroy; + entry.equalsFunction = pkix_pl_ByteArray_Equals; + entry.hashcodeFunction = pkix_pl_ByteArray_Hashcode; + entry.toStringFunction = pkix_pl_ByteArray_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_BYTEARRAY_TYPE] = entry; + + PKIX_RETURN(BYTEARRAY); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_ByteArray_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_ByteArray_Create( + void *array, + PKIX_UInt32 length, + PKIX_PL_ByteArray **pByteArray, + void *plContext) +{ + PKIX_PL_ByteArray *byteArray = NULL; + + PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_Create"); + PKIX_NULLCHECK_ONE(pByteArray); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_BYTEARRAY_TYPE, + sizeof (PKIX_PL_ByteArray), + (PKIX_PL_Object **)&byteArray, + plContext), + PKIX_COULDNOTCREATEOBJECTSTORAGE); + + byteArray->length = length; + byteArray->array = NULL; + + if (length != 0){ + /* Alloc space for array */ + PKIX_NULLCHECK_ONE(array); + + PKIX_CHECK(PKIX_PL_Malloc + (length, (void**)&(byteArray->array), plContext), + PKIX_MALLOCFAILED); + + PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy(byteArray->array, array, length); + } + + *pByteArray = byteArray; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(byteArray); + } + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: PKIX_PL_ByteArray_GetPointer (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_ByteArray_GetPointer( + PKIX_PL_ByteArray *byteArray, + void **pArray, + void *plContext) +{ + void *bytes = NULL; + PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetPointer"); + PKIX_NULLCHECK_TWO(byteArray, pArray); + + if (byteArray->length != 0){ + PKIX_CHECK(PKIX_PL_Malloc + (byteArray->length, &bytes, plContext), + PKIX_MALLOCFAILED); + + PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy + (bytes, byteArray->array, byteArray->length); + } + + *pArray = bytes; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(bytes); + } + + PKIX_RETURN(BYTEARRAY); +} + +/* + * FUNCTION: PKIX_PL_ByteArray_GetLength (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_ByteArray_GetLength( + PKIX_PL_ByteArray *byteArray, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetLength"); + PKIX_NULLCHECK_TWO(byteArray, pLength); + + *pLength = byteArray->length; + + PKIX_RETURN(BYTEARRAY); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h new file mode 100644 index 0000000000..4ba18eed74 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.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_pl_bytearray.h + * + * ByteArray Object Definitions + * + */ + +#ifndef _PKIX_PL_BYTEARRAY_H +#define _PKIX_PL_BYTEARRAY_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_ByteArrayStruct { + void *array; + PKIX_UInt32 length; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_ByteArray_ToHexString( + PKIX_PL_ByteArray *array, + PKIX_PL_String **pString, + void *plContext); + +PKIX_Error * +pkix_pl_ByteArray_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_BYTEARRAY_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c new file mode 100644 index 0000000000..831ce538d3 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c @@ -0,0 +1,1073 @@ +/* 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_common.c + * + * Common utility functions used by various PKIX_PL functions + * + */ + +#include "pkix_pl_common.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_LockObject + * DESCRIPTION: + * + * Locks the object pointed to by "object". + * + * PARAMETERS: + * "object" + * Address of object. 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_LockObject( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *objectHeader; + + PKIX_ENTER(OBJECT, "pkix_LockObject"); + PKIX_NULLCHECK_ONE(object); + + if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) { + goto cleanup; + } + + PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); + /* The header is sizeof(PKIX_PL_Object) before the object pointer */ + + objectHeader = object-1; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(objectHeader->lock); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_UnlockObject + * DESCRIPTION: + * + * Unlocks the object pointed to by "object". + * + * PARAMETERS: + * "object" + * Address of Object. 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_UnlockObject( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *objectHeader; + PRStatus result; + + PKIX_ENTER(OBJECT, "pkix_UnlockObject"); + PKIX_NULLCHECK_ONE(object); + + if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) { + goto cleanup; + } + + PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); + /* The header is sizeof(PKIX_PL_Object) before the object pointer */ + + objectHeader = object-1; + + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + result = PR_Unlock(objectHeader->lock); + + if (result == PR_FAILURE) { + PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n"); + PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT); + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_pl_UInt32_Overflows + * DESCRIPTION: + * + * Returns a PKIX_Boolean indicating whether the unsigned integer + * represented by "string" is too large to fit in 32-bits (i.e. + * whether it overflows). With the exception of the string "0", + * all other strings are stripped of any leading zeros. It is assumed + * that every character in "string" is from the set {'0' - '9'}. + * + * PARAMETERS + * "string" + * Address of array of bytes representing PKIX_UInt32 that's being tested + * for 32-bit overflow + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * PKIX_TRUE if PKIX_UInt32 represented by "string" overflows; + * PKIX_FALSE otherwise + */ +PKIX_Boolean +pkix_pl_UInt32_Overflows(char *string){ + char *firstNonZero = NULL; + PKIX_UInt32 length, i; + char *MAX_UINT32_STRING = "4294967295"; + + PKIX_DEBUG_ENTER(OID); + + PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); + length = PL_strlen(string); + + if (length < MAX_DIGITS_32){ + return (PKIX_FALSE); + } + + firstNonZero = string; + for (i = 0; i < length; i++){ + if (*string == '0'){ + firstNonZero++; + } + } + + PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); + length = PL_strlen(firstNonZero); + + if (length > MAX_DIGITS_32){ + return (PKIX_TRUE); + } + + PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); + if (length == MAX_DIGITS_32){ + PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n"); + if (PORT_Strcmp(firstNonZero, MAX_UINT32_STRING) > 0){ + return (PKIX_TRUE); + } + } + + return (PKIX_FALSE); +} + +/* + * FUNCTION: pkix_pl_getOIDToken + * DESCRIPTION: + * + * Takes the array of DER-encoded bytes pointed to by "derBytes" + * (representing an OID) and the value of "index" representing the index into + * the array, and decodes the bytes until an integer token is retrieved. If + * successful, this function stores the integer component at "pToken" and + * stores the index representing the next byte in the array at "pIndex" + * (following the last byte that was used in the decoding). This new output + * index can be used in subsequent calls as an input index, allowing each + * token of the OID to be retrieved consecutively. Note that there is a + * special case for the first byte, in that it encodes two separate integer + * tokens. For example, the byte {2a} represents the integer tokens {1,2}. + * This special case is not handled here and must be handled by the caller. + * + * PARAMETERS + * "derBytes" + * Address of array of bytes representing a DER-encoded OID. + * Must be non-NULL. + * "index" + * Index into the array that this function will begin decoding at. + * "pToken" + * Destination for decoded OID token. Must be non-NULL. + * "pIndex" + * Destination for index of next byte following last byte 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 an Object 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_pl_getOIDToken( + char *derBytes, + PKIX_UInt32 index, + PKIX_UInt32 *pToken, + PKIX_UInt32 *pIndex, + void *plContext) +{ + PKIX_UInt32 retval, i, tmp; + + PKIX_ENTER(OID, "pkix_pl_getOIDToken"); + PKIX_NULLCHECK_THREE(derBytes, pToken, pIndex); + + /* + * We should only need to parse a maximum of four bytes, because + * RFC 3280 "mandates support for OIDs which have arc elements + * with values that are less than 2^28, that is, they MUST be between + * 0 and 268,435,455, inclusive. This allows each arc element to be + * represented within a single 32 bit word." + */ + + for (i = 0, retval = 0; i < 4; i++) { + retval <<= 7; + tmp = derBytes[index]; + index++; + retval |= (tmp & 0x07f); + if ((tmp & 0x080) == 0){ + *pToken = retval; + *pIndex = index; + goto cleanup; + } + } + + PKIX_ERROR(PKIX_INVALIDENCODINGOIDTOKENVALUETOOBIG); + +cleanup: + + PKIX_RETURN(OID); + +} + +/* + * FUNCTION: pkix_pl_helperBytes2Ascii + * DESCRIPTION: + * + * Converts an array of integers pointed to by "tokens" with a length of + * "numTokens", to an ASCII string consisting of those integers with dots in + * between them and stores the result at "pAscii". The ASCII representation is + * guaranteed to end with a NUL character. This is particularly useful for + * OID's and IP Addresses. + * + * The return value "pAscii" is not reference-counted and will need to + * be freed with PKIX_PL_Free. + * + * PARAMETERS + * "tokens" + * Address of array of integers. Must be non-NULL. + * "numTokens" + * Length of array of integers. Must be non-zero. + * "pAscii" + * 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 Object 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_pl_helperBytes2Ascii( + PKIX_UInt32 *tokens, + PKIX_UInt32 numTokens, + char **pAscii, + void *plContext) +{ + char *tempString = NULL; + char *outputString = NULL; + char *format = "%d"; + PKIX_UInt32 i = 0; + PKIX_UInt32 outputLen = 0; + PKIX_Int32 error; + + PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii"); + PKIX_NULLCHECK_TWO(tokens, pAscii); + + if (numTokens == 0) { + PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO); + } + + /* + * tempString will hold the string representation of a PKIX_UInt32 type + * The maximum value that can be held by an unsigned 32-bit integer + * is (2^32 - 1) = 4294967295 (which is ten digits long) + * Since tempString will hold the string representation of a + * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0') + */ + + PKIX_CHECK(PKIX_PL_Malloc + (MAX_DIGITS_32 + 1, (void **)&tempString, plContext), + PKIX_MALLOCFAILED); + + for (i = 0; i < numTokens; i++){ + PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); + error = PR_snprintf(tempString, + MAX_DIGITS_32 + 1, + format, + tokens[i]); + if (error == -1){ + PKIX_ERROR(PKIX_PRSNPRINTFFAILED); + } + + PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n"); + outputLen += PL_strlen(tempString); + + /* Include a dot to separate each number */ + outputLen++; + } + + /* Allocate space for the destination string */ + PKIX_CHECK(PKIX_PL_Malloc + (outputLen, (void **)&outputString, plContext), + PKIX_MALLOCFAILED); + + *outputString = '\0'; + + /* Concatenate all strings together */ + for (i = 0; i < numTokens; i++){ + + PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); + error = PR_snprintf(tempString, + MAX_DIGITS_32 + 1, + format, + tokens[i]); + if (error == -1){ + PKIX_ERROR(PKIX_PRSNPRINTFFAILED); + } + + PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); + (void) PL_strcat(outputString, tempString); + + /* we don't want to put a "." at the very end */ + if (i < (numTokens - 1)){ + PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); + (void) PL_strcat(outputString, "."); + } + } + + /* Ensure output string ends with terminating null */ + outputString[outputLen-1] = '\0'; + + *pAscii = outputString; + outputString = NULL; + +cleanup: + + PKIX_FREE(outputString); + PKIX_FREE(tempString); + + PKIX_RETURN(OBJECT); + +} + +/* + * FUNCTION: pkix_pl_ipAddrBytes2Ascii + * DESCRIPTION: + * + * Converts the DER encoding of an IPAddress pointed to by "secItem" to an + * ASCII representation and stores the result at "pAscii". The ASCII + * representation is guaranteed to end with a NUL character. The input + * SECItem must contain non-NULL data and must have a positive length. + * + * The return value "pAscii" is not reference-counted and will need to + * be freed with PKIX_PL_Free. + * XXX this function assumes that IPv4 addresses are being used + * XXX what about IPv6? can NSS tell the difference + * + * PARAMETERS + * "secItem" + * Address of SECItem which contains bytes and length of DER encoding. + * Must be non-NULL. + * "pAscii" + * 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 Object 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_pl_ipAddrBytes2Ascii( + SECItem *secItem, + char **pAscii, + void *plContext) +{ + char *data = NULL; + PKIX_UInt32 *tokens = NULL; + PKIX_UInt32 numTokens = 0; + PKIX_UInt32 i = 0; + char *asciiString = NULL; + + PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii"); + PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); + + if (secItem->len == 0) { + PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO); + } + + data = (char *)(secItem->data); + numTokens = secItem->len; + + /* allocate space for array of integers */ + PKIX_CHECK(PKIX_PL_Malloc + (numTokens * sizeof (PKIX_UInt32), + (void **)&tokens, + plContext), + PKIX_MALLOCFAILED); + + /* populate array of integers */ + for (i = 0; i < numTokens; i++){ + tokens[i] = data[i]; + } + + /* convert array of integers to ASCII */ + PKIX_CHECK(pkix_pl_helperBytes2Ascii + (tokens, numTokens, &asciiString, plContext), + PKIX_HELPERBYTES2ASCIIFAILED); + + *pAscii = asciiString; + +cleanup: + + PKIX_FREE(tokens); + + PKIX_RETURN(OBJECT); +} + + +/* + * FUNCTION: pkix_pl_oidBytes2Ascii + * DESCRIPTION: + * + * Converts the DER encoding of an OID pointed to by "secItem" to an ASCII + * representation and stores it at "pAscii". The ASCII representation is + * guaranteed to end with a NUL character. The input SECItem must contain + * non-NULL data and must have a positive length. + * + * Example: the six bytes {2a 86 48 86 f7 0d} represent the + * four integer tokens {1, 2, 840, 113549}, which we will convert + * into ASCII yielding "1.2.840.113549" + * + * The return value "pAscii" is not reference-counted and will need to + * be freed with PKIX_PL_Free. + * + * PARAMETERS + * "secItem" + * Address of SECItem which contains bytes and length of DER encoding. + * Must be non-NULL. + * "pAscii" + * 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 OID 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_pl_oidBytes2Ascii( + SECItem *secItem, + char **pAscii, + void *plContext) +{ + char *data = NULL; + PKIX_UInt32 *tokens = NULL; + PKIX_UInt32 token = 0; + PKIX_UInt32 numBytes = 0; + PKIX_UInt32 numTokens = 0; + PKIX_UInt32 i = 0, x = 0, y = 0; + PKIX_UInt32 index = 0; + char *asciiString = NULL; + + PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii"); + PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); + + if (secItem->len == 0) { + PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO); + } + + data = (char *)(secItem->data); + numBytes = secItem->len; + numTokens = 0; + + /* calculate how many integer tokens are represented by the bytes. */ + for (i = 0; i < numBytes; i++){ + if ((data[i] & 0x080) == 0){ + numTokens++; + } + } + + /* if we are unable to retrieve any tokens at all, we throw an error */ + if (numTokens == 0){ + PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID); + } + + /* add one more token b/c the first byte always contains two tokens */ + numTokens++; + + /* allocate space for array of integers */ + PKIX_CHECK(PKIX_PL_Malloc + (numTokens * sizeof (PKIX_UInt32), + (void **)&tokens, + plContext), + PKIX_MALLOCFAILED); + + /* populate array of integers */ + for (i = 0; i < numTokens; i++){ + + /* retrieve integer token */ + PKIX_CHECK(pkix_pl_getOIDToken + (data, index, &token, &index, plContext), + PKIX_GETOIDTOKENFAILED); + + if (i == 0){ + + /* + * special case: the first DER-encoded byte represents + * two tokens. We take advantage of fact that first + * token must be 0, 1, or 2; and second token must be + * between {0, 39} inclusive if first token is 0 or 1. + */ + + if (token < 40) + x = 0; + else if (token < 80) + x = 1; + else + x = 2; + y = token - (x * 40); + + tokens[0] = x; + tokens[1] = y; + i++; + } else { + tokens[i] = token; + } + } + + /* convert array of integers to ASCII */ + PKIX_CHECK(pkix_pl_helperBytes2Ascii + (tokens, numTokens, &asciiString, plContext), + PKIX_HELPERBYTES2ASCIIFAILED); + + *pAscii = asciiString; + +cleanup: + + PKIX_FREE(tokens); + PKIX_RETURN(OID); + +} + +/* + * FUNCTION: pkix_UTF16_to_EscASCII + * DESCRIPTION: + * + * Converts array of bytes pointed to by "utf16String" with length of + * "utf16Length" (which must be even) into a freshly allocated Escaped ASCII + * string and stores a pointer to that string at "pDest" and stores the + * string's length at "pLength". The Escaped ASCII string's length does not + * include the final NUL character. The caller is responsible for freeing + * "pDest" using PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug + * encoding. + * + * PARAMETERS: + * "utf16String" + * Address of array of bytes representing data source. Must be non-NULL. + * "utf16Length" + * Length of data source. Must be even. + * "debug" + * Boolean value indicating whether debug mode is desired. + * "pDest" + * Address where data will be stored. Must be non-NULL. + * "pLength" + * Address where data length 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 String 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_UTF16_to_EscASCII( + const void *utf16String, + PKIX_UInt32 utf16Length, + PKIX_Boolean debug, + char **pDest, + PKIX_UInt32 *pLength, + void *plContext) +{ + char *destPtr = NULL; + PKIX_UInt32 i, charLen; + PKIX_UInt32 x = 0, y = 0, z = 0; + unsigned char *utf16Char = (unsigned char *)utf16String; + + PKIX_ENTER(STRING, "pkix_UTF16_to_EscASCII"); + PKIX_NULLCHECK_THREE(utf16String, pDest, pLength); + + /* Assume every pair of bytes becomes &#xNNNN; */ + charLen = 4*utf16Length; + + /* utf16Lenght must be even */ + if ((utf16Length % 2) != 0){ + PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR); + } + + /* Count how many bytes we need */ + for (i = 0; i < utf16Length; i += 2) { + if ((utf16Char[i] == 0x00)&& + pkix_isPlaintext(utf16Char[i+1], debug)) { + if (utf16Char[i+1] == '&') { + /* Need to convert this to & */ + charLen -= 3; + } else { + /* We can fit this into one char */ + charLen -= 7; + } + } else if ((utf16Char[i] >= 0xD8) && (utf16Char[i] <= 0xDB)) { + if ((i+3) >= utf16Length) { + PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR); + } else if ((utf16Char[i+2] >= 0xDC)&& + (utf16Char[i+2] <= 0xDF)) { + /* Quartet of bytes will become &#xNNNNNNNN; */ + charLen -= 4; + /* Quartet of bytes will produce 12 chars */ + i += 2; + } else { + /* Second pair should be DC00-DFFF */ + PKIX_ERROR(PKIX_UTF16LOWZONEERROR); + } + } + } + + *pLength = charLen; + + /* Ensure this string is null terminated */ + charLen++; + + /* Allocate space for character array */ + PKIX_CHECK(PKIX_PL_Malloc(charLen, (void **)pDest, plContext), + PKIX_MALLOCFAILED); + + destPtr = *pDest; + for (i = 0; i < utf16Length; i += 2) { + if ((utf16Char[i] == 0x00)&& + pkix_isPlaintext(utf16Char[i+1], debug)) { + /* Write a single character */ + *destPtr++ = utf16Char[i+1]; + } else if ((utf16Char[i+1] == '&') && (utf16Char[i] == 0x00)){ + *destPtr++ = '&'; + *destPtr++ = 'a'; + *destPtr++ = 'm'; + *destPtr++ = 'p'; + *destPtr++ = ';'; + } else if ((utf16Char[i] >= 0xD8)&& + (utf16Char[i] <= 0xDB)&& + (utf16Char[i+2] >= 0xDC)&& + (utf16Char[i+2] <= 0xDF)) { + /* + * Special UTF pairs are of the form: + * x = D800..DBFF; y = DC00..DFFF; + * The result is of the form: + * ((x - D800) * 400 + (y - DC00)) + 0001 0000 + */ + x = 0x0FFFF & ((utf16Char[i]<<8) | utf16Char[i+1]); + y = 0x0FFFF & ((utf16Char[i+2]<<8) | utf16Char[i+3]); + z = ((x - 0xD800) * 0x400 + (y - 0xDC00)) + 0x00010000; + + /* Sprintf &#xNNNNNNNN; */ + PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n"); + if (PR_snprintf(destPtr, 13, "&#x%08X;", z) == + (PKIX_UInt32)(-1)) { + PKIX_ERROR(PKIX_PRSNPRINTFFAILED); + } + i += 2; + destPtr += 12; + } else { + /* Sprintf &#xNNNN; */ + PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n"); + if (PR_snprintf + (destPtr, + 9, + "&#x%02X%02X;", + utf16Char[i], + utf16Char[i+1]) == + (PKIX_UInt32)(-1)) { + PKIX_ERROR(PKIX_PRSNPRINTFFAILED); + } + destPtr += 8; + } + } + *destPtr = '\0'; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(*pDest); + } + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_EscASCII_to_UTF16 + * DESCRIPTION: + * + * Converts array of bytes pointed to by "escAsciiString" with length of + * "escAsciiLength" into a freshly allocated UTF-16 string and stores a + * pointer to that string at "pDest" and stores the string's length at + * "pLength". The caller is responsible for freeing "pDest" using + * PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug encoding. + * + * PARAMETERS: + * "escAsciiString" + * Address of array of bytes representing data source. Must be non-NULL. + * "escAsciiLength" + * Length of data source. Must be even. + * "debug" + * Boolean value indicating whether debug mode is desired. + * "pDest" + * Address where data will be stored. Must be non-NULL. + * "pLength" + * Address where data length 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 String 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_EscASCII_to_UTF16( + const char *escAsciiString, + PKIX_UInt32 escAsciiLen, + PKIX_Boolean debug, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_UInt32 newLen, i, j, charSize; + PKIX_UInt32 x = 0, y = 0, z = 0; + unsigned char *destPtr = NULL; + unsigned char testChar, testChar2; + unsigned char *stringData = (unsigned char *)escAsciiString; + + PKIX_ENTER(STRING, "pkix_EscASCII_to_UTF16"); + PKIX_NULLCHECK_THREE(escAsciiString, pDest, pLength); + + if (escAsciiLen == 0) { + PKIX_CHECK(PKIX_PL_Malloc(escAsciiLen, pDest, plContext), + PKIX_MALLOCFAILED); + goto cleanup; + } + + /* Assume each unicode character takes two bytes */ + newLen = escAsciiLen*2; + + /* Count up number of unicode encoded characters */ + for (i = 0; i < escAsciiLen; i++) { + if (!pkix_isPlaintext(stringData[i], debug)&& + (stringData[i] != '&')) { + PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII); + } else if (PL_strstr(escAsciiString+i, "&") == + escAsciiString+i) { + /* Convert EscAscii "&" to two bytes */ + newLen -= 8; + i += 4; + } else if ((PL_strstr(escAsciiString+i, "&#x") == + escAsciiString+i)|| + (PL_strstr(escAsciiString+i, "&#X") == + escAsciiString+i)) { + if (((i+7) <= escAsciiLen)&& + (escAsciiString[i+7] == ';')) { + /* Convert &#xNNNN; to two bytes */ + newLen -= 14; + i += 7; + } else if (((i+11) <= escAsciiLen)&& + (escAsciiString[i+11] == ';')) { + /* Convert &#xNNNNNNNN; to four bytes */ + newLen -= 20; + i += 11; + } else { + PKIX_ERROR(PKIX_ILLEGALUSEOFAMP); + } + } + } + + PKIX_CHECK(PKIX_PL_Malloc(newLen, pDest, plContext), + PKIX_MALLOCFAILED); + + /* Copy into newly allocated space */ + destPtr = (unsigned char *)*pDest; + + i = 0; + while (i < escAsciiLen) { + /* Copy each byte until you hit a & */ + if (pkix_isPlaintext(escAsciiString[i], debug)) { + *destPtr++ = 0x00; + *destPtr++ = escAsciiString[i++]; + } else if (PL_strstr(escAsciiString+i, "&") == + escAsciiString+i) { + /* Convert EscAscii "&" to two bytes */ + *destPtr++ = 0x00; + *destPtr++ = '&'; + i += 5; + } else if (((PL_strstr(escAsciiString+i, "&#x") == + escAsciiString+i)|| + (PL_strstr(escAsciiString+i, "&#X") == + escAsciiString+i))&& + ((i+7) <= escAsciiLen)) { + + /* We're either looking at &#xNNNN; or &#xNNNNNNNN; */ + charSize = (escAsciiString[i+7] == ';')?4:8; + + /* Skip past the &#x */ + i += 3; + + /* Make sure there is a terminating semi-colon */ + if (((i+charSize) > escAsciiLen)|| + (escAsciiString[i+charSize] != ';')) { + PKIX_ERROR(PKIX_TRUNCATEDUNICODEINESCAPEDASCII); + } + + for (j = 0; j < charSize; j++) { + if (!PKIX_ISXDIGIT + (escAsciiString[i+j])) { + PKIX_ERROR(PKIX_ILLEGALUNICODECHARACTER); + } else if (charSize == 8) { + x |= (pkix_hex2i + (escAsciiString[i+j])) + <<(4*(7-j)); + } + } + + testChar = + (pkix_hex2i(escAsciiString[i])<<4)| + pkix_hex2i(escAsciiString[i+1]); + testChar2 = + (pkix_hex2i(escAsciiString[i+2])<<4)| + pkix_hex2i(escAsciiString[i+3]); + + if (charSize == 4) { + if ((testChar >= 0xD8)&& + (testChar <= 0xDF)) { + PKIX_ERROR(PKIX_ILLEGALSURROGATEPAIR); + } else if ((testChar == 0x00)&& + pkix_isPlaintext(testChar2, debug)) { + PKIX_ERROR( + PKIX_ILLEGALCHARACTERINESCAPEDASCII); + } + *destPtr++ = testChar; + *destPtr++ = testChar2; + } else if (charSize == 8) { + /* First two chars must be 0001-0010 */ + if (!((testChar == 0x00)&& + ((testChar2 >= 0x01)&& + (testChar2 <= 0x10)))) { + PKIX_ERROR( + PKIX_ILLEGALCHARACTERINESCAPEDASCII); + } + /* + * Unicode Strings of the form: + * x = 0001 0000..0010 FFFF + * Encoded as pairs of UTF-16 where + * y = ((x - 0001 0000) / 400) + D800 + * z = ((x - 0001 0000) % 400) + DC00 + */ + x -= 0x00010000; + y = (x/0x400)+ 0xD800; + z = (x%0x400)+ 0xDC00; + + /* Copy four bytes */ + *destPtr++ = (y&0xFF00)>>8; + *destPtr++ = (y&0x00FF); + *destPtr++ = (z&0xFF00)>>8; + *destPtr++ = (z&0x00FF); + } + /* Move past the Hex digits and the semi-colon */ + i += charSize+1; + } else { + /* Do not allow any other non-plaintext character */ + PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII); + } + } + + *pLength = newLen; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(*pDest); + } + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_UTF16_to_UTF8 + * DESCRIPTION: + * + * Converts array of bytes pointed to by "utf16String" with length of + * "utf16Length" into a freshly allocated UTF-8 string and stores a pointer + * to that string at "pDest" and stores the string's length at "pLength" (not + * counting the null terminator, if requested. The caller is responsible for + * freeing "pDest" using PKIX_PL_Free. + * + * PARAMETERS: + * "utf16String" + * Address of array of bytes representing data source. Must be non-NULL. + * "utf16Length" + * Length of data source. Must be even. + * "null-term" + * Boolean value indicating whether output should be null-terminated. + * "pDest" + * Address where data will be stored. Must be non-NULL. + * "pLength" + * Address where data length 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 String 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_UTF16_to_UTF8( + const void *utf16String, + PKIX_UInt32 utf16Length, + PKIX_Boolean null_term, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_Boolean result; + PKIX_UInt32 reallocLen; + char *endPtr = NULL; + + PKIX_ENTER(STRING, "pkix_UTF16_to_UTF8"); + PKIX_NULLCHECK_THREE(utf16String, pDest, pLength); + + /* XXX How big can a UTF8 string be compared to a UTF16? */ + PKIX_CHECK(PKIX_PL_Calloc(1, utf16Length*2, pDest, plContext), + PKIX_CALLOCFAILED); + + PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n"); + result = PORT_UCS2_UTF8Conversion + (PKIX_FALSE, /* False = From UCS2 */ + (unsigned char *)utf16String, + utf16Length, + (unsigned char *)*pDest, + utf16Length*2, /* Max Size */ + pLength); + if (result == PR_FALSE){ + PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED); + } + + reallocLen = *pLength; + + if (null_term){ + reallocLen++; + } + + PKIX_CHECK(PKIX_PL_Realloc(*pDest, reallocLen, pDest, plContext), + PKIX_REALLOCFAILED); + + if (null_term){ + endPtr = (char*)*pDest + reallocLen - 1; + *endPtr = '\0'; + } + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(*pDest); + } + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_UTF8_to_UTF16 + * DESCRIPTION: + * + * Converts array of bytes pointed to by "utf8String" with length of + * "utf8Length" into a freshly allocated UTF-16 string and stores a pointer + * to that string at "pDest" and stores the string's length at "pLength". The + * caller is responsible for freeing "pDest" using PKIX_PL_Free. + * + * PARAMETERS: + * "utf8String" + * Address of array of bytes representing data source. Must be non-NULL. + * "utf8Length" + * Length of data source. Must be even. + * "pDest" + * Address where data will be stored. Must be non-NULL. + * "pLength" + * Address where data length 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 String 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_UTF8_to_UTF16( + const void *utf8String, + PKIX_UInt32 utf8Length, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_Boolean result; + + PKIX_ENTER(STRING, "pkix_UTF8_to_UTF16"); + PKIX_NULLCHECK_THREE(utf8String, pDest, pLength); + + /* XXX How big can a UTF8 string be compared to a UTF16? */ + PKIX_CHECK(PKIX_PL_Calloc(1, utf8Length*2, pDest, plContext), + PKIX_MALLOCFAILED); + + PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n"); + result = PORT_UCS2_UTF8Conversion + (PKIX_TRUE, /* True = From UTF8 */ + (unsigned char *)utf8String, + utf8Length, + (unsigned char *)*pDest, + utf8Length*2, /* Max Size */ + pLength); + if (result == PR_FALSE){ + PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED); + } + + PKIX_CHECK(PKIX_PL_Realloc(*pDest, *pLength, pDest, plContext), + PKIX_REALLOCFAILED); + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(*pDest); + } + + PKIX_RETURN(STRING); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h new file mode 100644 index 0000000000..2946e07a67 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h @@ -0,0 +1,159 @@ +/* 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_pl_common.h + * + * Common central header file included by all PL source files + * + */ + +#ifndef _PKIX_PL_COMMON_H +#define _PKIX_PL_COMMON_H + +/* PKIX HEADERS */ +#include "pkix_tools.h" + +/* NSS headers */ +#include "nss.h" +#include "secport.h" +#include "secasn1.h" +#include "secerr.h" +#include "base64.h" +#include "cert.h" +#include "certdb.h" +#include "genname.h" +#include "xconst.h" +#include "keyhi.h" +#include "ocsp.h" +#include "ocspt.h" +#include "pk11pub.h" +#include "pkcs11.h" +#include "pkcs11t.h" +#include "prio.h" + +/* NSPR headers */ +#include "nspr.h" + +/* private PKIX_PL_NSS system headers */ +#include "pkix_pl_object.h" +#include "pkix_pl_string.h" +#ifndef NSS_PKIX_NO_LDAP +#include "pkix_pl_ldapt.h" +#endif /* !NSS_PKIX_NO_LDAP */ +#include "pkix_pl_aiamgr.h" +#include "pkix_pl_bigint.h" +#include "pkix_pl_oid.h" +#include "pkix_pl_x500name.h" +#include "pkix_pl_generalname.h" +#include "pkix_pl_publickey.h" +#include "pkix_pl_bytearray.h" +#include "pkix_pl_date.h" +#include "pkix_pl_primhash.h" +#include "pkix_pl_basicconstraints.h" +#include "pkix_pl_bytearray.h" +#include "pkix_pl_cert.h" +#include "pkix_pl_certpolicyinfo.h" +#include "pkix_pl_certpolicymap.h" +#include "pkix_pl_certpolicyqualifier.h" +#include "pkix_pl_crldp.h" +#include "pkix_pl_crl.h" +#include "pkix_pl_crlentry.h" +#include "pkix_pl_nameconstraints.h" +#include "pkix_pl_ocsprequest.h" +#include "pkix_pl_ocspresponse.h" +#include "pkix_pl_pk11certstore.h" +#include "pkix_pl_socket.h" +#ifndef NSS_PKIX_NO_LDAP +#include "pkix_pl_ldapcertstore.h" +#include "pkix_pl_ldaprequest.h" +#include "pkix_pl_ldapresponse.h" +#endif /* !NSS_PKIX_NO_LDAP */ +#include "pkix_pl_nsscontext.h" +#include "pkix_pl_httpcertstore.h" +#include "pkix_pl_httpdefaultclient.h" +#include "pkix_pl_infoaccess.h" +#include "pkix_sample_modules.h" + +#define MAX_DIGITS_32 (PKIX_UInt32) 10 + +#define PKIX_PL_NSSCALL(type, func, args) \ + PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \ + (func args) + +#define PKIX_PL_NSSCALLRV(type, lvalue, func, args) \ + PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \ + lvalue = (func args) + +/* see source file for function documentation */ + +PKIX_Error * +pkix_LockObject( + PKIX_PL_Object *object, + void *plContext); + +PKIX_Error * +pkix_UnlockObject( + PKIX_PL_Object *object, + void *plContext); + +PKIX_Boolean +pkix_pl_UInt32_Overflows(char *string); + +PKIX_Error * +pkix_pl_helperBytes2Ascii( + PKIX_UInt32 *tokens, + PKIX_UInt32 numTokens, + char **pAscii, + void *plContext); + +PKIX_Error * +pkix_pl_ipAddrBytes2Ascii( + SECItem *secItem, + char **pAscii, + void *plContext); + +PKIX_Error * +pkix_pl_oidBytes2Ascii( + SECItem *secItem, + char **pAscii, + void *plContext); + +/* --String-Encoding-Conversion-Functions------------------------ */ + +PKIX_Error * +pkix_UTF16_to_EscASCII( + const void *utf16String, + PKIX_UInt32 utf16Length, + PKIX_Boolean debug, + char **pDest, + PKIX_UInt32 *pLength, + void *plContext); + +PKIX_Error * +pkix_EscASCII_to_UTF16( + const char *escAsciiString, + PKIX_UInt32 escAsciiLen, + PKIX_Boolean debug, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext); + +PKIX_Error * +pkix_UTF16_to_UTF8( + const void *utf16String, + PKIX_UInt32 utf16Length, + PKIX_Boolean null_Term, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext); + +PKIX_Error * +pkix_UTF8_to_UTF16( + const void *utf8Source, + PKIX_UInt32 utf8Length, + void **pDest, + PKIX_UInt32 *pLength, + void *plContext); + +#endif /* _PKIX_PL_COMMON_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c new file mode 100644 index 0000000000..2631aed031 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c @@ -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/. */ +/* + * pkix_pl_error.c + * + * PL error functions + * + */ + +#include "pkix_pl_common.h" + +#undef PKIX_ERRORENTRY + +#define PKIX_ERRORENTRY(name,desc,plerr) plerr + +const PKIX_Int32 PKIX_PLErrorIndex[] = +{ +#include "pkix_errorstrings.h" +}; + +int +PKIX_PL_GetPLErrorCode() +{ + return PORT_GetError(); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c new file mode 100644 index 0000000000..260365375e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c @@ -0,0 +1,383 @@ +/* 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_pl_hashtable.c + * + * Hashtable Object Functions + * + */ + +#include "pkix_pl_hashtable.h" + +/* --Private-Structure-------------------------------------------- */ + +struct PKIX_PL_HashTableStruct { + pkix_pl_PrimHashTable *primHash; + PKIX_PL_Mutex *tableLock; + PKIX_UInt32 maxEntriesPerBucket; +}; + +/* --Private-Functions-------------------------------------------- */ + +#define PKIX_MUTEX_UNLOCK(mutex) \ + do { \ + if (mutex && lockedMutex == (PKIX_PL_Mutex *)(mutex)) { \ + pkixTempResult = \ + PKIX_PL_Mutex_Unlock((mutex), plContext); \ + PORT_Assert(pkixTempResult == NULL); \ + if (pkixTempResult) { \ + PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + lockedMutex = NULL; \ + } else { \ + PORT_Assert(lockedMutex == NULL); \ + }\ + } while (0) + + +#define PKIX_MUTEX_LOCK(mutex) \ + do { \ + if (mutex){ \ + PORT_Assert(lockedMutex == NULL); \ + PKIX_CHECK(PKIX_PL_Mutex_Lock((mutex), plContext), \ + PKIX_MUTEXLOCKFAILED); \ + lockedMutex = (mutex); \ + } \ + } while (0) + +/* + * FUNCTION: pkix_pl_HashTable_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_HashTable_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_HashTable *ht = NULL; + pkix_pl_HT_Elem *item = NULL; + PKIX_UInt32 i; + + PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_HASHTABLE_TYPE, plContext), + PKIX_OBJECTNOTHASHTABLE); + + ht = (PKIX_PL_HashTable*) object; + + /* DecRef every object in the primitive hash table */ + for (i = 0; i < ht->primHash->size; i++) { + for (item = ht->primHash->buckets[i]; + item != NULL; + item = item->next) { + PKIX_DECREF(item->key); + PKIX_DECREF(item->value); + } + } + + PKIX_CHECK(pkix_pl_PrimHashTable_Destroy(ht->primHash, plContext), + PKIX_PRIMHASHTABLEDESTROYFAILED); + + PKIX_DECREF(ht->tableLock); + +cleanup: + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_HashTable_RegisterSelf + * DESCRIPTION: + * Registers PKIX_HASHTABLE_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_pl_HashTable_RegisterSelf( + void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_RegisterSelf"); + + entry.description = "HashTable"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_HashTable); + entry.destructor = pkix_pl_HashTable_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_HASHTABLE_TYPE] = entry; + + PKIX_RETURN(HASHTABLE); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_HashTable_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_HashTable_Create( + PKIX_UInt32 numBuckets, + PKIX_UInt32 maxEntriesPerBucket, + PKIX_PL_HashTable **pResult, + void *plContext) +{ + PKIX_PL_HashTable *hashTable = NULL; + + PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Create"); + PKIX_NULLCHECK_ONE(pResult); + + if (numBuckets == 0) { + PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO); + } + + /* Allocate a new hashtable */ + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_HASHTABLE_TYPE, + sizeof (PKIX_PL_HashTable), + (PKIX_PL_Object **)&hashTable, + plContext), + PKIX_COULDNOTCREATEHASHTABLEOBJECT); + + /* Create the underlying primitive hash table type */ + PKIX_CHECK(pkix_pl_PrimHashTable_Create + (numBuckets, &hashTable->primHash, plContext), + PKIX_PRIMHASHTABLECREATEFAILED); + + /* Create a lock for this table */ + PKIX_CHECK(PKIX_PL_Mutex_Create(&hashTable->tableLock, plContext), + PKIX_ERRORCREATINGTABLELOCK); + + hashTable->maxEntriesPerBucket = maxEntriesPerBucket; + + *pResult = hashTable; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(hashTable); + } + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: PKIX_PL_HashTable_Add (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_HashTable_Add( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + PKIX_PL_Object *value, + void *plContext) +{ + PKIX_PL_Mutex *lockedMutex = NULL; + PKIX_PL_Object *deletedKey = NULL; + PKIX_PL_Object *deletedValue = NULL; + PKIX_UInt32 hashCode; + PKIX_PL_EqualsCallback keyComp; + PKIX_UInt32 bucketSize = 0; + + PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Add"); + +#if !defined(PKIX_OBJECT_LEAK_TEST) + PKIX_NULLCHECK_THREE(ht, key, value); +#else + PKIX_NULLCHECK_TWO(key, value); + + if (ht == NULL) { + PKIX_RETURN(HASHTABLE); + } +#endif + /* Insert into primitive hashtable */ + + PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback + (key, &keyComp, plContext), + PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); + + PKIX_MUTEX_LOCK(ht->tableLock); + + PKIX_CHECK(pkix_pl_PrimHashTable_GetBucketSize + (ht->primHash, + hashCode, + &bucketSize, + plContext), + PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED); + + if (ht->maxEntriesPerBucket != 0 && + bucketSize >= ht->maxEntriesPerBucket) { + /* drop the last one in the bucket */ + PKIX_CHECK(pkix_pl_PrimHashTable_RemoveFIFO + (ht->primHash, + hashCode, + (void **) &deletedKey, + (void **) &deletedValue, + plContext), + PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED); + PKIX_DECREF(deletedKey); + PKIX_DECREF(deletedValue); + } + + PKIX_CHECK(pkix_pl_PrimHashTable_Add + (ht->primHash, + (void *)key, + (void *)value, + hashCode, + keyComp, + plContext), + PKIX_PRIMHASHTABLEADDFAILED); + + PKIX_INCREF(key); + PKIX_INCREF(value); + PKIX_MUTEX_UNLOCK(ht->tableLock); + + /* + * we don't call PKIX_PL_InvalidateCache here b/c we have + * not implemented toString or hashcode for this Object + */ + +cleanup: + + PKIX_MUTEX_UNLOCK(ht->tableLock); + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: PKIX_PL_HashTable_Remove (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_HashTable_Remove( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + void *plContext) +{ + PKIX_PL_Mutex *lockedMutex = NULL; + PKIX_PL_Object *origKey = NULL; + PKIX_PL_Object *value = NULL; + PKIX_UInt32 hashCode; + PKIX_PL_EqualsCallback keyComp; + + PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Remove"); + +#if !defined(PKIX_OBJECT_LEAK_TEST) + PKIX_NULLCHECK_TWO(ht, key); +#else + PKIX_NULLCHECK_ONE(key); + + if (ht == NULL) { + PKIX_RETURN(HASHTABLE); + } +#endif + + PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback + (key, &keyComp, plContext), + PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); + + PKIX_MUTEX_LOCK(ht->tableLock); + + /* Remove from primitive hashtable */ + PKIX_CHECK(pkix_pl_PrimHashTable_Remove + (ht->primHash, + (void *)key, + hashCode, + keyComp, + (void **)&origKey, + (void **)&value, + plContext), + PKIX_PRIMHASHTABLEREMOVEFAILED); + + PKIX_MUTEX_UNLOCK(ht->tableLock); + + PKIX_DECREF(origKey); + PKIX_DECREF(value); + + /* + * we don't call PKIX_PL_InvalidateCache here b/c we have + * not implemented toString or hashcode for this Object + */ + +cleanup: + + PKIX_MUTEX_UNLOCK(ht->tableLock); + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: PKIX_PL_HashTable_Lookup (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_HashTable_Lookup( + PKIX_PL_HashTable *ht, + PKIX_PL_Object *key, + PKIX_PL_Object **pResult, + void *plContext) +{ + PKIX_PL_Mutex *lockedMutex = NULL; + PKIX_UInt32 hashCode; + PKIX_PL_EqualsCallback keyComp; + PKIX_PL_Object *result = NULL; + + PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Lookup"); + +#if !defined(PKIX_OBJECT_LEAK_TEST) + PKIX_NULLCHECK_THREE(ht, key, pResult); +#else + PKIX_NULLCHECK_TWO(key, pResult); + + if (ht == NULL) { + PKIX_RETURN(HASHTABLE); + } +#endif + + PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), + PKIX_OBJECTHASHCODEFAILED); + + PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback + (key, &keyComp, plContext), + PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); + + PKIX_MUTEX_LOCK(ht->tableLock); + + /* Lookup in primitive hashtable */ + PKIX_CHECK(pkix_pl_PrimHashTable_Lookup + (ht->primHash, + (void *)key, + hashCode, + keyComp, + (void **)&result, + plContext), + PKIX_PRIMHASHTABLELOOKUPFAILED); + + PKIX_INCREF(result); + PKIX_MUTEX_UNLOCK(ht->tableLock); + + *pResult = result; + +cleanup: + + PKIX_MUTEX_UNLOCK(ht->tableLock); + + PKIX_RETURN(HASHTABLE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h new file mode 100644 index 0000000000..479c623733 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h @@ -0,0 +1,29 @@ +/* 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_pl_hashtable.h + * + * Hashtable Object Definition + * + */ + +#ifndef _PKIX_PL_HASHTABLE_H +#define _PKIX_PL_HASHTABLE_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_HashTable_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_HASHTABLE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c new file mode 100644 index 0000000000..70ed25d729 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c @@ -0,0 +1,279 @@ +/* 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_pl_lifecycle.c + * + * Lifecycle Functions for the PKIX PL library. + * + */ + +#include "pkix_pl_lifecycle.h" + +PKIX_Boolean pkix_pl_initialized = PKIX_FALSE; +pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; +PRLock *classTableLock; +PRLogModuleInfo *pkixLog = NULL; + +/* + * PKIX_ALLOC_ERROR is a special error object hard-coded into the + * pkix_error.o object file. It is thrown if system memory cannot be + * allocated. PKIX_ALLOC_ERROR is immutable. + * IncRef, DecRef, and Settor functions cannot be called. + */ + +/* Keep this structure definition here for its is used only once here */ +struct PKIX_Alloc_Error_ObjectStruct { + PKIX_PL_Object header; + PKIX_Error error; +}; +typedef struct PKIX_Alloc_Error_ObjectStruct PKIX_Alloc_Error_Object; + +static const PKIX_Alloc_Error_Object pkix_Alloc_Error_Data = { + { + PKIX_MAGIC_HEADER, /* PRUint64 magicHeader */ + (PKIX_UInt32)PKIX_ERROR_TYPE, /* PKIX_UInt32 type */ + (PKIX_UInt32)1, /* PKIX_UInt32 references */ + /* Warning! Cannot Ref Count with NULL lock */ + (void *)0, /* PRLock *lock */ + (PKIX_PL_String *)0, /* PKIX_PL_String *stringRep */ + (PKIX_UInt32)0, /* PKIX_UInt32 hashcode */ + (PKIX_Boolean)PKIX_FALSE, /* PKIX_Boolean hashcodeCached */ + }, { + (PKIX_ERRORCODE)0, /* PKIX_ERRORCODE errCode; */ + (PKIX_ERRORCLASS)PKIX_FATAL_ERROR,/* PKIX_ERRORCLASS errClass */ + (PKIX_UInt32)SEC_ERROR_LIBPKIX_INTERNAL, /* default PL Error Code */ + (PKIX_Error *)0, /* PKIX_Error *cause */ + (PKIX_PL_Object *)0, /* PKIX_PL_Object *info */ + } +}; + +PKIX_Error* PKIX_ALLOC_ERROR(void) +{ + return (PKIX_Error *)&pkix_Alloc_Error_Data.error; +} + +#ifdef PKIX_OBJECT_LEAK_TEST +SECStatus +pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable) +{ + int typeCounter = 0; + + for (; typeCounter < PKIX_NUMTYPES; typeCounter++) { + pkix_ClassTable_Entry *entry = &systemClasses[typeCounter]; + + objCountTable[typeCounter] = entry->objCounter; + } + + return SECSuccess; +} +#endif /* PKIX_OBJECT_LEAK_TEST */ + + +PKIX_UInt32 +pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable) +{ + unsigned int typeCounter = 0; + PKIX_UInt32 numObjects = 0; + char classNameBuff[128]; + char *className = NULL; + + for (; typeCounter < PKIX_NUMTYPES; typeCounter++) { + pkix_ClassTable_Entry *entry = &systemClasses[typeCounter]; + PKIX_UInt32 objCountDiff = entry->objCounter; + + if (initObjCountTable) { + PKIX_UInt32 initialCount = initObjCountTable[typeCounter]; + objCountDiff = (entry->objCounter > initialCount) ? + entry->objCounter - initialCount : 0; + } + + numObjects += objCountDiff; + + if (!pkixLog || !objCountDiff) { + continue; + } + className = entry->description; + if (!className) { + className = classNameBuff; + PR_snprintf(className, 128, "Unknown(ref %d)", + entry->objCounter); + } + + PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of " + "size %d bytes, total = %d bytes\n", className, + objCountDiff, entry->typeObjectSize, + objCountDiff * entry->typeObjectSize)); + } + + return numObjects; +} + +/* + * PKIX_PL_Initialize (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Initialize( + PKIX_Boolean platformInitNeeded, + PKIX_Boolean useArenas, + void **pPlContext) +{ + void *plContext = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Initialize"); + + /* + * This function can only be called once. If it has already been + * called, we return a positive status. + */ + if (pkix_pl_initialized) { + PKIX_RETURN(OBJECT); + } + + classTableLock = PR_NewLock(); + if (classTableLock == NULL) { + return PKIX_ALLOC_ERROR(); + } + + if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) { + pkixLog = PR_NewLogModule("pkix"); + } + /* + * Register Object, it is the base object of all other objects. + */ + pkix_pl_Object_RegisterSelf(plContext); + + /* + * Register Error and String, since they will be needed if + * there is a problem in registering any other type. + */ + pkix_Error_RegisterSelf(plContext); + pkix_pl_String_RegisterSelf(plContext); + + + /* + * We register all other system types + * (They don't need to be in order, but it's + * easier to keep track of what types are registered + * if we register them in the same order as their + * numbers, defined in pkixt.h. + */ + pkix_pl_BigInt_RegisterSelf(plContext); /* 1-10 */ + pkix_pl_ByteArray_RegisterSelf(plContext); + pkix_pl_HashTable_RegisterSelf(plContext); + pkix_List_RegisterSelf(plContext); + pkix_Logger_RegisterSelf(plContext); + pkix_pl_Mutex_RegisterSelf(plContext); + pkix_pl_OID_RegisterSelf(plContext); + pkix_pl_RWLock_RegisterSelf(plContext); + + pkix_pl_CertBasicConstraints_RegisterSelf(plContext); /* 11-20 */ + pkix_pl_Cert_RegisterSelf(plContext); + pkix_pl_CRL_RegisterSelf(plContext); + pkix_pl_CRLEntry_RegisterSelf(plContext); + pkix_pl_Date_RegisterSelf(plContext); + pkix_pl_GeneralName_RegisterSelf(plContext); + pkix_pl_CertNameConstraints_RegisterSelf(plContext); + pkix_pl_PublicKey_RegisterSelf(plContext); + pkix_TrustAnchor_RegisterSelf(plContext); + + pkix_pl_X500Name_RegisterSelf(plContext); /* 21-30 */ + pkix_pl_HttpCertStoreContext_RegisterSelf(plContext); + pkix_BuildResult_RegisterSelf(plContext); + pkix_ProcessingParams_RegisterSelf(plContext); + pkix_ValidateParams_RegisterSelf(plContext); + pkix_ValidateResult_RegisterSelf(plContext); + pkix_CertStore_RegisterSelf(plContext); + pkix_CertChainChecker_RegisterSelf(plContext); + pkix_RevocationChecker_RegisterSelf(plContext); + pkix_CertSelector_RegisterSelf(plContext); + + pkix_ComCertSelParams_RegisterSelf(plContext); /* 31-40 */ + pkix_CRLSelector_RegisterSelf(plContext); + pkix_ComCRLSelParams_RegisterSelf(plContext); + pkix_pl_CertPolicyInfo_RegisterSelf(plContext); + pkix_pl_CertPolicyQualifier_RegisterSelf(plContext); + pkix_pl_CertPolicyMap_RegisterSelf(plContext); + pkix_PolicyNode_RegisterSelf(plContext); + pkix_TargetCertCheckerState_RegisterSelf(plContext); + pkix_BasicConstraintsCheckerState_RegisterSelf(plContext); + pkix_PolicyCheckerState_RegisterSelf(plContext); + + pkix_pl_CollectionCertStoreContext_RegisterSelf(plContext); /* 41-50 */ + pkix_CrlChecker_RegisterSelf(plContext); + pkix_ForwardBuilderState_RegisterSelf(plContext); + pkix_SignatureCheckerState_RegisterSelf(plContext); + pkix_NameConstraintsCheckerState_RegisterSelf(plContext); +#ifndef NSS_PKIX_NO_LDAP + pkix_pl_LdapRequest_RegisterSelf(plContext); + pkix_pl_LdapResponse_RegisterSelf(plContext); + pkix_pl_LdapDefaultClient_RegisterSelf(plContext); +#endif + pkix_pl_Socket_RegisterSelf(plContext); + + pkix_ResourceLimits_RegisterSelf(plContext); /* 51-59 */ + pkix_pl_MonitorLock_RegisterSelf(plContext); + pkix_pl_InfoAccess_RegisterSelf(plContext); + pkix_pl_AIAMgr_RegisterSelf(plContext); + pkix_OcspChecker_RegisterSelf(plContext); + pkix_pl_OcspCertID_RegisterSelf(plContext); + pkix_pl_OcspRequest_RegisterSelf(plContext); + pkix_pl_OcspResponse_RegisterSelf(plContext); + pkix_pl_HttpDefaultClient_RegisterSelf(plContext); + pkix_VerifyNode_RegisterSelf(plContext); + pkix_EkuChecker_RegisterSelf(plContext); + pkix_pl_CrlDp_RegisterSelf(plContext); + + if (pPlContext) { + PKIX_CHECK(PKIX_PL_NssContext_Create + (0, useArenas, NULL, &plContext), + PKIX_NSSCONTEXTCREATEFAILED); + + *pPlContext = plContext; + } + + pkix_pl_initialized = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * PKIX_PL_Shutdown (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Shutdown(void *plContext) +{ +#ifdef DEBUG + PKIX_UInt32 numLeakedObjects = 0; +#endif + + PKIX_ENTER(OBJECT, "PKIX_PL_Shutdown"); + + if (!pkix_pl_initialized) { + /* The library was not initilized */ + PKIX_RETURN(OBJECT); + } + + PR_DestroyLock(classTableLock); + + pkix_pl_HttpCertStore_Shutdown(plContext); + +#ifdef DEBUG + numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL); + if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) { + PORT_Assert(numLeakedObjects == 0); + } +#else + pkix_pl_lifecycle_ObjectLeakCheck(NULL); +#endif + + if (plContext != NULL) { + PKIX_PL_NssContext_Destroy(plContext); + } + + pkix_pl_initialized = PKIX_FALSE; + + PKIX_RETURN(OBJECT); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h new file mode 100644 index 0000000000..9660af123d --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h @@ -0,0 +1,91 @@ +/* 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_pl_lifecycle.h + * + * Lifecycle Definitions + * + */ + +#ifndef _PKIX_PL_LIFECYCLE_H +#define _PKIX_PL_LIFECYCLE_H + +#include "pkix_pl_common.h" +#include "pkix_pl_oid.h" +#include "pkix_pl_aiamgr.h" +#include "pkix_pl_bigint.h" +#include "pkix_pl_bytearray.h" +#include "pkix_pl_hashtable.h" +#include "pkix_pl_mutex.h" +#include "pkix_pl_rwlock.h" +#include "pkix_pl_monitorlock.h" +#include "pkix_pl_string.h" +#include "pkix_pl_cert.h" +#include "pkix_pl_x500name.h" +#include "pkix_pl_generalname.h" +#include "pkix_pl_publickey.h" +#include "pkix_pl_date.h" +#include "pkix_pl_basicconstraints.h" +#include "pkix_pl_certpolicyinfo.h" +#include "pkix_pl_certpolicymap.h" +#include "pkix_pl_certpolicyqualifier.h" +#include "pkix_pl_crlentry.h" +#include "pkix_pl_crl.h" +#include "pkix_pl_colcertstore.h" +#ifndef NSS_PKIX_NO_LDAP +#include "pkix_pl_ldapcertstore.h" +#include "pkix_pl_ldapdefaultclient.h" +#include "pkix_pl_ldaprequest.h" +#include "pkix_pl_ldapresponse.h" +#endif /* !NSS_PKIX_NO_LDAP */ +#include "pkix_pl_socket.h" +#include "pkix_pl_infoaccess.h" +#include "pkix_store.h" +#include "pkix_error.h" +#include "pkix_logger.h" +#include "pkix_list.h" +#include "pkix_trustanchor.h" +#include "pkix_procparams.h" +#include "pkix_valparams.h" +#include "pkix_valresult.h" +#include "pkix_verifynode.h" +#include "pkix_resourcelimits.h" +#include "pkix_certchainchecker.h" +#include "pkix_revocationchecker.h" +#include "pkix_certselector.h" +#include "pkix_comcertselparams.h" +#include "pkix_crlselector.h" +#include "pkix_comcrlselparams.h" +#include "pkix_targetcertchecker.h" +#include "pkix_basicconstraintschecker.h" +#include "pkix_policynode.h" +#include "pkix_policychecker.h" +#include "pkix_crlchecker.h" +#include "pkix_signaturechecker.h" +#include "pkix_buildresult.h" +#include "pkix_build.h" +#include "pkix_pl_nameconstraints.h" +#include "pkix_nameconstraintschecker.h" +#include "pkix_ocspchecker.h" +#include "pkix_pl_ocspcertid.h" +#include "pkix_pl_ocsprequest.h" +#include "pkix_pl_ocspresponse.h" +#include "pkix_pl_httpdefaultclient.h" +#include "pkix_pl_httpcertstore.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_InitializeParamsStruct { + PKIX_List *loggers; + PKIX_UInt32 majorVersion; + PKIX_UInt32 minorVersion; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_LIFECYCLE_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c new file mode 100644 index 0000000000..d75c0be26e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c @@ -0,0 +1,168 @@ +/* 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_pl_mem.c + * + * Memory Management Functions + * + */ + +#include "pkix_pl_mem.h" + +/* + * FUNCTION: PKIX_PL_Malloc (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Malloc( + PKIX_UInt32 size, + void **pMemory, + void *plContext) +{ + PKIX_PL_NssContext *nssContext = NULL; + void *result = NULL; + + PKIX_ENTER(MEM, "PKIX_PL_Malloc"); + PKIX_NULLCHECK_ONE(pMemory); + + if (size == 0){ + *pMemory = NULL; + } else { + + nssContext = (PKIX_PL_NssContext *)plContext; + + if (nssContext != NULL && nssContext->arena != NULL) { + PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n"); + *pMemory = PORT_ArenaAlloc(nssContext->arena, size); + } else { + PKIX_MEM_DEBUG("\tCalling PR_Malloc.\n"); + result = (void *) PR_Malloc(size); + + if (result == NULL) { + PKIX_MEM_DEBUG("Fatal Error Occurred: " + "PR_Malloc failed.\n"); + PKIX_ERROR_ALLOC_ERROR(); + } else { + *pMemory = result; + } + } + } + +cleanup: + PKIX_RETURN(MEM); +} + +/* + * FUNCTION: PKIX_PL_Calloc (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Calloc( + PKIX_UInt32 nElem, + PKIX_UInt32 elSize, + void **pMemory, + void *plContext) +{ + PKIX_PL_NssContext *nssContext = NULL; + void *result = NULL; + + PKIX_ENTER(MEM, "PKIX_PL_Calloc"); + PKIX_NULLCHECK_ONE(pMemory); + + if ((nElem == 0) || (elSize == 0)){ + *pMemory = NULL; + } else { + + nssContext = (PKIX_PL_NssContext *)plContext; + + if (nssContext != NULL && nssContext->arena != NULL) { + PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n"); + *pMemory = PORT_ArenaAlloc(nssContext->arena, elSize); + } else { + PKIX_MEM_DEBUG("\tCalling PR_Calloc.\n"); + result = (void *) PR_Calloc(nElem, elSize); + + if (result == NULL) { + PKIX_MEM_DEBUG("Fatal Error Occurred: " + "PR_Calloc failed.\n"); + PKIX_ERROR_ALLOC_ERROR(); + } else { + *pMemory = result; + } + } + } + +cleanup: + + PKIX_RETURN(MEM); +} + +/* + * FUNCTION: PKIX_PL_Realloc (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Realloc( + void *ptr, + PKIX_UInt32 size, + void **pMemory, + void *plContext) +{ + PKIX_PL_NssContext *nssContext = NULL; + void *result = NULL; + + PKIX_ENTER(MEM, "PKIX_PL_Realloc"); + PKIX_NULLCHECK_ONE(pMemory); + + nssContext = (PKIX_PL_NssContext *)plContext; + + if (nssContext != NULL && nssContext->arena != NULL) { + PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n"); + result = PORT_ArenaAlloc(nssContext->arena, size); + + if (result){ + PKIX_MEM_DEBUG("\tCalling PORT_Memcpy.\n"); + PORT_Memcpy(result, ptr, size); + } + *pMemory = result; + } else { + PKIX_MEM_DEBUG("\tCalling PR_Realloc.\n"); + result = (void *) PR_Realloc(ptr, size); + + if (result == NULL) { + if (size == 0){ + *pMemory = NULL; + } else { + PKIX_MEM_DEBUG + ("Fatal Error Occurred: " + "PR_Realloc failed.\n"); + PKIX_ERROR_ALLOC_ERROR(); + } + } else { + *pMemory = result; + } + } + +cleanup: + + PKIX_RETURN(MEM); +} + +/* + * FUNCTION: PKIX_PL_Free (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Free( + void *ptr, + /* ARGSUSED */ void *plContext) +{ + PKIX_PL_NssContext *context = NULL; + + PKIX_ENTER(MEM, "PKIX_PL_Free"); + + context = (PKIX_PL_NssContext *) plContext; + if (context == NULL || context->arena == NULL) { + PKIX_MEM_DEBUG("\tCalling PR_Free.\n"); + (void) PR_Free(ptr); + } + + PKIX_RETURN(MEM); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h new file mode 100644 index 0000000000..eaec6246c9 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h @@ -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/. */ +/* + * pkix_pl_mem.h + * + * Memory Management Definitions + * + */ + +#ifndef _PKIX_PL_MEM_H +#define _PKIX_PL_MEM_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_MEM_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c new file mode 100644 index 0000000000..a5d2fc9621 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c @@ -0,0 +1,136 @@ +/* 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_pl_monitorlock.c + * + * Read/Write Lock Functions + * + */ + +#include "pkix_pl_monitorlock.h" + +/* --Private-Functions-------------------------------------------- */ + +static PKIX_Error * +pkix_pl_MonitorLock_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_MonitorLock* monitorLock = NULL; + + PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_MONITORLOCK_TYPE, plContext), + PKIX_OBJECTNOTMONITORLOCK); + + monitorLock = (PKIX_PL_MonitorLock*) object; + + PKIX_MONITORLOCK_DEBUG("Calling PR_DestroyMonitor)\n"); + PR_DestroyMonitor(monitorLock->lock); + monitorLock->lock = NULL; + +cleanup: + + PKIX_RETURN(MONITORLOCK); +} + +/* + * FUNCTION: pkix_pl_MonitorLock_RegisterSelf + * DESCRIPTION: + * Registers PKIX_MONITORLOCK_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_pl_MonitorLock_RegisterSelf( + void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_RegisterSelf"); + + entry.description = "MonitorLock"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_MonitorLock); + entry.destructor = pkix_pl_MonitorLock_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_MONITORLOCK_TYPE] = entry; + + PKIX_RETURN(MONITORLOCK); +} + +/* --Public-Functions--------------------------------------------- */ + +PKIX_Error * +PKIX_PL_MonitorLock_Create( + PKIX_PL_MonitorLock **pNewLock, + void *plContext) +{ + PKIX_PL_MonitorLock *monitorLock = NULL; + + PKIX_ENTER(MONITORLOCK, "PKIX_PL_MonitorLock_Create"); + PKIX_NULLCHECK_ONE(pNewLock); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_MONITORLOCK_TYPE, + sizeof (PKIX_PL_MonitorLock), + (PKIX_PL_Object **)&monitorLock, + plContext), + PKIX_ERRORALLOCATINGMONITORLOCK); + + PKIX_MONITORLOCK_DEBUG("\tCalling PR_NewMonitor)\n"); + monitorLock->lock = PR_NewMonitor(); + + if (monitorLock->lock == NULL) { + PKIX_DECREF(monitorLock); + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + *pNewLock = monitorLock; + +cleanup: + + PKIX_RETURN(MONITORLOCK); +} + +PKIX_Error * +PKIX_PL_MonitorLock_Enter( + PKIX_PL_MonitorLock *monitorLock, + void *plContext) +{ + PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Enter"); + PKIX_NULLCHECK_ONE(monitorLock); + + PKIX_MONITORLOCK_DEBUG("\tCalling PR_EnterMonitor)\n"); + (void) PR_EnterMonitor(monitorLock->lock); + + PKIX_RETURN_NO_LOGGER(MONITORLOCK); +} + +PKIX_Error * +PKIX_PL_MonitorLock_Exit( + PKIX_PL_MonitorLock *monitorLock, + void *plContext) +{ + PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Exit"); + PKIX_NULLCHECK_ONE(monitorLock); + + PKIX_MONITORLOCK_DEBUG("\tCalling PR_ExitMonitor)\n"); + PR_ExitMonitor(monitorLock->lock); + + PKIX_RETURN_NO_LOGGER(MONITORLOCK); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h new file mode 100644 index 0000000000..76ac539ad8 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.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_pl_monitorlock.h + * + * Read/Write Lock Definition + * + */ + +#ifndef _PKIX_PL_MONITORLOCK_H +#define _PKIX_PL_MONITORLOCK_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_MonitorLockStruct { + PRMonitor* lock; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_MonitorLock_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_MONITORLOCK_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c new file mode 100644 index 0000000000..07d13695b5 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c @@ -0,0 +1,163 @@ +/* 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_pl_mutex.c + * + * Mutual Exclusion (Lock) Object Functions + * + */ + +#include "pkix_pl_mutex.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_Mutex_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_Mutex_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Mutex *mutex = NULL; + + PKIX_ENTER(MUTEX, "pkix_pl_Mutex_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Sanity check: Test that "object" is a mutex */ + PKIX_CHECK(pkix_CheckType(object, PKIX_MUTEX_TYPE, plContext), + PKIX_OBJECTNOTMUTEX); + + mutex = (PKIX_PL_Mutex*) object; + + PKIX_MUTEX_DEBUG("\tCalling PR_DestroyLock).\n"); + PR_DestroyLock(mutex->lock); + mutex->lock = NULL; + +cleanup: + + PKIX_RETURN(MUTEX); +} + +/* + * FUNCTION: pkix_pl_Mutex_RegisterSelf + * DESCRIPTION: + * Registers PKIX_MUTEX_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_pl_Mutex_RegisterSelf( + /* ARGSUSED */ void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(MUTEX, "pkix_pl_Mutex_RegisterSelf"); + + entry.description = "Mutex"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_Mutex); + entry.destructor = pkix_pl_Mutex_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_MUTEX_TYPE] = entry; + + PKIX_RETURN(MUTEX); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_Mutex_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Mutex_Create( + PKIX_PL_Mutex **pNewLock, + void *plContext) +{ + PKIX_PL_Mutex *mutex = NULL; + + PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Create"); + PKIX_NULLCHECK_ONE(pNewLock); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_MUTEX_TYPE, + sizeof (PKIX_PL_Mutex), + (PKIX_PL_Object **)&mutex, + plContext), + PKIX_COULDNOTCREATELOCKOBJECT); + + PKIX_MUTEX_DEBUG("\tCalling PR_NewLock).\n"); + mutex->lock = PR_NewLock(); + + /* If an error occurred in NSPR, report it here */ + if (mutex->lock == NULL) { + PKIX_DECREF(mutex); + PKIX_ERROR_ALLOC_ERROR(); + } + + *pNewLock = mutex; + +cleanup: + + PKIX_RETURN(MUTEX); +} + +/* + * FUNCTION: PKIX_PL_Mutex_Lock (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Mutex_Lock( + PKIX_PL_Mutex *mutex, + void *plContext) +{ + PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Lock"); + PKIX_NULLCHECK_ONE(mutex); + + PKIX_MUTEX_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(mutex->lock); + + PKIX_MUTEX_DEBUG_ARG("(Thread %u just acquired the lock)\n", + (PKIX_UInt32)PR_GetCurrentThread()); + + PKIX_RETURN(MUTEX); +} + +/* + * FUNCTION: PKIX_PL_Mutex_Unlock (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Mutex_Unlock( + PKIX_PL_Mutex *mutex, + void *plContext) +{ + PRStatus result; + + PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Unlock"); + PKIX_NULLCHECK_ONE(mutex); + + PKIX_MUTEX_DEBUG("\tCalling PR_Unlock).\n"); + result = PR_Unlock(mutex->lock); + + PKIX_MUTEX_DEBUG_ARG("(Thread %u just released the lock)\n", + (PKIX_UInt32)PR_GetCurrentThread()); + + if (result == PR_FAILURE) { + PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGMUTEX); + } + +cleanup: + PKIX_RETURN(MUTEX); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h new file mode 100644 index 0000000000..baf16fea92 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.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_pl_mutex.h + * + * Mutual Exclusion (Lock) Object Type Definition + * + */ + +#ifndef _PKIX_PL_MUTEX_H +#define _PKIX_PL_MUTEX_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_MutexStruct { + PRLock* lock; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_Mutex_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_MUTEX_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c new file mode 100644 index 0000000000..7dafa0b204 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c @@ -0,0 +1,1440 @@ +/* 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_pl_object.c + * + * Object Construction, Destruction and Callback Functions + * + */ + +#include "pkix_pl_object.h" + +#ifdef PKIX_USER_OBJECT_TYPE +/* --Class-Table-Initializers------------------------------------ */ + +/* + * Create storage space for 20 Class Table buckets. + * These are only for user-defined types. System types are registered + * separately by PKIX_PL_Initialize. + */ + +static pkix_pl_HT_Elem* +pkix_Raw_ClassTable_Buckets[] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* + * Allocate static memory for a ClassTable. + * XXX This assumes the bucket pointer will fit into a PKIX_UInt32 + */ +static pkix_pl_PrimHashTable pkix_Raw_ClassTable = { + (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */ + 20 /* Number of Buckets */ +}; +static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable; +#endif /* PKIX_USER_OBJECT_TYPE */ + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_Object_GetHeader + * DESCRIPTION: + * + * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and + * stores the value at "pObjectHeader". + * + * PARAMETERS: + * "object" + * Address of Object to shift. Must be non-NULL. + * "pObjectHeader" + * 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_pl_Object_GetHeader( + PKIX_PL_Object *object, + PKIX_PL_Object **pObjectHeader, + void *plContext) +{ + PKIX_PL_Object *header = NULL; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader"); + PKIX_NULLCHECK_TWO(object, pObjectHeader); + + PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); + + /* The header is sizeof(PKIX_PL_Object) before the object pointer */ + header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object)); + + objType = header->type; + + if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + + PKIX_CHECK(pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext), + PKIX_ERRORGETTINGCLASSTABLEENTRY); + + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + if (ctEntry == NULL) { + PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE); + } +#else + PORT_Assert(objType < PKIX_NUMTYPES); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } + +#ifdef PKIX_OBJECT_LEAK_TEST + PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER); +#endif /* PKIX_OBJECT_LEAK_TEST */ + + if ((header == NULL)|| + (header->magicHeader != PKIX_MAGIC_HEADER)) { + PKIX_ERROR_ALLOC_ERROR(); + } + + *pObjectHeader = header; + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_Destroy_Object + * DESCRIPTION: + * + * Destroys and deallocates Object pointed to by "object". The caller is + * assumed to hold the Object's lock, which is acquired in + * PKIX_PL_Object_DecRef(). + * + * PARAMETERS: + * "object" + * Address of Object to destroy. 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_pl_Object_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + + PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy"); + PKIX_NULLCHECK_ONE(object); + +#ifdef PKIX_OBJECT_LEAK_TEST + PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); +#else + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); +#endif /* PKIX_OBJECT_LEAK_TEST */ + + /* Attempt to delete an object still being used */ + if (objectHeader->references != 0) { + PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED); + } + + PKIX_DECREF(objectHeader->stringRep); + + /* Destroy this object's lock */ + PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n"); + PR_DestroyLock(objectHeader->lock); + objectHeader->lock = NULL; + object = NULL; + + objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED; + +#ifdef PKIX_OBJECT_LEAK_TEST + memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize); +#endif + + PKIX_FREE(objectHeader); + +cleanup: +#ifdef PKIX_OBJECT_LEAK_TEST +fatal: +#endif + + PKIX_RETURN(OBJECT); +} + +/* --Default-Callbacks-------------------------------------------- */ + +/* + * FUNCTION: pkix_pl_Object_Equals_Default + * DESCRIPTION: + * + * Default Object_Equals callback: Compares the address of the Object pointed + * to by "firstObject" with the address of the Object pointed to by + * "secondObject" and stores the Boolean result at "pResult". + * + * PARAMETERS: + * "firstObject" + * Address of first Object to compare. Must be non-NULL. + * "secondObject" + * Address of second Object to compare. Must be non-NULL. + * "pResult" + * Address where Boolean 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_pl_Object_Equals_Default( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* Just compare pointer values */ + *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE; + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_pl_Object_ToString_Default + * DESCRIPTION: + * + * Default Object_ToString callback: Creates a string consisting of the + * typename and address of the Object pointed to by "object" and stores + * the result at "pString". The format for the string is + * "TypeName@Address: <address>", where the default typename is "Object". + * + * PARAMETERS: + * "object" + * Address of Object to convert to a string. Must be non-NULL. + * "pString" + * 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 Object 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_pl_Object_ToString_Default( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *descString = NULL; + char *format = "%s@Address: %x"; + char *description = NULL; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext), + PKIX_OBJECTGETTYPEFAILED); + + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if (ctEntry == NULL){ + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY); + } else { + description = ctEntry->description; + if (description == NULL) { + description = "User Type Object"; + } + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + description = systemClasses[objType].description; + } + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)format, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)description, + 0, + &descString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (pString, + plContext, + formatString, + descString, + object), + PKIX_SPRINTFFAILED); + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(descString); + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_pl_Object_Hashcode_Default + * DESCRIPTION: + * + * Default Object_Hashcode callback. Creates the a hashcode value using the + * address of the Object pointed to by "object" and stores the result at + * "pValue". + * + * XXX This isn't great since addresses are not uniformly distributed. + * + * PARAMETERS: + * "object" + * Address of Object to compute hashcode for. Must be non-NULL. + * "pValue" + * Address where PKIX_UInt32 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_pl_Object_Hashcode_Default( + PKIX_PL_Object *object, + PKIX_UInt32 *pValue, + void *plContext) +{ + PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default"); + PKIX_NULLCHECK_TWO(object, pValue); + + *pValue = (PKIX_UInt32)((char *)object - (char *)NULL); + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback + * DESCRIPTION: + * + * Retrieves Equals callback function of Object pointed to by "object and + * stores it at "pEqualsCallback". If the object's type is one of the system + * types, its callback function is retrieved from the systemClasses array; + * otherwise, its callback function is retrieve from the classTable hash + * table where user-defined types are stored. + * + * PARAMETERS: + * "object" + * Address of Object whose equals callback is desired. Must be non-NULL. + * "pEqualsCallback" + * Address where EqualsCallback function 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 Object 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_pl_Object_RetrieveEqualsCallback( + PKIX_PL_Object *object, + PKIX_PL_EqualsCallback *pEqualsCallback, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + PKIX_PL_EqualsCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback"); + PKIX_NULLCHECK_TWO(object, pEqualsCallback); + + PKIX_CHECK(pkix_pl_Object_GetHeader + (object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + objType = objectHeader->type; + + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { + PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK); + } else { + *pEqualsCallback = ctEntry->equalsFunction; + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + entry = systemClasses[objType]; + func = entry.equalsFunction; + if (func == NULL){ + func = pkix_pl_Object_Equals_Default; + } + *pEqualsCallback = func; + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_pl_Object_RegisterSelf + * DESCRIPTION: + * Registers PKIX_OBJECT_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_PL_Object should have all function pointes to be to NULL: they + * work as proxy function to a real objects. + * + */ +PKIX_Error * +pkix_pl_Object_RegisterSelf(void *plContext) +{ + pkix_ClassTable_Entry entry; + + PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf"); + + entry.description = "Object"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_Object); + entry.destructor = NULL; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_OBJECT_TYPE] = entry; + + PKIX_RETURN(ERROR); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Alloc( + PKIX_TYPENUM objType, + PKIX_UInt32 size, + PKIX_PL_Object **pObject, + void *plContext) +{ + PKIX_PL_Object *object = NULL; + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); + PKIX_NULLCHECK_ONE(pObject); + + /* + * We need to ensure that user-defined types have been registered. + * All system types have already been registered by PKIX_PL_Initialize. + */ + + if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */ +#ifdef PKIX_USER_OBJECT_TYPE + PKIX_Boolean typeRegistered; + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); + } + + typeRegistered = (ctEntry != NULL); + + if (!typeRegistered) { + PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + ctEntry = &systemClasses[objType]; + } + + PORT_Assert(size == ctEntry->typeObjectSize); + + /* Allocate space for the object header and the requested size */ +#ifdef PKIX_OBJECT_LEAK_TEST + PKIX_CHECK(PKIX_PL_Calloc + (1, + ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, + (void **)&object, + plContext), + PKIX_MALLOCFAILED); +#else + PKIX_CHECK(PKIX_PL_Malloc + (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, + (void **)&object, + plContext), + PKIX_MALLOCFAILED); +#endif /* PKIX_OBJECT_LEAK_TEST */ + + /* Initialize all object fields */ + object->magicHeader = PKIX_MAGIC_HEADER; + object->type = objType; + object->references = 1; /* Default to a single reference */ + object->stringRep = NULL; + object->hashcode = 0; + object->hashcodeCached = 0; + + /* Cannot use PKIX_PL_Mutex because it depends on Object */ + /* Using NSPR Locks instead */ + PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); + object->lock = PR_NewLock(); + if (object->lock == NULL) { + PKIX_ERROR_ALLOC_ERROR(); + } + + PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); + + + /* Return a pointer to the user data. Need to offset by object size */ + *pObject = object + 1; + object = NULL; + + /* Atomically increment object counter */ + PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter); + +cleanup: + + PKIX_FREE(object); + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_IsTypeRegistered( + PKIX_UInt32 objType, + PKIX_Boolean *pBool, + void *plContext) +{ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; +#endif + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered"); + PKIX_NULLCHECK_ONE(pBool); + + /* first, we handle the system types */ + if (objType < PKIX_NUMTYPES) { + *pBool = PKIX_TRUE; + goto cleanup; + } + +#ifndef PKIX_USER_OBJECT_TYPE + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; +#else + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); + } + + *pBool = (ctEntry != NULL); +#endif /* PKIX_USER_OBJECT_TYPE */ + +cleanup: + + PKIX_RETURN(OBJECT); +} + +#ifdef PKIX_USER_OBJECT_TYPE +/* + * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_RegisterType( + PKIX_UInt32 objType, + char *description, + PKIX_PL_DestructorCallback destructor, + PKIX_PL_EqualsCallback equalsFunction, + PKIX_PL_HashcodeCallback hashcodeFunction, + PKIX_PL_ToStringCallback toStringFunction, + PKIX_PL_ComparatorCallback comparator, + PKIX_PL_DuplicateCallback duplicateFunction, + void *plContext) +{ + pkix_ClassTable_Entry *ctEntry = NULL; + pkix_pl_Integer *key = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType"); + + /* + * System types are registered on startup by PKIX_PL_Initialize. + * These can not be overwritten. + */ + + if (objType < PKIX_NUMTYPES) { /* if this is a system type */ + PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE); + } + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + PKIX_CHECK(pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext), + PKIX_PRIMHASHTABLELOOKUPFAILED); + + /* If the type is already registered, throw an error */ + if (ctEntry) { + PKIX_ERROR(PKIX_TYPEALREADYREGISTERED); + } + + PKIX_CHECK(PKIX_PL_Malloc + (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)), + (void **)&ctEntry, + plContext), + PKIX_MALLOCFAILED); + + /* Set Default Values if none specified */ + + if (description == NULL){ + description = "Object"; + } + + if (equalsFunction == NULL) { + equalsFunction = pkix_pl_Object_Equals_Default; + } + + if (toStringFunction == NULL) { + toStringFunction = pkix_pl_Object_ToString_Default; + } + + if (hashcodeFunction == NULL) { + hashcodeFunction = pkix_pl_Object_Hashcode_Default; + } + + ctEntry->destructor = destructor; + ctEntry->equalsFunction = equalsFunction; + ctEntry->toStringFunction = toStringFunction; + ctEntry->hashcodeFunction = hashcodeFunction; + ctEntry->comparator = comparator; + ctEntry->duplicateFunction = duplicateFunction; + ctEntry->description = description; + + PKIX_CHECK(PKIX_PL_Malloc + (((PKIX_UInt32)sizeof (pkix_pl_Integer)), + (void **)&key, + plContext), + PKIX_COULDNOTMALLOCNEWKEY); + + key->ht_int = objType; + + PKIX_CHECK(pkix_pl_PrimHashTable_Add + (classTable, + (void *)key, + (void *)ctEntry, + objType, + NULL, + plContext), + PKIX_PRIMHASHTABLEADDFAILED); + +cleanup: + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + PKIX_RETURN(OBJECT); +} +#endif /* PKIX_USER_OBJECT_TYPE */ + +/* + * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_IncRef( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + PKIX_PL_NssContext *context = NULL; + PKIX_Int32 refCount = 0; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef"); + PKIX_NULLCHECK_ONE(object); + + if (plContext){ + /* + * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't + * have a header therefore we cannot verify its type before + * casting. + */ + context = (PKIX_PL_NssContext *) plContext; + if (context->arena != NULL) { + goto cleanup; + } + } + + if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { + goto cleanup; + } + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + /* This object should never have zero references */ + refCount = PR_ATOMIC_INCREMENT(&objectHeader->references); + + if (refCount <= 1) { + PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES); + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_DecRef( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Int32 refCount = 0; + PKIX_PL_Object *objectHeader = NULL; + PKIX_PL_NssContext *context = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); + PKIX_NULLCHECK_ONE(object); + + if (plContext){ + /* + * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't + * have a header therefore we cannot verify its type before + * casting. + */ + context = (PKIX_PL_NssContext *) plContext; + if (context->arena != NULL) { + goto cleanup; + } + } + + if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { + goto cleanup; + } + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); + + if (refCount == 0) { + PKIX_PL_DestructorCallback destructor = NULL; + pkix_ClassTable_Entry *ctEntry = NULL; + PKIX_UInt32 objType = objectHeader->type; + + /* first, special handling for system types */ + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG + ("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR_FATAL + (PKIX_ERRORINGETTINGDESTRUCTOR); + } + + if (ctEntry != NULL){ + destructor = ctEntry->destructor; + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + ctEntry = &systemClasses[objType]; + destructor = ctEntry->destructor; + } + + if (destructor != NULL){ + /* Call destructor on user data if necessary */ + pkixErrorResult = destructor(object, plContext); + if (pkixErrorResult) { + pkixErrorClass = PKIX_FATAL_ERROR; + PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); + pkixErrorResult = NULL; + } + } + + /* Atomically decrement object counter */ + PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter); + + /* pkix_pl_Object_Destroy assumes the lock is held */ + /* It will call unlock and destroy the object */ + pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); + goto cleanup; + } + + if (refCount < 0) { + PKIX_ERROR_ALLOC_ERROR(); + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + + + +/* + * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_PL_Object *firstObjectHeader = NULL; + PKIX_PL_Object *secondObjectHeader = NULL; + PKIX_PL_EqualsCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + PKIX_CHECK(pkix_pl_Object_GetHeader + (firstObject, &firstObjectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + PKIX_CHECK(pkix_pl_Object_GetHeader + (secondObject, &secondObjectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + /* if hashcodes are cached but not equal, objects can't be equal */ + if (firstObjectHeader->hashcodeCached && + secondObjectHeader->hashcodeCached){ + if (firstObjectHeader->hashcode != + secondObjectHeader->hashcode){ + *pResult = PKIX_FALSE; + goto cleanup; + } + } + + objType = firstObjectHeader->type; + + if (objType >= PKIX_NUMTYPES) { +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&firstObjectHeader->type, + firstObjectHeader->type, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); + } else { + func = ctEntry->equalsFunction; + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + entry = systemClasses[objType]; + func = entry.equalsFunction; + if (func == NULL){ + func = pkix_pl_Object_Equals_Default; + } + } + + PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), + PKIX_OBJECTSPECIFICFUNCTIONFAILED); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Duplicate( + PKIX_PL_Object *firstObject, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_PL_Object *firstObjectHeader = NULL; + PKIX_PL_DuplicateCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate"); + PKIX_NULLCHECK_TWO(firstObject, pNewObject); + + PKIX_CHECK(pkix_pl_Object_GetHeader + (firstObject, &firstObjectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + objType = firstObjectHeader->type; + + if (objType >= PKIX_NUMTYPES) { +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) { + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); + } else { + func = ctEntry->duplicateFunction; + } +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + entry = systemClasses[objType]; + func = entry.duplicateFunction; + if (!func){ + PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION); + } + } + + PKIX_CHECK(func(firstObject, pNewObject, plContext), + PKIX_OBJECTSPECIFICFUNCTIONFAILED); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pValue, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + PKIX_PL_HashcodeCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_UInt32 objectHash; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode"); + PKIX_NULLCHECK_TWO(object, pValue); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + /* if we don't have a cached copy from before, we create one */ + if (!objectHeader->hashcodeCached){ + + PKIX_UInt32 objType = objectHeader->type; + + /* first, special handling for system types */ + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + + if (pkixErrorResult){ + PKIX_ERROR_FATAL + (PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || + (ctEntry->hashcodeFunction == NULL)) { + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); + } + + func = ctEntry->hashcodeFunction; +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + entry = systemClasses[objType]; + func = entry.hashcodeFunction; + if (func == NULL){ + func = pkix_pl_Object_Hashcode_Default; + } + } + + PKIX_CHECK(func(object, &objectHash, plContext), + PKIX_OBJECTSPECIFICFUNCTIONFAILED); + + if (!objectHeader->hashcodeCached){ + + PKIX_CHECK(pkix_LockObject(object, plContext), + PKIX_ERRORLOCKINGOBJECT); + + if (!objectHeader->hashcodeCached){ + /* save cached copy in case we need it again */ + objectHeader->hashcode = objectHash; + objectHeader->hashcodeCached = PKIX_TRUE; + } + + PKIX_CHECK(pkix_UnlockObject(object, plContext), + PKIX_ERRORUNLOCKINGOBJECT); + } + } + + *pValue = objectHeader->hashcode; + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + PKIX_PL_ToStringCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_PL_String *objectString = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + /* if we don't have a cached copy from before, we create one */ + if (!objectHeader->stringRep){ + + PKIX_UInt32 objType = objectHeader->type; + + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR_FATAL + (PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || + (ctEntry->toStringFunction == NULL)) { + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); + } + + func = ctEntry->toStringFunction; +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + entry = systemClasses[objType]; + func = entry.toStringFunction; + if (func == NULL){ + func = pkix_pl_Object_ToString_Default; + } + } + + PKIX_CHECK(func(object, &objectString, plContext), + PKIX_OBJECTSPECIFICFUNCTIONFAILED); + + if (!objectHeader->stringRep){ + + PKIX_CHECK(pkix_LockObject(object, plContext), + PKIX_ERRORLOCKINGOBJECT); + + if (!objectHeader->stringRep){ + /* save a cached copy */ + objectHeader->stringRep = objectString; + objectString = NULL; + } + + PKIX_CHECK(pkix_UnlockObject(object, plContext), + PKIX_ERRORUNLOCKINGOBJECT); + } + } + + + *pString = objectHeader->stringRep; + objectHeader->stringRep = NULL; + +cleanup: + if (objectHeader) { + PKIX_DECREF(objectHeader->stringRep); + } + PKIX_DECREF(objectString); + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_InvalidateCache( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache"); + PKIX_NULLCHECK_ONE(object); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + PKIX_CHECK(pkix_LockObject(object, plContext), + PKIX_ERRORLOCKINGOBJECT); + + /* invalidate hashcode */ + objectHeader->hashcode = 0; + objectHeader->hashcodeCached = PKIX_FALSE; + + PKIX_DECREF(objectHeader->stringRep); + + PKIX_CHECK(pkix_UnlockObject(object, plContext), + PKIX_ERRORUNLOCKINGOBJECT); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Compare( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_PL_Object *firstObjectHeader = NULL; + PKIX_PL_Object *secondObjectHeader = NULL; + PKIX_PL_ComparatorCallback func = NULL; + pkix_ClassTable_Entry entry; + PKIX_UInt32 objType; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader + (firstObject, &firstObjectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader + (secondObject, &secondObjectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + objType = firstObjectHeader->type; + + if (objType >= PKIX_NUMTYPES){ +#ifdef PKIX_USER_OBJECT_TYPE + pkix_ClassTable_Entry *ctEntry = NULL; + + PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); + PR_Lock(classTableLock); + pkixErrorResult = pkix_pl_PrimHashTable_Lookup + (classTable, + (void *)&objType, + objType, + NULL, + (void **)&ctEntry, + plContext); + PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); + PR_Unlock(classTableLock); + if (pkixErrorResult){ + PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); + } + + if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) { + PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR); + } + + func = ctEntry->comparator; +#else + PORT_Assert (0); + pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; + pkixErrorClass = PKIX_FATAL_ERROR; + goto cleanup; +#endif /* PKIX_USER_OBJECT_TYPE */ + } else { + /* special handling for system types */ + entry = systemClasses[objType]; + func = entry.comparator; + if (!func){ + PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR); + } + } + + PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), + PKIX_OBJECTSPECIFICFUNCTIONFAILED); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Lock( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_LockObject(object, plContext), + PKIX_LOCKOBJECTFAILED); + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_Unlock( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_UnlockObject(object, plContext), + PKIX_UNLOCKOBJECTFAILED); + +cleanup: + + PKIX_RETURN(OBJECT); +} + + +/* + * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Object_GetType( + PKIX_PL_Object *object, + PKIX_UInt32 *pType, + void *plContext) +{ + PKIX_PL_Object *objectHeader = NULL; + + PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType"); + PKIX_NULLCHECK_TWO(object, pType); + + /* Shift pointer from user data to object header */ + PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), + PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); + + *pType = objectHeader->type; + +cleanup: + + PKIX_RETURN(OBJECT); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h new file mode 100644 index 0000000000..0133c43eeb --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h @@ -0,0 +1,76 @@ +/* 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_pl_object.h + * + * Object Construction, Destruction and Callback Definitions + * + */ + +#ifndef _PKIX_PL_OBJECT_H +#define _PKIX_PL_OBJECT_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Object Implementation Notes: + * + * Allocating a new object creates an object header and a block of + * uninitialized user data. A pointer to this uninitialized data is + * returned to the user. The structure looks as follows: + * + * +--------------------+ + * | MAGIC HEADER | + * | (object header) | + * +--------------------+ + * | user data | -- pointer returned from PKIX_PL_Object_Alloc + * +--------------------+ + * + * Object operations receive a pointer to raw user data as an argument. + * The macro HEADER(object) returns a pointer to the object header. + * An assertion then verifies that the first field is the MAGIC_HEADER. + */ + +/* PKIX_PL_Object Structure Definition */ +struct PKIX_PL_ObjectStruct { + PRUint64 magicHeader; + PKIX_UInt32 type; + PKIX_Int32 references; + PRLock *lock; + PKIX_PL_String *stringRep; + PKIX_UInt32 hashcode; + PKIX_Boolean hashcodeCached; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_Object_RetrieveEqualsCallback( + PKIX_PL_Object *object, + PKIX_PL_EqualsCallback *equalsCallback, + void *plContext); + +extern PKIX_Boolean initializing; +extern PKIX_Boolean initialized; + +#ifdef PKIX_USER_OBJECT_TYPE + +extern PRLock *classTableLock; + +#endif + +extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + +PKIX_Error * +pkix_pl_Object_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_OBJECT_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c new file mode 100644 index 0000000000..a6e0503850 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c @@ -0,0 +1,316 @@ +/* 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_pl_oid.c + * + * OID Object Functions + * + */ + +#include "pkix_pl_oid.h" + +/* --Private-OID-Functions---------------------------------------- */ + + /* + * FUNCTION: pkix_pl_OID_Comparator + * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OID_Comparator( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Int32 *pRes, + void *plContext) +{ + PKIX_PL_OID *firstOID = NULL; + PKIX_PL_OID *secondOID = NULL; + + PKIX_ENTER(OID, "pkix_pl_OID_Comparator"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pRes); + + PKIX_CHECK(pkix_CheckTypes + (firstObject, secondObject, PKIX_OID_TYPE, plContext), + PKIX_ARGUMENTSNOTOIDS); + + firstOID = (PKIX_PL_OID*)firstObject; + secondOID = (PKIX_PL_OID*)secondObject; + + *pRes = (PKIX_Int32)SECITEM_CompareItem(&firstOID->derOid, + &secondOID->derOid); +cleanup: + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OID_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_OID *oid = NULL; + + PKIX_ENTER(OID, "pkix_pl_OID_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), + PKIX_OBJECTNOTANOID); + oid = (PKIX_PL_OID*)object; + SECITEM_FreeItem(&oid->derOid, PR_FALSE); + +cleanup: + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OID_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_OID *oid = NULL; + + PKIX_ENTER(OID, "pkix_pl_OID_HashCode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), + PKIX_OBJECTNOTANOID); + + oid = (PKIX_PL_OID *)object; + + PKIX_CHECK(pkix_hash + ((unsigned char *)oid->derOid.data, + oid->derOid.len * sizeof (char), + pHashcode, + plContext), + PKIX_HASHFAILED); +cleanup: + + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_OID_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Int32 cmpResult; + + PKIX_ENTER(OID, "pkix_pl_OID_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + PKIX_CHECK(pkix_pl_OID_Comparator + (first, second, &cmpResult, plContext), + PKIX_OIDCOMPARATORFAILED); + + *pResult = (cmpResult == 0); +cleanup: + + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + * Use this function only for printing OIDs and not to make any + * critical security decision. + */ +static PKIX_Error * +pkix_pl_OID_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_OID *oid = NULL; + char *oidString = NULL; + + PKIX_ENTER(OID, "pkix_pl_OID_toString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext), + PKIX_OBJECTNOTANOID); + oid = (PKIX_PL_OID*)object; + oidString = CERT_GetOidString(&oid->derOid); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, oidString , 0, pString, plContext), + PKIX_STRINGCREATEFAILED); +cleanup: + PR_smprintf_free(oidString); + + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_RegisterSelf + * DESCRIPTION: + * Registers PKIX_OID_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_pl_OID_RegisterSelf( + void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OID_TYPE]; + + PKIX_ENTER(OID, "pkix_pl_OID_RegisterSelf"); + + entry->description = "OID"; + entry->typeObjectSize = sizeof(PKIX_PL_OID); + entry->destructor = pkix_pl_OID_Destroy; + entry->equalsFunction = pkix_pl_OID_Equals; + entry->hashcodeFunction = pkix_pl_OID_Hashcode; + entry->toStringFunction = pkix_pl_OID_ToString; + entry->comparator = pkix_pl_OID_Comparator; + entry->duplicateFunction = pkix_duplicateImmutable; + + PKIX_RETURN(OID); +} + +/* + * FUNCTION: pkix_pl_OID_GetCriticalExtensionOIDs + * DESCRIPTION: + * + * Converts the extensions in "extensions" array that are critical to + * PKIX_PL_OID and returns the result as a PKIX_List in "pPidList". + * If there is no critical extension, an empty list is returned. + * + * PARAMETERS + * "extension" + * an array of extension pointers. May be NULL. + * "pOidsList" + * Address where the list of OIDs is returned. Must be non-NULL. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CRL 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_pl_OID_GetCriticalExtensionOIDs( + CERTCertExtension **extensions, + PKIX_List **pOidsList, + void *plContext) +{ + PKIX_List *oidsList = NULL; + PKIX_PL_OID *pkixOID = NULL; + + PKIX_ENTER(OID, "pkix_pl_OID_GetCriticalExtensionOIDs"); + PKIX_NULLCHECK_ONE(pOidsList); + + PKIX_CHECK(PKIX_List_Create(&oidsList, plContext), + PKIX_LISTCREATEFAILED); + + if (extensions) { + while (*extensions) { + CERTCertExtension *extension = NULL; + SECItem *critical = NULL; + SECItem *oid = NULL; + + extension = *extensions++; + /* extension is critical ? */ + critical = &extension->critical; + if (critical->len == 0 || critical->data[0] == 0) { + continue; + } + oid = &extension->id; + PKIX_CHECK( + PKIX_PL_OID_CreateBySECItem(oid, &pkixOID, plContext), + PKIX_OIDCREATEFAILED); + PKIX_CHECK( + PKIX_List_AppendItem(oidsList, (PKIX_PL_Object *)pkixOID, + plContext), + PKIX_LISTAPPENDITEMFAILED); + PKIX_DECREF(pkixOID); + } + } + + *pOidsList = oidsList; + oidsList = NULL; + +cleanup: + PKIX_DECREF(oidsList); + PKIX_DECREF(pkixOID); + PKIX_RETURN(OID); +} + +/* --Public-Functions------------------------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_OID_CreateBySECItem (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_OID_CreateBySECItem( + SECItem *derOid, + PKIX_PL_OID **pOID, + void *plContext) +{ + PKIX_PL_OID *oid = NULL; + SECStatus rv; + + PKIX_ENTER(OID, "PKIX_PL_OID_CreateBySECItem"); + PKIX_NULLCHECK_TWO(pOID, derOid); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_OID_TYPE, + sizeof (PKIX_PL_OID), + (PKIX_PL_Object **)&oid, + plContext), + PKIX_COULDNOTCREATEOBJECT); + rv = SECITEM_CopyItem(NULL, &oid->derOid, derOid); + if (rv != SECSuccess) { + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + *pOID = oid; + oid = NULL; + +cleanup: + PKIX_DECREF(oid); + + PKIX_RETURN(OID); +} + +/* + * FUNCTION: PKIX_PL_OID_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_OID_Create( + SECOidTag idtag, + PKIX_PL_OID **pOID, + void *plContext) +{ + SECOidData *oidData = NULL; + + PKIX_ENTER(OID, "PKIX_PL_OID_Create"); + PKIX_NULLCHECK_ONE(pOID); + + oidData = SECOID_FindOIDByTag((SECOidTag)idtag); + if (!oidData) { + PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); + } + + pkixErrorResult = + PKIX_PL_OID_CreateBySECItem(&oidData->oid, pOID, plContext); +cleanup: + PKIX_RETURN(OID); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h new file mode 100644 index 0000000000..0229194d84 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h @@ -0,0 +1,39 @@ +/* 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_pl_oid.h + * + * OID Object Definitions + * + */ + +#ifndef _PKIX_PL_OID_H +#define _PKIX_PL_OID_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_OIDStruct { + SECItem derOid; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_OID_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_pl_OID_GetCriticalExtensionOIDs( + CERTCertExtension **extensions, + PKIX_List **pOidsList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_OID_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c new file mode 100644 index 0000000000..c920533d37 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c @@ -0,0 +1,584 @@ +/* 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_pl_primhash.c + * + * Primitive (non-object) Hashtable Functions + * + */ + +#include "pkix_pl_primhash.h" + +/* --Private-Functions---------------------------------------- */ + +/* + * FUNCTION: pkix_pl_KeyComparator_Default + * DESCRIPTION: + * + * Compares the integer pointed to by "firstKey" with the integer pointed to + * by "secondKey" for equality and stores the Boolean result at "pResult". + * This default key comparator assumes each key is a PKIX_UInt32, and it + * simply tests them for equality. + * + * PARAMETERS: + * "firstKey" + * Address of the first integer key to compare. Must be non-NULL. + * The EqualsCallback for this Object will be called. + * "secondKey" + * Address of the second integer key to compare. Must be non-NULL. + * "pResult" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_pl_KeyComparator_Default( + PKIX_UInt32 *firstKey, + PKIX_UInt32 *secondKey, + PKIX_Boolean *pResult, + void *plContext) +{ + /* Assume both keys are pointers to PKIX_UInt32 */ + PKIX_UInt32 firstInt, secondInt; + + PKIX_ENTER(HASHTABLE, "pkix_pl_KeyComparator_Default"); + PKIX_NULLCHECK_THREE(firstKey, secondKey, pResult); + + firstInt = *firstKey; + secondInt = *secondKey; + + *pResult = (firstInt == secondInt)?PKIX_TRUE:PKIX_FALSE; + + PKIX_RETURN(HASHTABLE); +} + + +/* + * FUNCTION: pkix_pl_PrimHashTable_Create + * DESCRIPTION: + * + * Creates a new PrimHashtable object with a number of buckets equal to + * "numBuckets" and stores the result at "pResult". + * + * PARAMETERS: + * "numBuckets" + * The number of hash table buckets. Must be non-zero. + * "pResult" + * Address where PrimHashTable 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_pl_PrimHashTable_Create( + PKIX_UInt32 numBuckets, + pkix_pl_PrimHashTable **pResult, + void *plContext) +{ + pkix_pl_PrimHashTable *primHashTable = NULL; + PKIX_UInt32 i; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Create"); + PKIX_NULLCHECK_ONE(pResult); + + if (numBuckets == 0) { + PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO); + } + + /* Allocate a new hashtable */ + PKIX_CHECK(PKIX_PL_Malloc + (sizeof (pkix_pl_PrimHashTable), + (void **)&primHashTable, + plContext), + PKIX_MALLOCFAILED); + + primHashTable->size = numBuckets; + + /* Allocate space for the buckets */ + PKIX_CHECK(PKIX_PL_Malloc + (numBuckets * sizeof (pkix_pl_HT_Elem*), + (void **)&primHashTable->buckets, + plContext), + PKIX_MALLOCFAILED); + + for (i = 0; i < numBuckets; i++) { + primHashTable->buckets[i] = NULL; + } + + *pResult = primHashTable; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_FREE(primHashTable); + } + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_PrimHashTable_Add + * DESCRIPTION: + * + * Adds the value pointed to by "value" to the PrimHashTable pointed to by + * "ht" using the key pointed to by "key" and the hashCode value equal to + * "hashCode", using the function pointed to by "keyComp" to compare keys. + * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value + * already exists in the hashtable, this function returns a non-fatal error. + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to insert into. Must be non-NULL. + * "key" + * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object. + * Must be non-NULL. + * "value" + * Address of Object to be added to PrimHashtable. Must be non-NULL. + * "hashCode" + * Hashcode value of the key. + * "keyComp" + * Address of function used to determine if two keys are equal. + * If NULL, pkix_pl_KeyComparator_Default is used. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a HashTable 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_pl_PrimHashTable_Add( + pkix_pl_PrimHashTable *ht, + void *key, + void *value, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void *plContext) +{ + pkix_pl_HT_Elem **elemPtr = NULL; + pkix_pl_HT_Elem *element = NULL; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Add"); + PKIX_NULLCHECK_THREE(ht, key, value); + + for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr; + element != NULL; elemPtr = &(element->next), element = *elemPtr) { + + if (element->hashCode != hashCode){ + /* no possibility of a match */ + continue; + } + + if (keyComp == NULL){ + PKIX_CHECK(pkix_pl_KeyComparator_Default + ((PKIX_UInt32 *)key, + (PKIX_UInt32 *)(element->key), + &compResult, + plContext), + PKIX_COULDNOTTESTWHETHERKEYSEQUAL); + } else { + PKIX_CHECK(keyComp + ((PKIX_PL_Object *)key, + (PKIX_PL_Object *)(element->key), + &compResult, + plContext), + PKIX_COULDNOTTESTWHETHERKEYSEQUAL); + } + + if ((element->hashCode == hashCode) && + (compResult == PKIX_TRUE)){ + /* Same key already exists in the table */ + PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY); + } + } + + /* Next Element should be NULL at this point */ + if (element != NULL) { + PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET); + } + + /* Create a new HT_Elem */ + PKIX_CHECK(PKIX_PL_Malloc + (sizeof (pkix_pl_HT_Elem), (void **)elemPtr, plContext), + PKIX_MALLOCFAILED); + + element = *elemPtr; + + element->key = key; + element->value = value; + element->hashCode = hashCode; + element->next = NULL; + +cleanup: + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_PrimHashTable_Remove + * DESCRIPTION: + * + * Removes any objects with the key pointed to by "key" and hashCode value + * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the + * function pointed to by "keyComp" to compare keys, and stores the object's + * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object. + * This function sets "pResult" to NULL if the key is not in the hashtable. + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to remove object. Must be non-NULL. + * "key" + * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object. + * Must be non-NULL. + * "value" + * Address of Object to be added to PrimHashtable. Must be non-NULL. + * "hashCode" + * Hashcode value of the key. + * "keyComp" + * Address of function used to determine if two keys are equal. + * If NULL, pkix_pl_KeyComparator_Default is used. + * "pResult" + * Address where value will be stored. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a HashTable 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_pl_PrimHashTable_Remove( + pkix_pl_PrimHashTable *ht, + void *key, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void **pKey, + void **pValue, + void *plContext) +{ + pkix_pl_HT_Elem *element = NULL; + pkix_pl_HT_Elem *prior = NULL; + PKIX_Boolean compResult; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove"); + PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue); + + *pKey = NULL; + *pValue = NULL; + + for (element = ht->buckets[hashCode%ht->size], prior = element; + (element != NULL); + prior = element, element = element->next) { + + if (element->hashCode != hashCode){ + /* no possibility of a match */ + continue; + } + + if (keyComp == NULL){ + PKIX_CHECK(pkix_pl_KeyComparator_Default + ((PKIX_UInt32 *)key, + (PKIX_UInt32 *)(element->key), + &compResult, + plContext), + PKIX_COULDNOTTESTWHETHERKEYSEQUAL); + } else { + PKIX_CHECK(keyComp + ((PKIX_PL_Object *)key, + (PKIX_PL_Object *)(element->key), + &compResult, + plContext), + PKIX_COULDNOTTESTWHETHERKEYSEQUAL); + } + + if ((element->hashCode == hashCode) && + (compResult == PKIX_TRUE)){ + if (element != prior) { + prior->next = element->next; + } else { + ht->buckets[hashCode%ht->size] = element->next; + } + *pKey = element->key; + *pValue = element->value; + element->key = NULL; + element->value = NULL; + element->next = NULL; + PKIX_FREE(element); + goto cleanup; + } + } + +cleanup: + + PKIX_RETURN(HASHTABLE); +} + + +/* + * FUNCTION: pkix_pl_HashTableLookup + * DESCRIPTION: + * + * Looks up object using the key pointed to by "key" and hashCode value + * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the + * function pointed to by "keyComp" to compare keys, and stores the object's + * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object. + * This function sets "pResult" to NULL if the key is not in the hashtable. + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to lookup object from. Must be non-NULL. + * "key" + * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object. + * Must be non-NULL. + * "keyComp" + * Address of function used to determine if two keys are equal. + * If NULL, pkix_pl_KeyComparator_Default is used. + * "hashCode" + * Hashcode value of the key. + * "pResult" + * Address where value 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. + */ +PKIX_Error * +pkix_pl_PrimHashTable_Lookup( + pkix_pl_PrimHashTable *ht, + void *key, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void **pResult, + void *plContext) +{ + pkix_pl_HT_Elem *element = NULL; + PKIX_Boolean compResult = PKIX_FALSE; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Lookup"); + PKIX_NULLCHECK_THREE(ht, key, pResult); + + *pResult = NULL; + + for (element = (ht->buckets)[hashCode%ht->size]; + (element != NULL) && (*pResult == NULL); + element = element->next) { + + if (element->hashCode != hashCode){ + /* no possibility of a match */ + continue; + } + + if (keyComp == NULL){ + PKIX_CHECK(pkix_pl_KeyComparator_Default + ((PKIX_UInt32 *)key, + (PKIX_UInt32 *)(element->key), + &compResult, + plContext), + PKIX_COULDNOTTESTWHETHERKEYSEQUAL); + } else { + pkixErrorResult = + keyComp((PKIX_PL_Object *)key, + (PKIX_PL_Object *)(element->key), + &compResult, + plContext); + if (pkixErrorResult) { + pkixErrorClass = PKIX_FATAL_ERROR; + pkixErrorCode = PKIX_COULDNOTTESTWHETHERKEYSEQUAL; + goto cleanup; + } + } + + if ((element->hashCode == hashCode) && + (compResult == PKIX_TRUE)){ + *pResult = element->value; + goto cleanup; + } + } + + /* if we've reached here, specified key doesn't exist in hashtable */ + *pResult = NULL; + +cleanup: + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_PrimHashTable_Destroy + * + * Destroys PrimHashTable pointed to by "ht". + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to free. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS + * Returns NULL if the function succeeds. + * Returns a HashTable 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_pl_PrimHashTable_Destroy( + pkix_pl_PrimHashTable *ht, + void *plContext) +{ + pkix_pl_HT_Elem *element = NULL; + pkix_pl_HT_Elem *temp = NULL; + PKIX_UInt32 i; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Destroy"); + PKIX_NULLCHECK_ONE(ht); + + /* Free each element (list) */ + for (i = 0; i < ht->size; i++) { + for (element = ht->buckets[i]; + element != NULL; + element = temp) { + temp = element->next; + element->value = NULL; + element->key = NULL; + element->hashCode = 0; + element->next = NULL; + PKIX_FREE(element); + } + } + + /* Free the pointer to the list array */ + PKIX_FREE(ht->buckets); + ht->size = 0; + + /* Free the table itself */ + PKIX_FREE(ht); + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize + * DESCRIPTION: + * + * Retruns number of entries in the bucket the "hashCode" is designated in + * the hashtable "ht" in the address "pBucketSize". + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to get entries count. Must be non-NULL. + * "hashCode" + * Hashcode value of the key. + * "pBucketSize" + * Address that an PKIX_UInt32 is returned for number of entries in the + * bucket associated with the hashCode. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a HashTable 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_pl_PrimHashTable_GetBucketSize( + pkix_pl_PrimHashTable *ht, + PKIX_UInt32 hashCode, + PKIX_UInt32 *pBucketSize, + void *plContext) +{ + pkix_pl_HT_Elem **elemPtr = NULL; + pkix_pl_HT_Elem *element = NULL; + PKIX_UInt32 bucketSize = 0; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_GetBucketSize"); + PKIX_NULLCHECK_TWO(ht, pBucketSize); + + for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr; + element != NULL; elemPtr = &(element->next), element = *elemPtr) { + bucketSize++; + } + + *pBucketSize = bucketSize; + + PKIX_RETURN(HASHTABLE); +} + +/* + * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO + * DESCRIPTION: + * + * Remove the first entry in the bucket the "hashCode" is designated in + * the hashtable "ht". Since new entry is added at end of the link list + * the first one is the oldest (FI) therefore removed first (FO). + * + * PARAMETERS: + * "ht" + * Address of PrimHashtable to get entries count. Must be non-NULL. + * "hashCode" + * Hashcode value of the key. + * "pKey" + * Address of key of the entry deleted. Must be non-NULL. + * "pValue" + * Address of Value of the entry deleted. Must be non-NULL. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "ht" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a HashTable 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_pl_PrimHashTable_RemoveFIFO( + pkix_pl_PrimHashTable *ht, + PKIX_UInt32 hashCode, + void **pKey, + void **pValue, + void *plContext) +{ + pkix_pl_HT_Elem *element = NULL; + + PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove"); + PKIX_NULLCHECK_THREE(ht, pKey, pValue); + + element = (ht->buckets)[hashCode%ht->size]; + + if (element != NULL) { + + *pKey = element->key; + *pValue = element->value; + ht->buckets[hashCode%ht->size] = element->next; + element->key = NULL; + element->value = NULL; + element->next = NULL; + PKIX_FREE(element); + } + + PKIX_RETURN(HASHTABLE); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h new file mode 100644 index 0000000000..b889e2e91e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h @@ -0,0 +1,102 @@ +/* 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_pl_primhash.h + * + * Primitive Hashtable Definition + * + */ + +#ifndef _PKIX_PL_PRIMHASH_H +#define _PKIX_PL_PRIMHASH_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pkix_pl_HT_Elem pkix_pl_HT_Elem; + +typedef struct pkix_pl_PrimHashTable pkix_pl_PrimHashTable; + +typedef struct pkix_pl_Integer pkix_pl_Integer; + +struct pkix_pl_Integer{ + PKIX_UInt32 ht_int; +}; + +struct pkix_pl_HT_Elem { + void *key; + void *value; + PKIX_UInt32 hashCode; + pkix_pl_HT_Elem *next; +}; + +struct pkix_pl_PrimHashTable { + pkix_pl_HT_Elem **buckets; + PKIX_UInt32 size; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_PrimHashTable_Create( + PKIX_UInt32 numBuckets, + pkix_pl_PrimHashTable **pResult, + void *plContext); + +PKIX_Error * +pkix_pl_PrimHashTable_Add( + pkix_pl_PrimHashTable *ht, + void *key, + void *value, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void *plContext); + +PKIX_Error * +pkix_pl_PrimHashTable_Remove( + pkix_pl_PrimHashTable *ht, + void *key, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void **pKey, + void **pValue, + void *plContext); + +PKIX_Error * +pkix_pl_PrimHashTable_Lookup( + pkix_pl_PrimHashTable *ht, + void *key, + PKIX_UInt32 hashCode, + PKIX_PL_EqualsCallback keyComp, + void **pResult, + void *plContext); + +PKIX_Error* +pkix_pl_PrimHashTable_Destroy( + pkix_pl_PrimHashTable *ht, + void *plContext); + +PKIX_Error * +pkix_pl_PrimHashTable_GetBucketSize( + pkix_pl_PrimHashTable *ht, + PKIX_UInt32 hashCode, + PKIX_UInt32 *pBucketSize, + void *plContext); + +PKIX_Error * +pkix_pl_PrimHashTable_RemoveFIFO( + pkix_pl_PrimHashTable *ht, + PKIX_UInt32 hashCode, + void **pKey, + void **pValue, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_PRIMHASH_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c new file mode 100644 index 0000000000..662931e981 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c @@ -0,0 +1,217 @@ +/* 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_pl_rwlock.c + * + * Read/Write Lock Functions + * + */ + +#include "pkix_pl_rwlock.h" + +/* --Private-Functions-------------------------------------------- */ + +static PKIX_Error * +pkix_pl_RWLock_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_RWLock* rwlock = NULL; + + PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_RWLOCK_TYPE, plContext), + PKIX_OBJECTNOTRWLOCK); + + rwlock = (PKIX_PL_RWLock*) object; + + PKIX_RWLOCK_DEBUG("Calling PR_DestroyRWLock)\n"); + PR_DestroyRWLock(rwlock->lock); + rwlock->lock = NULL; + +cleanup: + + PKIX_RETURN(RWLOCK); +} + +/* + * FUNCTION: pkix_pl_RWLock_RegisterSelf + * DESCRIPTION: + * Registers PKIX_RWLOCK_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_pl_RWLock_RegisterSelf( + void *plContext) +{ + + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_RegisterSelf"); + + entry.description = "RWLock"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_RWLock); + entry.destructor = pkix_pl_RWLock_Destroy; + entry.equalsFunction = NULL; + entry.hashcodeFunction = NULL; + entry.toStringFunction = NULL; + entry.comparator = NULL; + entry.duplicateFunction = NULL; + + systemClasses[PKIX_RWLOCK_TYPE] = entry; + + PKIX_RETURN(RWLOCK); +} + +/* --Public-Functions--------------------------------------------- */ + +PKIX_Error * +PKIX_PL_RWLock_Create( + PKIX_PL_RWLock **pNewLock, + void *plContext) +{ + PKIX_PL_RWLock *rwLock = NULL; + + PKIX_ENTER(RWLOCK, "PKIX_PL_RWLock_Create"); + PKIX_NULLCHECK_ONE(pNewLock); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_RWLOCK_TYPE, + sizeof (PKIX_PL_RWLock), + (PKIX_PL_Object **)&rwLock, + plContext), + PKIX_ERRORALLOCATINGRWLOCK); + + PKIX_RWLOCK_DEBUG("\tCalling PR_NewRWLock)\n"); + rwLock->lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "PKIX RWLock"); + + if (rwLock->lock == NULL) { + PKIX_DECREF(rwLock); + PKIX_ERROR(PKIX_OUTOFMEMORY); + } + + rwLock->readCount = 0; + rwLock->writeLocked = PKIX_FALSE; + + *pNewLock = rwLock; + +cleanup: + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_AcquireReaderLock( + PKIX_PL_RWLock *lock, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireReaderLock"); + PKIX_NULLCHECK_ONE(lock); + + PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Rlock)\n"); + (void) PR_RWLock_Rlock(lock->lock); + + lock->readCount++; + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_ReleaseReaderLock( + PKIX_PL_RWLock *lock, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseReaderLock"); + PKIX_NULLCHECK_ONE(lock); + + PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n"); + (void) PR_RWLock_Unlock(lock->lock); + + lock->readCount--; + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_IsReaderLockHeld( + PKIX_PL_RWLock *lock, + PKIX_Boolean *pIsHeld, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_IsReaderLockHeld"); + PKIX_NULLCHECK_TWO(lock, pIsHeld); + + *pIsHeld = (lock->readCount > 0)?PKIX_TRUE:PKIX_FALSE; + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_AcquireWriterLock( + PKIX_PL_RWLock *lock, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireWriterLock"); + PKIX_NULLCHECK_ONE(lock); + + PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Wlock\n"); + (void) PR_RWLock_Wlock(lock->lock); + + if (lock->readCount > 0) { + PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT); + } + + /* We should never acquire a write lock if the lock is held */ + lock->writeLocked = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_ReleaseWriterLock( + PKIX_PL_RWLock *lock, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseWriterLock"); + PKIX_NULLCHECK_ONE(lock); + + if (lock->readCount > 0) { + PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT); + } + + PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n"); + (void) PR_RWLock_Unlock(lock->lock); + + /* XXX Need to think about thread safety here */ + /* There should be a single lock holder */ + lock->writeLocked = PKIX_FALSE; + +cleanup: + + PKIX_RETURN(RWLOCK); +} + +PKIX_Error * +PKIX_PL_IsWriterLockHeld( + PKIX_PL_RWLock *lock, + PKIX_Boolean *pIsHeld, + void *plContext) +{ + PKIX_ENTER(RWLOCK, "PKIX_PL_IsWriterLockHeld"); + PKIX_NULLCHECK_TWO(lock, pIsHeld); + + *pIsHeld = lock->writeLocked; + + PKIX_RETURN(RWLOCK); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h new file mode 100644 index 0000000000..fd64659506 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.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_pl_rwlock.h + * + * Read/Write Lock Definition + * + */ + +#ifndef _PKIX_PL_RWLOCK_H +#define _PKIX_PL_RWLOCK_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_RWLockStruct { + PRRWLock* lock; + PKIX_UInt32 readCount; + PKIX_Boolean writeLocked; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_RWLock_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_RWLOCK_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c new file mode 100644 index 0000000000..167382466e --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c @@ -0,0 +1,628 @@ +/* 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_pl_string.c + * + * String Object Functions + * + */ + +#include "pkix_pl_string.h" + +/* --Private-String-Functions------------------------------------- */ + +/* + * FUNCTION: pkix_pl_String_Comparator + * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h) + * + * NOTE: + * This function is a utility function called by pkix_pl_String_Equals(). + * It is not officially registered as a comparator. + */ +static PKIX_Error * +pkix_pl_String_Comparator( + PKIX_PL_String *firstString, + PKIX_PL_String *secondString, + PKIX_Int32 *pResult, + void *plContext) +{ + PKIX_UInt32 i; + PKIX_Int32 result; + unsigned char *p1 = NULL; + unsigned char *p2 = NULL; + + PKIX_ENTER(STRING, "pkix_pl_String_Comparator"); + PKIX_NULLCHECK_THREE(firstString, secondString, pResult); + + result = 0; + + p1 = (unsigned char*) firstString->utf16String; + p2 = (unsigned char*) secondString->utf16String; + + /* Compare characters until you find a difference */ + for (i = 0; ((i < firstString->utf16Length) && + (i < secondString->utf16Length) && + result == 0); i++, p1++, p2++) { + if (*p1 < *p2){ + result = -1; + } else if (*p1 > *p2){ + result = 1; + } + } + + /* If two arrays are identical so far, the longer one is greater */ + if (result == 0) { + if (firstString->utf16Length < secondString->utf16Length) { + result = -1; + } else if (firstString->utf16Length > + secondString->utf16Length) { + result = 1; + } + } + + *pResult = result; + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_pl_String_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_String_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_String *string = NULL; + + PKIX_ENTER(STRING, "pkix_pl_String_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext), + PKIX_ARGUMENTNOTSTRING); + + string = (PKIX_PL_String*)object; + + /* XXX For debugging Destroy EscASCII String */ + if (string->escAsciiString != NULL) { + PKIX_FREE(string->escAsciiString); + string->escAsciiString = NULL; + string->escAsciiLength = 0; + } + + /* Destroy UTF16 String */ + if (string->utf16String != NULL) { + PKIX_FREE(string->utf16String); + string->utf16String = NULL; + string->utf16Length = 0; + } + +cleanup: + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_pl_String_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_String_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *string = NULL; + char *ascii = NULL; + PKIX_UInt32 length; + + PKIX_ENTER(STRING, "pkix_pl_String_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext), + PKIX_ARGUMENTNOTSTRING); + + string = (PKIX_PL_String*)object; + + PKIX_CHECK(PKIX_PL_String_GetEncoded + (string, PKIX_ESCASCII, (void **)&ascii, &length, plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, ascii, 0, pString, plContext), + PKIX_STRINGCREATEFAILED); + + goto cleanup; + +cleanup: + + PKIX_FREE(ascii); + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_pl_String_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_String_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Int32 cmpResult = 0; + + PKIX_ENTER(STRING, "pkix_pl_String_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + /* Sanity check: Test that "firstObject" is a Strings */ + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_STRING_TYPE, plContext), + PKIX_FIRSTOBJECTNOTSTRING); + + /* "SecondObject" doesn't have to be a string */ + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + + /* If types differ, then we will return false */ + *pResult = PKIX_FALSE; + + if (secondType != PKIX_STRING_TYPE) goto cleanup; + + /* It's safe to cast here */ + PKIX_CHECK(pkix_pl_String_Comparator + ((PKIX_PL_String*)firstObject, + (PKIX_PL_String*)secondObject, + &cmpResult, + plContext), + PKIX_STRINGCOMPARATORFAILED); + + /* Strings are equal iff Comparator Result is 0 */ + *pResult = (cmpResult == 0); + +cleanup: + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_pl_String_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_pl_String_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_PL_String *string = NULL; + + PKIX_ENTER(STRING, "pkix_pl_String_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext), + PKIX_OBJECTNOTSTRING); + + string = (PKIX_PL_String*)object; + + PKIX_CHECK(pkix_hash + ((const unsigned char *)string->utf16String, + string->utf16Length, + pHashcode, + plContext), + PKIX_HASHFAILED); + +cleanup: + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: pkix_pl_String_RegisterSelf + * DESCRIPTION: + * Registers PKIX_STRING_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_pl_String_RegisterSelf( + void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(STRING, "pkix_pl_String_RegisterSelf"); + + entry.description = "String"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_PL_String); + entry.destructor = pkix_pl_String_Destroy; + entry.equalsFunction = pkix_pl_String_Equals; + entry.hashcodeFunction = pkix_pl_String_Hashcode; + entry.toStringFunction = pkix_pl_String_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_STRING_TYPE] = entry; + + PKIX_RETURN(STRING); +} + + +/* --Public-String-Functions----------------------------------------- */ + +/* + * FUNCTION: PKIX_PL_String_Create (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_String_Create( + PKIX_UInt32 fmtIndicator, + const void *stringRep, + PKIX_UInt32 stringLen, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *string = NULL; + unsigned char *utf16Char = NULL; + PKIX_UInt32 i; + + PKIX_ENTER(STRING, "PKIX_PL_String_Create"); + PKIX_NULLCHECK_TWO(pString, stringRep); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_STRING_TYPE, + sizeof (PKIX_PL_String), + (PKIX_PL_Object **)&string, + plContext), + PKIX_COULDNOTALLOCATENEWSTRINGOBJECT); + + string->utf16String = NULL; + string->utf16Length = 0; + + /* XXX For Debugging */ + string->escAsciiString = NULL; + string->escAsciiLength = 0; + + switch (fmtIndicator) { + case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG: + PKIX_STRING_DEBUG("\tCalling PL_strlen).\n"); + string->escAsciiLength = PL_strlen(stringRep); + + /* XXX Cache for Debugging */ + PKIX_CHECK(PKIX_PL_Malloc + ((string->escAsciiLength)+1, + (void **)&string->escAsciiString, + plContext), + PKIX_MALLOCFAILED); + + (void) PORT_Memcpy + (string->escAsciiString, + (void *)((char *)stringRep), + (string->escAsciiLength)+1); + + /* Convert the EscASCII string to UTF16 */ + PKIX_CHECK(pkix_EscASCII_to_UTF16 + (string->escAsciiString, + string->escAsciiLength, + (fmtIndicator == PKIX_ESCASCII_DEBUG), + &string->utf16String, + &string->utf16Length, + plContext), + PKIX_ESCASCIITOUTF16FAILED); + break; + case PKIX_UTF8: + /* Convert the UTF8 string to UTF16 */ + PKIX_CHECK(pkix_UTF8_to_UTF16 + (stringRep, + stringLen, + &string->utf16String, + &string->utf16Length, + plContext), + PKIX_UTF8TOUTF16FAILED); + break; + case PKIX_UTF16: + /* UTF16 Strings must be even in length */ + if (stringLen%2 == 1) { + PKIX_DECREF(string); + PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR); + } + + utf16Char = (unsigned char *)stringRep; + + /* Make sure this is a valid UTF-16 String */ + for (i = 0; \ + (i < stringLen) && (pkixErrorResult == NULL); \ + i += 2) { + /* Check that surrogate pairs are valid */ + if ((utf16Char[i] >= 0xD8)&& + (utf16Char[i] <= 0xDB)) { + if ((i+2) >= stringLen) { + PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR); + /* Second pair should be DC00-DFFF */ + } else if (!((utf16Char[i+2] >= 0xDC)&& + (utf16Char[i+2] <= 0xDF))) { + PKIX_ERROR(PKIX_UTF16LOWZONEERROR); + } else { + /* Surrogate quartet is valid. */ + i += 2; + } + } + } + + /* Create UTF16 String */ + string->utf16Length = stringLen; + + /* Alloc space for string */ + PKIX_CHECK(PKIX_PL_Malloc + (stringLen, &string->utf16String, plContext), + PKIX_MALLOCFAILED); + + PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy + (string->utf16String, stringRep, stringLen); + break; + + default: + PKIX_ERROR(PKIX_UNKNOWNFORMAT); + } + + *pString = string; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(string); + } + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: PKIX_PL_Sprintf (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_Sprintf( + PKIX_PL_String **pOut, + void *plContext, + const PKIX_PL_String *fmt, + ...) +{ + PKIX_PL_String *tempString = NULL; + PKIX_UInt32 tempUInt = 0; + void *pArg = NULL; + char *asciiText = NULL; + char *asciiFormat = NULL; + char *convertedAsciiFormat = NULL; + char *convertedAsciiFormatBase = NULL; + va_list args; + PKIX_UInt32 length, i, j, dummyLen; + + PKIX_ENTER(STRING, "PKIX_PL_Sprintf"); + PKIX_NULLCHECK_TWO(pOut, fmt); + + PKIX_CHECK(PKIX_PL_String_GetEncoded + ((PKIX_PL_String *)fmt, + PKIX_ESCASCII, + (void **)&asciiFormat, + &length, + plContext), + PKIX_STRINGGETENCODEDFAILED); + + PKIX_STRING_DEBUG("\tCalling PR_Malloc).\n"); + convertedAsciiFormat = PR_Malloc(length + 1); + if (convertedAsciiFormat == NULL) + PKIX_ERROR_ALLOC_ERROR(); + + convertedAsciiFormatBase = convertedAsciiFormat; + + PKIX_STRING_DEBUG("\tCalling va_start).\n"); + va_start(args, fmt); + + i = 0; + j = 0; + while (i < length) { + if ((asciiFormat[i] == '%')&&((i+1) < length)) { + switch (asciiFormat[i+1]) { + case 's': + convertedAsciiFormat[j++] = asciiFormat[i++]; + convertedAsciiFormat[j++] = asciiFormat[i++]; + convertedAsciiFormat[j] = '\0'; + + tempString = va_arg(args, PKIX_PL_String *); + if (tempString != NULL) { + PKIX_CHECK_NO_GOTO( + PKIX_PL_String_GetEncoded + ((PKIX_PL_String*) + tempString, + PKIX_ESCASCII, + &pArg, + &dummyLen, + plContext), + PKIX_STRINGGETENCODEDFAILED); + /* need to cleanup var args before + * we ditch out to cleanup. */ + if (pkixErrorResult) { + va_end(args); + goto cleanup; + } + } else { + /* there may be a NULL in var_args */ + pArg = NULL; + } + if (asciiText != NULL) { + asciiText = PR_sprintf_append(asciiText, + (const char *)convertedAsciiFormat, + pArg); + } else { + asciiText = PR_smprintf + ((const char *)convertedAsciiFormat, + pArg); + } + if (pArg != NULL) { + PKIX_PL_Free(pArg, plContext); + pArg = NULL; + } + convertedAsciiFormat += j; + j = 0; + break; + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + convertedAsciiFormat[j++] = asciiFormat[i++]; + convertedAsciiFormat[j++] = asciiFormat[i++]; + convertedAsciiFormat[j] = '\0'; + + tempUInt = va_arg(args, PKIX_UInt32); + if (asciiText != NULL) { + asciiText = PR_sprintf_append(asciiText, + (const char *)convertedAsciiFormat, + tempUInt); + } else { + asciiText = PR_smprintf + ((const char *)convertedAsciiFormat, + tempUInt); + } + convertedAsciiFormat += j; + j = 0; + break; + default: + convertedAsciiFormat[j++] = asciiFormat[i++]; + convertedAsciiFormat[j++] = asciiFormat[i++]; + break; + } + } else { + convertedAsciiFormat[j++] = asciiFormat[i++]; + } + } + + /* for constant string value at end of fmt */ + if (j > 0) { + convertedAsciiFormat[j] = '\0'; + if (asciiText != NULL) { + asciiText = PR_sprintf_append(asciiText, + (const char *)convertedAsciiFormat); + } else { + asciiText = PR_smprintf((const char *)convertedAsciiFormat); + } + } + + va_end(args); + + /* Copy temporary char * into a string object */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, (void *)asciiText, 0, pOut, plContext), + PKIX_STRINGCREATEFAILED); + +cleanup: + + PKIX_FREE(asciiFormat); + + if (convertedAsciiFormatBase){ + PR_Free(convertedAsciiFormatBase); + } + + if (asciiText){ + PKIX_STRING_DEBUG("\tCalling PR_smprintf_free).\n"); + PR_smprintf_free(asciiText); + } + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: PKIX_PL_GetString (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_GetString( + /* ARGSUSED */ PKIX_UInt32 stringID, + char *defaultString, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_ENTER(STRING, "PKIX_PL_GetString"); + PKIX_NULLCHECK_TWO(pString, defaultString); + + /* XXX Optimization - use stringID for caching */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, defaultString, 0, pString, plContext), + PKIX_STRINGCREATEFAILED); + +cleanup: + + PKIX_RETURN(STRING); +} + +/* + * FUNCTION: PKIX_PL_String_GetEncoded (see comments in pkix_pl_system.h) + */ +PKIX_Error * +PKIX_PL_String_GetEncoded( + PKIX_PL_String *string, + PKIX_UInt32 fmtIndicator, + void **pStringRep, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_ENTER(STRING, "PKIX_PL_String_GetEncoded"); + PKIX_NULLCHECK_THREE(string, pStringRep, pLength); + + switch (fmtIndicator) { + case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG: + PKIX_CHECK(pkix_UTF16_to_EscASCII + (string->utf16String, + string->utf16Length, + (fmtIndicator == PKIX_ESCASCII_DEBUG), + (char **)pStringRep, + pLength, + plContext), + PKIX_UTF16TOESCASCIIFAILED); + break; + case PKIX_UTF8: + PKIX_CHECK(pkix_UTF16_to_UTF8 + (string->utf16String, + string->utf16Length, + PKIX_FALSE, + pStringRep, + pLength, + plContext), + PKIX_UTF16TOUTF8FAILED); + break; + case PKIX_UTF8_NULL_TERM: + PKIX_CHECK(pkix_UTF16_to_UTF8 + (string->utf16String, + string->utf16Length, + PKIX_TRUE, + pStringRep, + pLength, + plContext), + PKIX_UTF16TOUTF8FAILED); + break; + case PKIX_UTF16: + *pLength = string->utf16Length; + + PKIX_CHECK(PKIX_PL_Malloc(*pLength, pStringRep, plContext), + PKIX_MALLOCFAILED); + + PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n"); + (void) PORT_Memcpy(*pStringRep, string->utf16String, *pLength); + break; + default: + PKIX_ERROR(PKIX_UNKNOWNFORMAT); + } + +cleanup: + + PKIX_RETURN(STRING); +} diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h new file mode 100644 index 0000000000..9270e4c567 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h @@ -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/. */ +/* + * pkix_pl_string.h + * + * String Object Definitions + * + */ + +#ifndef _PKIX_PL_STRING_H +#define _PKIX_PL_STRING_H + +#include "pkix_pl_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_PL_StringStruct { + void* utf16String; + PKIX_UInt32 utf16Length; + /* XXX For Debugging */ + char* escAsciiString; + PKIX_UInt32 escAsciiLength; +}; + +/* see source file for function documentation */ + +PKIX_Error * +pkix_pl_String_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_PL_STRING_H */ diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp new file mode 100644 index 0000000000..32daec93d6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp @@ -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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'pkixsystem', + 'type': 'static_library', + 'sources': [ + 'pkix_pl_bigint.c', + 'pkix_pl_bytearray.c', + 'pkix_pl_common.c', + 'pkix_pl_error.c', + 'pkix_pl_hashtable.c', + 'pkix_pl_lifecycle.c', + 'pkix_pl_mem.c', + 'pkix_pl_monitorlock.c', + 'pkix_pl_mutex.c', + 'pkix_pl_object.c', + 'pkix_pl_oid.c', + 'pkix_pl_primhash.c', + 'pkix_pl_rwlock.c', + 'pkix_pl_string.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file |