/* * 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_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_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_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_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, PKIX_UInt32 *pReasonCode, void *plContext) { PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn; PKIX_CertStore *certStore = NULL; pkix_CrlChecker *state = NULL; PKIX_UInt32 reasonCode = 0; 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, &reasonCode, &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_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_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_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_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_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_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_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_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 {
/* * 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_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_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_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_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); }
/* * 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_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_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_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_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++) { 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, 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, 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); }
/* * 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 PRArenaPool 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( PRArenaPool *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); }
/* * 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_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) { PRArenaPool *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_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_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; PRArenaPool *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) { for (thisName = 0; thisName < numNames; thisName++) { 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; } /* * LDAP Servers don't seem to be able to handle * requests with more than more than one name. */ break; } } 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_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, PKIX_UInt32 *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 reasonCode = 0; 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, &reasonCode, &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); }
/* * 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_GetEnv("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); }