/* * 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_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_NameConstraintsChecker_Check * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) */ static PKIX_Error * pkix_NameConstraintsChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_NameConstraintsCheckerState *state = NULL; PKIX_PL_CertNameConstraints *nameConstraints = NULL; PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL; PKIX_Boolean selfIssued = PKIX_FALSE; PKIX_Boolean lastCert = PKIX_FALSE; PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); *pNBIOContext = NULL; /* we never block on pending I/O */ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); state->certsRemaining--; lastCert = state->certsRemaining == 0; /* Get status of self issued */ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), PKIX_ISCERTSELFISSUEDFAILED); /* Check on non self-issued and if so only for last cert */ if (selfIssued == PKIX_FALSE || (selfIssued == PKIX_TRUE && lastCert)) { PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints (cert, state->nameConstraints, lastCert, plContext), PKIX_CERTCHECKNAMECONSTRAINTSFAILED); } if (!lastCert) { PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints (cert, &nameConstraints, plContext), PKIX_CERTGETNAMECONSTRAINTSFAILED); /* Merge with previous name constraints kept in state */ if (nameConstraints != NULL) { if (state->nameConstraints == NULL) { state->nameConstraints = nameConstraints; } else { PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints (nameConstraints, state->nameConstraints, &mergedNameConstraints, plContext), PKIX_CERTMERGENAMECONSTRAINTSFAILED); PKIX_DECREF(nameConstraints); PKIX_DECREF(state->nameConstraints); state->nameConstraints = mergedNameConstraints; } /* Remove Name Constraints Extension OID from list */ if (unresolvedCriticalExtensions != NULL) { PKIX_CHECK(pkix_List_Remove (unresolvedCriticalExtensions, (PKIX_PL_Object *)state->nameConstraintsOID, plContext), PKIX_LISTREMOVEFAILED); } } } PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState (checker, (PKIX_PL_Object *)state, plContext), PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); cleanup: PKIX_DECREF(state); PKIX_RETURN(CERTCHAINCHECKER); }
/* * FUNCTION: pkix_DefaultCRLChecker_CheckCRLs * * DESCRIPTION: * Check validity of "cert" based on CRLs at "crlList" that has correct * signature verification with "publicKey". * * PARAMETERS * "cert" * Address of Cert which has the certificate data. Must be non-NULL. * "certIssuer" * Address of Issuer that associates with the Cert. Must be non-NULL. * "certSerialNumber" * Address of Serial Number that associates with the Cert. Must be * non-NULL. * "publicKey" * Address of Public Key that associates with the Cert Issuer. * Must be non-NULL. * "crlList" * A List CRLs that the certificate is verified upon. Must be non-NULL. * "state" * Address of DefaultCRLCheckerState which keeps dynamic state data. * Must be non-NULL. * "pCrlEntryList" * Address of PKIX_PL_CrlEntry List that contains valid CrlEntries for * this Cert. May be 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 */ static PKIX_Error * pkix_DefaultCRLChecker_CheckCRLs( PKIX_PL_Cert *cert, PKIX_PL_X500Name *certIssuer, PKIX_PL_BigInt *certSerialNumber, PKIX_PL_PublicKey *publicKey, PKIX_List *crlList, pkix_DefaultCRLCheckerState *state, PKIX_List **pCrlEntryList, void *plContext) { PKIX_PL_CRL *crl = NULL; PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_PL_PublicKey *pKey = NULL; PKIX_List *unresCrlCritExtOIDs = NULL; PKIX_List *unresCrlEntryCritExtOIDs = NULL; PKIX_List *crlEntryList = NULL; PKIX_Error *verifyFail = NULL; PKIX_UInt32 numCrls = 0; PKIX_UInt32 numKeys = 0; PKIX_UInt32 numCritExtOIDs = 0; PKIX_Boolean crlVerified = PKIX_FALSE; PKIX_Boolean crlRevoking = PKIX_FALSE; PKIX_Int32 reasonCode = 0; PKIX_UInt32 i; PKIX_Int32 j; PKIX_ENTER(CERTCHAINCHECKER, "pkix_DefaultCRLChecker_CheckCRLs"); PKIX_NULLCHECK_FOUR(cert, publicKey, crlList, state); PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext), PKIX_LISTGETLENGTHFAILED); if (state->prevPublicKeyList != NULL) { PKIX_CHECK(PKIX_List_GetLength (state->prevPublicKeyList, &numKeys, plContext), PKIX_LISTGETLENGTHFAILED); } /* Check if Cert is not revoked by any the the CRLs */ for (i = 0; i < numCrls; i++){ PKIX_CHECK(PKIX_List_GetItem (crlList, i, (PKIX_PL_Object **)&crl, plContext), PKIX_LISTGETITEMFAILED); /* * Checking serial number (issuer done in selector) then * verify signature. If matches, get the CRL reason(s). */ if (state->prevCertCrlSign == PKIX_TRUE) { verifyFail = PKIX_PL_CRL_VerifySignature (crl, publicKey, plContext); if (verifyFail == NULL) { crlVerified = PKIX_TRUE; } else { crlVerified = PKIX_FALSE; PKIX_DECREF(verifyFail); } } if (crlVerified == PKIX_FALSE) { /* Verify from old key(s) on the list */ for (j = numKeys - 1; j >= 0; j--) { PKIX_CHECK(PKIX_List_GetItem (state->prevPublicKeyList, j, (PKIX_PL_Object **) &pKey, plContext), PKIX_LISTGETITEMFAILED); verifyFail = PKIX_PL_CRL_VerifySignature (crl, pKey, plContext); if (verifyFail == NULL) { crlVerified = PKIX_TRUE; break; } else { crlVerified = PKIX_FALSE; PKIX_DECREF(verifyFail); } PKIX_DECREF(pKey); } } if (crlVerified == PKIX_FALSE) { /* try next one ... */ goto cleanup_loop; } state->certHasValidCrl = PKIX_TRUE; PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs (crl, &unresCrlCritExtOIDs, plContext), PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED); /* * XXX Advanced CRL work - should put a * Loop here to process and remove critical * extension oids. */ if (unresCrlCritExtOIDs) { PKIX_CHECK(PKIX_List_GetLength(unresCrlCritExtOIDs, &numCritExtOIDs, plContext), PKIX_LISTGETLENGTHFAILED); if (numCritExtOIDs != 0) { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG (PKIX_CRLCRITICALEXTENSIONOIDSNOTPROCESSED); /* * Uncomment this after we have implemented * checkers for all the critical extensions. * * PKIX_ERROR * ("Unrecognized CRL Critical Extension"); */ } } PKIX_CHECK(PKIX_PL_CRL_GetCRLEntryForSerialNumber (crl, certSerialNumber, &crlEntry, plContext), PKIX_CRLGETCRLENTRYFORSERIALNUMBERFAILED); if (crlEntry == NULL) { goto cleanup_loop; } crlRevoking = PKIX_TRUE; PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode (crlEntry, &reasonCode, plContext), PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); /* This is a valid CRLEntry, return it for caching */ if (crlEntryList == NULL) { PKIX_CHECK(PKIX_List_Create(&crlEntryList, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (crlEntryList, (PKIX_PL_Object *) crlEntry, plContext), PKIX_LISTAPPENDITEMFAILED); /* Set reason code in state for advance CRL reviewing */ if (reasonCode >= 0) { if (reasonCode >= numReasonCodes) reasonCode = 0; state->reasonCodeMask |= 1 << reasonCode; PKIX_DEFAULTCRLCHECKERSTATE_DEBUG_ARG ("CRL revocation Reason: %s\n ", reasonCodeMsgString[reasonCode]); } else { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG ("Revoked by Unknown CRL ReasonCode"); } PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (crlEntry, &unresCrlEntryCritExtOIDs, plContext), PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED); if (unresCrlEntryCritExtOIDs) { PKIX_CHECK(pkix_List_Remove (unresCrlEntryCritExtOIDs, (PKIX_PL_Object *) state->crlReasonCodeOID, plContext), PKIX_LISTREMOVEFAILED); PKIX_CHECK(PKIX_List_GetLength(unresCrlEntryCritExtOIDs, &numCritExtOIDs, plContext), PKIX_LISTGETLENGTHFAILED); if (numCritExtOIDs != 0) { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG (PKIX_CRLENTRYCRITICALEXTENSIONWASNOTPROCESSED); PKIX_ERROR(PKIX_UNRECOGNIZEDCRLENTRYCRITICALEXTENSION); } } cleanup_loop: PKIX_DECREF(pKey); PKIX_DECREF(verifyFail); PKIX_DECREF(pKey); PKIX_DECREF(crlEntry); PKIX_DECREF(crl); PKIX_DECREF(unresCrlCritExtOIDs); PKIX_DECREF(unresCrlEntryCritExtOIDs); } *pCrlEntryList = crlEntryList; if (crlRevoking == PKIX_TRUE) { PKIX_ERROR(PKIX_CERTIFICATEREVOKEDBYCRL); } cleanup: PKIX_DECREF(pKey); PKIX_DECREF(verifyFail); PKIX_DECREF(crlEntry); PKIX_DECREF(crl); PKIX_DECREF(unresCrlCritExtOIDs); PKIX_DECREF(unresCrlEntryCritExtOIDs); PKIX_RETURN(CERTCHAINCHECKER); }