/* * FUNCTION: pkix_List_AppendUnique * DESCRIPTION: * * Adds each Object in the List pointed to by "fromList" to the List pointed * to by "toList", if it is not already a member of that List. In other words, * "toList" becomes the union of the two sets. * * PARAMETERS: * "toList" * Address of a List of Objects to be augmented by "fromList". Must be * non-NULL, but may be empty. * "fromList" * Address of a List of Objects to be added, if not already present, to * "toList". Must be non-NULL, but may be empty. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "toList" * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_AppendUnique( PKIX_List *toList, PKIX_List *fromList, void *plContext) { PKIX_Boolean isContained = PKIX_FALSE; PKIX_UInt32 listLen = 0; PKIX_UInt32 listIx = 0; PKIX_PL_Object *object = NULL; PKIX_ENTER(BUILD, "pkix_List_AppendUnique"); PKIX_NULLCHECK_TWO(fromList, toList); PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext), PKIX_LISTGETLENGTHFAILED); for (listIx = 0; listIx < listLen; listIx++) { PKIX_CHECK(PKIX_List_GetItem (fromList, listIx, &object, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_List_Contains (toList, object, &isContained, plContext), PKIX_LISTCONTAINSFAILED); if (isContained == PKIX_FALSE) { PKIX_CHECK(PKIX_List_AppendItem (toList, object, plContext), PKIX_LISTAPPENDITEMFAILED); } PKIX_DECREF(object); } cleanup: PKIX_DECREF(object); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_EkuChecker_Check * DESCRIPTION: * * This function determines the Extended Key Usage OIDs specified by the * application is included in the Extended Key Usage OIDs of this "cert". * * PARAMETERS: * "checker" * Address of CertChainChecker which has the state data. * Must be non-NULL. * "cert" * Address of Certificate that is to be validated. Must be non-NULL. * "unresolvedCriticalExtensions" * A List OIDs. The OID for Extended Key Usage is removed. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a UserDefinedModules Error if the function fails in * a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_EkuChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_EkuChecker *state = NULL; PKIX_List *requiredExtKeyUsageList = NULL; PKIX_List *certExtKeyUsageList = NULL; PKIX_PL_OID *ekuOid = NULL; PKIX_Boolean isContained = PKIX_FALSE; PKIX_UInt32 numItems = 0; PKIX_UInt32 i; PKIX_Boolean checkResult = PKIX_TRUE; PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); *pNBIOContext = NULL; /* no non-blocking IO */ PKIX_CHECK( PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); requiredExtKeyUsageList = state->requiredExtKeyUsageOids; if (requiredExtKeyUsageList == NULL) { goto cleanup; } PKIX_CHECK( PKIX_List_GetLength(requiredExtKeyUsageList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); if (numItems == 0) { goto cleanup; } PKIX_CHECK( PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList, plContext), PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); if (certExtKeyUsageList == NULL) { goto cleanup; } for (i = 0; i < numItems; i++) { PKIX_CHECK( PKIX_List_GetItem(requiredExtKeyUsageList, i, (PKIX_PL_Object **)&ekuOid, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK( pkix_List_Contains(certExtKeyUsageList, (PKIX_PL_Object *)ekuOid, &isContained, plContext), PKIX_LISTCONTAINSFAILED); PKIX_DECREF(ekuOid); if (isContained != PKIX_TRUE) { checkResult = PKIX_FALSE; goto cleanup; } } cleanup: if (!pkixErrorResult && checkResult == PKIX_FALSE) { pkixErrorReceived = PKIX_TRUE; pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED; } PKIX_DECREF(ekuOid); PKIX_DECREF(certExtKeyUsageList); PKIX_DECREF(state); PKIX_RETURN(EKUCHECKER); }
/* * FUNCTION: pkix_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); }