| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| /* |
| * pkix_ekuchecker.c |
| * |
| * User Defined ExtenedKeyUsage Function Definitions |
| * |
| */ |
| |
| #include "pkix_ekuchecker.h" |
| |
| SECOidTag ekuOidStrings[] = { |
| PKIX_KEY_USAGE_SERVER_AUTH_OID, |
| PKIX_KEY_USAGE_CLIENT_AUTH_OID, |
| PKIX_KEY_USAGE_CODE_SIGN_OID, |
| PKIX_KEY_USAGE_EMAIL_PROTECT_OID, |
| PKIX_KEY_USAGE_TIME_STAMP_OID, |
| PKIX_KEY_USAGE_OCSP_RESPONDER_OID, |
| PKIX_UNKNOWN_OID |
| }; |
| |
| typedef struct pkix_EkuCheckerStruct { |
| PKIX_List *requiredExtKeyUsageOids; |
| PKIX_PL_OID *ekuOID; |
| } pkix_EkuChecker; |
| |
| |
| /* |
| * FUNCTION: pkix_EkuChecker_Destroy |
| * (see comments for PKIX_DestructorCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_EkuChecker_Destroy( |
| PKIX_PL_Object *object, |
| void *plContext) |
| { |
| pkix_EkuChecker *ekuCheckerState = NULL; |
| |
| PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy"); |
| PKIX_NULLCHECK_ONE(object); |
| |
| PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext), |
| PKIX_OBJECTNOTANEKUCHECKERSTATE); |
| |
| ekuCheckerState = (pkix_EkuChecker *)object; |
| |
| PKIX_DECREF(ekuCheckerState->ekuOID); |
| PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids); |
| |
| cleanup: |
| |
| PKIX_RETURN(EKUCHECKER); |
| } |
| |
| /* |
| * FUNCTION: pkix_EkuChecker_RegisterSelf |
| * |
| * DESCRIPTION: |
| * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related |
| * functions with systemClasses[] |
| * |
| * THREAD SAFETY: |
| * Not Thread Safe - for performance and complexity reasons |
| * |
| * Since this function is only called by PKIX_PL_Initialize, which should |
| * only be called once, it is acceptable that this function is not |
| * thread-safe. |
| */ |
| PKIX_Error * |
| pkix_EkuChecker_RegisterSelf(void *plContext) |
| { |
| extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
| pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE]; |
| |
| PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf"); |
| |
| entry->description = "EkuChecker"; |
| entry->typeObjectSize = sizeof(pkix_EkuChecker); |
| entry->destructor = pkix_EkuChecker_Destroy; |
| |
| PKIX_RETURN(EKUCHECKER); |
| } |
| |
| /* |
| * FUNCTION: pkix_EkuChecker_Create |
| * DESCRIPTION: |
| * |
| * Creates a new Extend Key Usage CheckerState using "params" to retrieve |
| * application specified EKU for verification and stores it at "pState". |
| * |
| * PARAMETERS: |
| * "params" |
| * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of |
| * Extended Key Usage OIDs specified by application can be retrieved for |
| * verification. |
| * "pState" |
| * Address where state pointer will be stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a UserDefinedModules Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_EkuChecker_Create( |
| PKIX_ProcessingParams *params, |
| pkix_EkuChecker **pState, |
| void *plContext) |
| { |
| pkix_EkuChecker *state = NULL; |
| PKIX_CertSelector *certSelector = NULL; |
| PKIX_ComCertSelParams *comCertSelParams = NULL; |
| PKIX_List *requiredOids = NULL; |
| |
| PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create"); |
| PKIX_NULLCHECK_TWO(params, pState); |
| |
| PKIX_CHECK(PKIX_PL_Object_Alloc |
| (PKIX_EKUCHECKER_TYPE, |
| sizeof (pkix_EkuChecker), |
| (PKIX_PL_Object **)&state, |
| plContext), |
| PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT); |
| |
| |
| PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints |
| (params, &certSelector, plContext), |
| PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); |
| |
| if (certSelector != NULL) { |
| |
| /* Get initial EKU OIDs from ComCertSelParams, if set */ |
| PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams |
| (certSelector, &comCertSelParams, plContext), |
| PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); |
| |
| if (comCertSelParams != NULL) { |
| PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage |
| (comCertSelParams, &requiredOids, plContext), |
| PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); |
| |
| } |
| } |
| |
| PKIX_CHECK(PKIX_PL_OID_Create |
| (PKIX_EXTENDEDKEYUSAGE_OID, |
| &state->ekuOID, |
| plContext), |
| PKIX_OIDCREATEFAILED); |
| |
| state->requiredExtKeyUsageOids = requiredOids; |
| requiredOids = NULL; |
| *pState = state; |
| state = NULL; |
| |
| cleanup: |
| |
| PKIX_DECREF(certSelector); |
| PKIX_DECREF(comCertSelParams); |
| PKIX_DECREF(requiredOids); |
| PKIX_DECREF(state); |
| |
| PKIX_RETURN(EKUCHECKER); |
| } |
| |
| /* |
| * FUNCTION: pkix_EkuChecker_Check |
| * DESCRIPTION: |
| * |
| * This function determines the Extended Key Usage OIDs specified by the |
| * application is included in the Extended Key Usage OIDs of this "cert". |
| * |
| * PARAMETERS: |
| * "checker" |
| * Address of CertChainChecker which has the state data. |
| * Must be non-NULL. |
| * "cert" |
| * Address of Certificate that is to be validated. Must be non-NULL. |
| * "unresolvedCriticalExtensions" |
| * A List OIDs. The OID for Extended Key Usage is removed. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a UserDefinedModules Error if the function fails in |
| * a non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_EkuChecker_Check( |
| PKIX_CertChainChecker *checker, |
| PKIX_PL_Cert *cert, |
| PKIX_List *unresolvedCriticalExtensions, |
| void **pNBIOContext, |
| void *plContext) |
| { |
| pkix_EkuChecker *state = NULL; |
| PKIX_List *requiredExtKeyUsageList = NULL; |
| PKIX_List *certExtKeyUsageList = NULL; |
| PKIX_PL_OID *ekuOid = NULL; |
| PKIX_Boolean isContained = PKIX_FALSE; |
| PKIX_UInt32 numItems = 0; |
| PKIX_UInt32 i; |
| PKIX_Boolean checkResult = PKIX_TRUE; |
| |
| PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check"); |
| PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); |
| |
| *pNBIOContext = NULL; /* no non-blocking IO */ |
| |
| PKIX_CHECK( |
| PKIX_CertChainChecker_GetCertChainCheckerState |
| (checker, (PKIX_PL_Object **)&state, plContext), |
| PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); |
| |
| requiredExtKeyUsageList = state->requiredExtKeyUsageOids; |
| if (requiredExtKeyUsageList == NULL) { |
| goto cleanup; |
| } |
| |
| PKIX_CHECK( |
| PKIX_List_GetLength(requiredExtKeyUsageList, &numItems, |
| plContext), |
| PKIX_LISTGETLENGTHFAILED); |
| if (numItems == 0) { |
| goto cleanup; |
| } |
| |
| PKIX_CHECK( |
| PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList, |
| plContext), |
| PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); |
| |
| if (certExtKeyUsageList == NULL) { |
| goto cleanup; |
| } |
| |
| for (i = 0; i < numItems; i++) { |
| |
| PKIX_CHECK( |
| PKIX_List_GetItem(requiredExtKeyUsageList, i, |
| (PKIX_PL_Object **)&ekuOid, plContext), |
| PKIX_LISTGETITEMFAILED); |
| |
| PKIX_CHECK( |
| pkix_List_Contains(certExtKeyUsageList, |
| (PKIX_PL_Object *)ekuOid, |
| &isContained, |
| plContext), |
| PKIX_LISTCONTAINSFAILED); |
| |
| PKIX_DECREF(ekuOid); |
| if (isContained != PKIX_TRUE) { |
| checkResult = PKIX_FALSE; |
| goto cleanup; |
| } |
| } |
| |
| cleanup: |
| if (!pkixErrorResult && checkResult == PKIX_FALSE) { |
| pkixErrorReceived = PKIX_TRUE; |
| pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED; |
| } |
| |
| PKIX_DECREF(ekuOid); |
| PKIX_DECREF(certExtKeyUsageList); |
| PKIX_DECREF(state); |
| |
| PKIX_RETURN(EKUCHECKER); |
| } |
| |
| /* |
| * FUNCTION: pkix_EkuChecker_Initialize |
| * (see comments in pkix_sample_modules.h) |
| */ |
| PKIX_Error * |
| PKIX_EkuChecker_Create( |
| PKIX_ProcessingParams *params, |
| PKIX_CertChainChecker **pEkuChecker, |
| void *plContext) |
| { |
| pkix_EkuChecker *state = NULL; |
| PKIX_List *critExtOIDsList = NULL; |
| |
| PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize"); |
| PKIX_NULLCHECK_ONE(params); |
| |
| /* |
| * This function and functions in this file provide an example of how |
| * an application defined checker can be hooked into libpkix. |
| */ |
| |
| PKIX_CHECK(pkix_EkuChecker_Create |
| (params, &state, plContext), |
| PKIX_EKUCHECKERSTATECREATEFAILED); |
| |
| PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext), |
| PKIX_LISTCREATEFAILED); |
| |
| PKIX_CHECK(PKIX_List_AppendItem |
| (critExtOIDsList, |
| (PKIX_PL_Object *)state->ekuOID, |
| plContext), |
| PKIX_LISTAPPENDITEMFAILED); |
| |
| PKIX_CHECK(PKIX_CertChainChecker_Create |
| (pkix_EkuChecker_Check, |
| PKIX_TRUE, /* forwardCheckingSupported */ |
| PKIX_FALSE, /* forwardDirectionExpected */ |
| critExtOIDsList, |
| (PKIX_PL_Object *) state, |
| pEkuChecker, |
| plContext), |
| PKIX_CERTCHAINCHECKERCREATEFAILED); |
| cleanup: |
| |
| PKIX_DECREF(critExtOIDsList); |
| PKIX_DECREF(state); |
| |
| PKIX_RETURN(EKUCHECKER); |
| } |