security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,328 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_ekuchecker.c
     1.9 + *
    1.10 + * User Defined ExtenedKeyUsage Function Definitions
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +#include "pkix_ekuchecker.h"
    1.15 +
    1.16 +SECOidTag ekuOidStrings[] = {
    1.17 +    PKIX_KEY_USAGE_SERVER_AUTH_OID,
    1.18 +    PKIX_KEY_USAGE_CLIENT_AUTH_OID,
    1.19 +    PKIX_KEY_USAGE_CODE_SIGN_OID,
    1.20 +    PKIX_KEY_USAGE_EMAIL_PROTECT_OID,
    1.21 +    PKIX_KEY_USAGE_TIME_STAMP_OID,
    1.22 +    PKIX_KEY_USAGE_OCSP_RESPONDER_OID,
    1.23 +    PKIX_UNKNOWN_OID
    1.24 +};
    1.25 +
    1.26 +typedef struct pkix_EkuCheckerStruct {
    1.27 +    PKIX_List *requiredExtKeyUsageOids;
    1.28 +    PKIX_PL_OID *ekuOID;
    1.29 +} pkix_EkuChecker;
    1.30 +
    1.31 +
    1.32 +/*
    1.33 + * FUNCTION: pkix_EkuChecker_Destroy
    1.34 + * (see comments for PKIX_DestructorCallback in pkix_pl_system.h)
    1.35 + */
    1.36 +static PKIX_Error *
    1.37 +pkix_EkuChecker_Destroy(
    1.38 +        PKIX_PL_Object *object,
    1.39 +        void *plContext)
    1.40 +{
    1.41 +        pkix_EkuChecker *ekuCheckerState = NULL;
    1.42 +
    1.43 +        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy");
    1.44 +        PKIX_NULLCHECK_ONE(object);
    1.45 +
    1.46 +        PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext),
    1.47 +                    PKIX_OBJECTNOTANEKUCHECKERSTATE);
    1.48 +
    1.49 +        ekuCheckerState = (pkix_EkuChecker *)object;
    1.50 +
    1.51 +        PKIX_DECREF(ekuCheckerState->ekuOID);
    1.52 +        PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids);
    1.53 +
    1.54 +cleanup:
    1.55 +
    1.56 +        PKIX_RETURN(EKUCHECKER);
    1.57 +}
    1.58 +
    1.59 +/*
    1.60 + * FUNCTION: pkix_EkuChecker_RegisterSelf
    1.61 + *
    1.62 + * DESCRIPTION:
    1.63 + *  Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related
    1.64 + *  functions with systemClasses[]
    1.65 + *
    1.66 + * THREAD SAFETY:
    1.67 + *  Not Thread Safe - for performance and complexity reasons
    1.68 + *
    1.69 + *  Since this function is only called by PKIX_PL_Initialize, which should
    1.70 + *  only be called once, it is acceptable that this function is not
    1.71 + *  thread-safe.
    1.72 + */
    1.73 +PKIX_Error *
    1.74 +pkix_EkuChecker_RegisterSelf(void *plContext)
    1.75 +{
    1.76 +        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    1.77 +        pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE];
    1.78 +
    1.79 +        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf");
    1.80 +
    1.81 +        entry->description = "EkuChecker";
    1.82 +        entry->typeObjectSize = sizeof(pkix_EkuChecker);
    1.83 +        entry->destructor = pkix_EkuChecker_Destroy;
    1.84 +
    1.85 +        PKIX_RETURN(EKUCHECKER);
    1.86 +}
    1.87 +
    1.88 +/*
    1.89 + * FUNCTION: pkix_EkuChecker_Create
    1.90 + * DESCRIPTION:
    1.91 + *
    1.92 + *  Creates a new Extend Key Usage CheckerState using "params" to retrieve
    1.93 + *  application specified EKU for verification and stores it at "pState".
    1.94 + *
    1.95 + * PARAMETERS:
    1.96 + *  "params"
    1.97 + *      a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
    1.98 + *      Extended Key Usage OIDs specified by application can be retrieved for
    1.99 + *      verification.
   1.100 + *  "pState"
   1.101 + *      Address where state pointer will be stored. Must be non-NULL.
   1.102 + *  "plContext"
   1.103 + *      Platform-specific context pointer.
   1.104 + * THREAD SAFETY:
   1.105 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.106 + * RETURNS:
   1.107 + *  Returns NULL if the function succeeds.
   1.108 + *  Returns a UserDefinedModules Error if the function fails in a
   1.109 + *      non-fatal way.
   1.110 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.111 + */
   1.112 +static PKIX_Error *
   1.113 +pkix_EkuChecker_Create(
   1.114 +        PKIX_ProcessingParams *params,
   1.115 +        pkix_EkuChecker **pState,
   1.116 +        void *plContext)
   1.117 +{
   1.118 +        pkix_EkuChecker *state = NULL;
   1.119 +        PKIX_CertSelector *certSelector = NULL;
   1.120 +        PKIX_ComCertSelParams *comCertSelParams = NULL;
   1.121 +        PKIX_List *requiredOids = NULL;
   1.122 +
   1.123 +        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create");
   1.124 +        PKIX_NULLCHECK_TWO(params, pState);
   1.125 +
   1.126 +        PKIX_CHECK(PKIX_PL_Object_Alloc
   1.127 +                    (PKIX_EKUCHECKER_TYPE,
   1.128 +                    sizeof (pkix_EkuChecker),
   1.129 +                    (PKIX_PL_Object **)&state,
   1.130 +                    plContext),
   1.131 +                    PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT);
   1.132 +
   1.133 +
   1.134 +        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
   1.135 +                    (params, &certSelector, plContext),
   1.136 +                    PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
   1.137 +
   1.138 +        if (certSelector != NULL) {
   1.139 +
   1.140 +            /* Get initial EKU OIDs from ComCertSelParams, if set */
   1.141 +            PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
   1.142 +                       (certSelector, &comCertSelParams, plContext),
   1.143 +                       PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
   1.144 +
   1.145 +            if (comCertSelParams != NULL) {
   1.146 +                PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
   1.147 +                           (comCertSelParams, &requiredOids, plContext),
   1.148 +                           PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
   1.149 +
   1.150 +            }
   1.151 +        }
   1.152 +
   1.153 +        PKIX_CHECK(PKIX_PL_OID_Create
   1.154 +                    (PKIX_EXTENDEDKEYUSAGE_OID,
   1.155 +                    &state->ekuOID,
   1.156 +                    plContext),
   1.157 +                    PKIX_OIDCREATEFAILED);
   1.158 +
   1.159 +        state->requiredExtKeyUsageOids = requiredOids;
   1.160 +        requiredOids = NULL;
   1.161 +        *pState = state;
   1.162 +        state = NULL;
   1.163 +
   1.164 +cleanup:
   1.165 +
   1.166 +        PKIX_DECREF(certSelector);
   1.167 +        PKIX_DECREF(comCertSelParams);
   1.168 +        PKIX_DECREF(requiredOids);
   1.169 +        PKIX_DECREF(state);
   1.170 +
   1.171 +        PKIX_RETURN(EKUCHECKER);
   1.172 +}
   1.173 +
   1.174 +/*
   1.175 + * FUNCTION: pkix_EkuChecker_Check
   1.176 + * DESCRIPTION:
   1.177 + *
   1.178 + *  This function determines the Extended Key Usage OIDs specified by the
   1.179 + *  application is included in the Extended Key Usage OIDs of this "cert".
   1.180 + *
   1.181 + * PARAMETERS:
   1.182 + *  "checker"
   1.183 + *      Address of CertChainChecker which has the state data.
   1.184 + *      Must be non-NULL.
   1.185 + *  "cert"
   1.186 + *      Address of Certificate that is to be validated. Must be non-NULL.
   1.187 + *  "unresolvedCriticalExtensions"
   1.188 + *      A List OIDs. The OID for Extended Key Usage is removed.
   1.189 + *  "plContext"
   1.190 + *      Platform-specific context pointer.
   1.191 + * THREAD SAFETY:
   1.192 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.193 + * RETURNS:
   1.194 + *  Returns NULL if the function succeeds.
   1.195 + *  Returns a UserDefinedModules Error if the function fails in
   1.196 + *      a non-fatal way.
   1.197 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.198 + */
   1.199 +static PKIX_Error *
   1.200 +pkix_EkuChecker_Check(
   1.201 +        PKIX_CertChainChecker *checker,
   1.202 +        PKIX_PL_Cert *cert,
   1.203 +        PKIX_List *unresolvedCriticalExtensions,
   1.204 +        void **pNBIOContext,
   1.205 +        void *plContext)
   1.206 +{
   1.207 +        pkix_EkuChecker *state = NULL;
   1.208 +        PKIX_List *requiredExtKeyUsageList = NULL;
   1.209 +        PKIX_List *certExtKeyUsageList = NULL;
   1.210 +        PKIX_PL_OID *ekuOid = NULL;
   1.211 +        PKIX_Boolean isContained = PKIX_FALSE;
   1.212 +        PKIX_UInt32 numItems = 0;
   1.213 +        PKIX_UInt32 i;
   1.214 +        PKIX_Boolean checkResult = PKIX_TRUE;
   1.215 +
   1.216 +        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check");
   1.217 +        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
   1.218 +
   1.219 +        *pNBIOContext = NULL; /* no non-blocking IO */
   1.220 +
   1.221 +        PKIX_CHECK(
   1.222 +            PKIX_CertChainChecker_GetCertChainCheckerState
   1.223 +            (checker, (PKIX_PL_Object **)&state, plContext),
   1.224 +            PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
   1.225 +
   1.226 +        requiredExtKeyUsageList = state->requiredExtKeyUsageOids;
   1.227 +        if (requiredExtKeyUsageList == NULL) {
   1.228 +            goto cleanup;
   1.229 +        }
   1.230 +
   1.231 +        PKIX_CHECK(
   1.232 +            PKIX_List_GetLength(requiredExtKeyUsageList, &numItems,
   1.233 +                                plContext),
   1.234 +            PKIX_LISTGETLENGTHFAILED);
   1.235 +        if (numItems == 0) {
   1.236 +            goto cleanup;
   1.237 +        }
   1.238 +
   1.239 +        PKIX_CHECK(
   1.240 +            PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList,
   1.241 +                                             plContext),
   1.242 +            PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
   1.243 +
   1.244 +        if (certExtKeyUsageList == NULL) {
   1.245 +            goto cleanup;
   1.246 +        }
   1.247 +        
   1.248 +        for (i = 0; i < numItems; i++) {
   1.249 +            
   1.250 +            PKIX_CHECK(
   1.251 +                PKIX_List_GetItem(requiredExtKeyUsageList, i,
   1.252 +                                  (PKIX_PL_Object **)&ekuOid, plContext),
   1.253 +                PKIX_LISTGETITEMFAILED);
   1.254 +
   1.255 +            PKIX_CHECK(
   1.256 +                pkix_List_Contains(certExtKeyUsageList,
   1.257 +                                   (PKIX_PL_Object *)ekuOid,
   1.258 +                                   &isContained,
   1.259 +                                   plContext),
   1.260 +                PKIX_LISTCONTAINSFAILED);
   1.261 +            
   1.262 +            PKIX_DECREF(ekuOid);
   1.263 +            if (isContained != PKIX_TRUE) {
   1.264 +                checkResult = PKIX_FALSE;
   1.265 +                goto cleanup;
   1.266 +            }
   1.267 +        }
   1.268 +
   1.269 +cleanup:
   1.270 +        if (!pkixErrorResult && checkResult == PKIX_FALSE) {
   1.271 +            pkixErrorReceived = PKIX_TRUE;
   1.272 +            pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED;
   1.273 +        }
   1.274 +        
   1.275 +        PKIX_DECREF(ekuOid);
   1.276 +        PKIX_DECREF(certExtKeyUsageList);
   1.277 +        PKIX_DECREF(state);
   1.278 +
   1.279 +        PKIX_RETURN(EKUCHECKER);
   1.280 +}
   1.281 +
   1.282 +/*
   1.283 + * FUNCTION: pkix_EkuChecker_Initialize
   1.284 + * (see comments in pkix_sample_modules.h)
   1.285 + */
   1.286 +PKIX_Error *
   1.287 +PKIX_EkuChecker_Create(
   1.288 +        PKIX_ProcessingParams *params,
   1.289 +        PKIX_CertChainChecker **pEkuChecker,
   1.290 +        void *plContext)
   1.291 +{
   1.292 +        pkix_EkuChecker *state = NULL;
   1.293 +        PKIX_List *critExtOIDsList = NULL;
   1.294 +
   1.295 +        PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize");
   1.296 +        PKIX_NULLCHECK_ONE(params);
   1.297 +
   1.298 +        /*
   1.299 +         * This function and functions in this file provide an example of how
   1.300 +         * an application defined checker can be hooked into libpkix.
   1.301 +         */
   1.302 +
   1.303 +        PKIX_CHECK(pkix_EkuChecker_Create
   1.304 +                    (params, &state, plContext),
   1.305 +                    PKIX_EKUCHECKERSTATECREATEFAILED);
   1.306 +
   1.307 +        PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext),
   1.308 +                    PKIX_LISTCREATEFAILED);
   1.309 +
   1.310 +        PKIX_CHECK(PKIX_List_AppendItem
   1.311 +                    (critExtOIDsList,
   1.312 +                    (PKIX_PL_Object *)state->ekuOID,
   1.313 +                    plContext),
   1.314 +                    PKIX_LISTAPPENDITEMFAILED);
   1.315 +
   1.316 +        PKIX_CHECK(PKIX_CertChainChecker_Create
   1.317 +                (pkix_EkuChecker_Check,
   1.318 +                PKIX_TRUE,                 /* forwardCheckingSupported */
   1.319 +                PKIX_FALSE,                /* forwardDirectionExpected */
   1.320 +                critExtOIDsList,
   1.321 +                (PKIX_PL_Object *) state,
   1.322 +                pEkuChecker,
   1.323 +                plContext),
   1.324 +                PKIX_CERTCHAINCHECKERCREATEFAILED);
   1.325 +cleanup:
   1.326 +
   1.327 +        PKIX_DECREF(critExtOIDsList);
   1.328 +        PKIX_DECREF(state);
   1.329 +
   1.330 +        PKIX_RETURN(EKUCHECKER);
   1.331 +}

mercurial