tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_ekuchecker.c (10309B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_ekuchecker.c
      6 *
      7 * User Defined ExtenedKeyUsage Function Definitions
      8 *
      9 */
     10 
     11 #include "pkix_ekuchecker.h"
     12 
     13 SECOidTag ekuOidStrings[] = {
     14    PKIX_KEY_USAGE_SERVER_AUTH_OID,
     15    PKIX_KEY_USAGE_CLIENT_AUTH_OID,
     16    PKIX_KEY_USAGE_CODE_SIGN_OID,
     17    PKIX_KEY_USAGE_EMAIL_PROTECT_OID,
     18    PKIX_KEY_USAGE_TIME_STAMP_OID,
     19    PKIX_KEY_USAGE_OCSP_RESPONDER_OID,
     20    PKIX_UNKNOWN_OID
     21 };
     22 
     23 typedef struct pkix_EkuCheckerStruct {
     24    PKIX_List *requiredExtKeyUsageOids;
     25    PKIX_PL_OID *ekuOID;
     26 } pkix_EkuChecker;
     27 
     28 
     29 /*
     30 * FUNCTION: pkix_EkuChecker_Destroy
     31 * (see comments for PKIX_DestructorCallback in pkix_pl_system.h)
     32 */
     33 static PKIX_Error *
     34 pkix_EkuChecker_Destroy(
     35        PKIX_PL_Object *object,
     36        void *plContext)
     37 {
     38        pkix_EkuChecker *ekuCheckerState = NULL;
     39 
     40        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy");
     41        PKIX_NULLCHECK_ONE(object);
     42 
     43        PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext),
     44                    PKIX_OBJECTNOTANEKUCHECKERSTATE);
     45 
     46        ekuCheckerState = (pkix_EkuChecker *)object;
     47 
     48        PKIX_DECREF(ekuCheckerState->ekuOID);
     49        PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids);
     50 
     51 cleanup:
     52 
     53        PKIX_RETURN(EKUCHECKER);
     54 }
     55 
     56 /*
     57 * FUNCTION: pkix_EkuChecker_RegisterSelf
     58 *
     59 * DESCRIPTION:
     60 *  Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related
     61 *  functions with systemClasses[]
     62 *
     63 * THREAD SAFETY:
     64 *  Not Thread Safe - for performance and complexity reasons
     65 *
     66 *  Since this function is only called by PKIX_PL_Initialize, which should
     67 *  only be called once, it is acceptable that this function is not
     68 *  thread-safe.
     69 */
     70 PKIX_Error *
     71 pkix_EkuChecker_RegisterSelf(void *plContext)
     72 {
     73        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
     74        pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE];
     75 
     76        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf");
     77 
     78        entry->description = "EkuChecker";
     79        entry->typeObjectSize = sizeof(pkix_EkuChecker);
     80        entry->destructor = pkix_EkuChecker_Destroy;
     81 
     82        PKIX_RETURN(EKUCHECKER);
     83 }
     84 
     85 /*
     86 * FUNCTION: pkix_EkuChecker_Create
     87 * DESCRIPTION:
     88 *
     89 *  Creates a new Extend Key Usage CheckerState using "params" to retrieve
     90 *  application specified EKU for verification and stores it at "pState".
     91 *
     92 * PARAMETERS:
     93 *  "params"
     94 *      a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
     95 *      Extended Key Usage OIDs specified by application can be retrieved for
     96 *      verification.
     97 *  "pState"
     98 *      Address where state pointer will be stored. Must be non-NULL.
     99 *  "plContext"
    100 *      Platform-specific context pointer.
    101 * THREAD SAFETY:
    102 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    103 * RETURNS:
    104 *  Returns NULL if the function succeeds.
    105 *  Returns a UserDefinedModules Error if the function fails in a
    106 *      non-fatal way.
    107 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    108 */
    109 static PKIX_Error *
    110 pkix_EkuChecker_Create(
    111        PKIX_ProcessingParams *params,
    112        pkix_EkuChecker **pState,
    113        void *plContext)
    114 {
    115        pkix_EkuChecker *state = NULL;
    116        PKIX_CertSelector *certSelector = NULL;
    117        PKIX_ComCertSelParams *comCertSelParams = NULL;
    118        PKIX_List *requiredOids = NULL;
    119 
    120        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create");
    121        PKIX_NULLCHECK_TWO(params, pState);
    122 
    123        PKIX_CHECK(PKIX_PL_Object_Alloc
    124                    (PKIX_EKUCHECKER_TYPE,
    125                    sizeof (pkix_EkuChecker),
    126                    (PKIX_PL_Object **)&state,
    127                    plContext),
    128                    PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT);
    129 
    130 
    131        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
    132                    (params, &certSelector, plContext),
    133                    PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
    134 
    135        if (certSelector != NULL) {
    136 
    137            /* Get initial EKU OIDs from ComCertSelParams, if set */
    138            PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
    139                       (certSelector, &comCertSelParams, plContext),
    140                       PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
    141 
    142            if (comCertSelParams != NULL) {
    143                PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
    144                           (comCertSelParams, &requiredOids, plContext),
    145                           PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
    146 
    147            }
    148        }
    149 
    150        PKIX_CHECK(PKIX_PL_OID_Create
    151                    (PKIX_EXTENDEDKEYUSAGE_OID,
    152                    &state->ekuOID,
    153                    plContext),
    154                    PKIX_OIDCREATEFAILED);
    155 
    156        state->requiredExtKeyUsageOids = requiredOids;
    157        requiredOids = NULL;
    158        *pState = state;
    159        state = NULL;
    160 
    161 cleanup:
    162 
    163        PKIX_DECREF(certSelector);
    164        PKIX_DECREF(comCertSelParams);
    165        PKIX_DECREF(requiredOids);
    166        PKIX_DECREF(state);
    167 
    168        PKIX_RETURN(EKUCHECKER);
    169 }
    170 
    171 /*
    172 * FUNCTION: pkix_EkuChecker_Check
    173 * DESCRIPTION:
    174 *
    175 *  This function determines the Extended Key Usage OIDs specified by the
    176 *  application is included in the Extended Key Usage OIDs of this "cert".
    177 *
    178 * PARAMETERS:
    179 *  "checker"
    180 *      Address of CertChainChecker which has the state data.
    181 *      Must be non-NULL.
    182 *  "cert"
    183 *      Address of Certificate that is to be validated. Must be non-NULL.
    184 *  "unresolvedCriticalExtensions"
    185 *      A List OIDs. The OID for Extended Key Usage is removed.
    186 *  "plContext"
    187 *      Platform-specific context pointer.
    188 * THREAD SAFETY:
    189 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    190 * RETURNS:
    191 *  Returns NULL if the function succeeds.
    192 *  Returns a UserDefinedModules Error if the function fails in
    193 *      a non-fatal way.
    194 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    195 */
    196 static PKIX_Error *
    197 pkix_EkuChecker_Check(
    198        PKIX_CertChainChecker *checker,
    199        PKIX_PL_Cert *cert,
    200        PKIX_List *unresolvedCriticalExtensions,
    201        void **pNBIOContext,
    202        void *plContext)
    203 {
    204        pkix_EkuChecker *state = NULL;
    205        PKIX_List *requiredExtKeyUsageList = NULL;
    206        PKIX_List *certExtKeyUsageList = NULL;
    207        PKIX_PL_OID *ekuOid = NULL;
    208        PKIX_Boolean isContained = PKIX_FALSE;
    209        PKIX_UInt32 numItems = 0;
    210        PKIX_UInt32 i;
    211        PKIX_Boolean checkResult = PKIX_TRUE;
    212 
    213        PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check");
    214        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
    215 
    216        *pNBIOContext = NULL; /* no non-blocking IO */
    217 
    218        PKIX_CHECK(
    219            PKIX_CertChainChecker_GetCertChainCheckerState
    220            (checker, (PKIX_PL_Object **)&state, plContext),
    221            PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
    222 
    223        requiredExtKeyUsageList = state->requiredExtKeyUsageOids;
    224        if (requiredExtKeyUsageList == NULL) {
    225            goto cleanup;
    226        }
    227 
    228        PKIX_CHECK(
    229            PKIX_List_GetLength(requiredExtKeyUsageList, &numItems,
    230                                plContext),
    231            PKIX_LISTGETLENGTHFAILED);
    232        if (numItems == 0) {
    233            goto cleanup;
    234        }
    235 
    236        PKIX_CHECK(
    237            PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList,
    238                                             plContext),
    239            PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
    240 
    241        if (certExtKeyUsageList == NULL) {
    242            goto cleanup;
    243        }
    244        
    245        for (i = 0; i < numItems; i++) {
    246            
    247            PKIX_CHECK(
    248                PKIX_List_GetItem(requiredExtKeyUsageList, i,
    249                                  (PKIX_PL_Object **)&ekuOid, plContext),
    250                PKIX_LISTGETITEMFAILED);
    251 
    252            PKIX_CHECK(
    253                pkix_List_Contains(certExtKeyUsageList,
    254                                   (PKIX_PL_Object *)ekuOid,
    255                                   &isContained,
    256                                   plContext),
    257                PKIX_LISTCONTAINSFAILED);
    258            
    259            PKIX_DECREF(ekuOid);
    260            if (isContained != PKIX_TRUE) {
    261                checkResult = PKIX_FALSE;
    262                goto cleanup;
    263            }
    264        }
    265 
    266 cleanup:
    267        if (!pkixErrorResult && checkResult == PKIX_FALSE) {
    268            pkixErrorReceived = PKIX_TRUE;
    269            pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED;
    270        }
    271        
    272        PKIX_DECREF(ekuOid);
    273        PKIX_DECREF(certExtKeyUsageList);
    274        PKIX_DECREF(state);
    275 
    276        PKIX_RETURN(EKUCHECKER);
    277 }
    278 
    279 /*
    280 * FUNCTION: pkix_EkuChecker_Initialize
    281 * (see comments in pkix_sample_modules.h)
    282 */
    283 PKIX_Error *
    284 PKIX_EkuChecker_Create(
    285        PKIX_ProcessingParams *params,
    286        PKIX_CertChainChecker **pEkuChecker,
    287        void *plContext)
    288 {
    289        pkix_EkuChecker *state = NULL;
    290        PKIX_List *critExtOIDsList = NULL;
    291 
    292        PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize");
    293        PKIX_NULLCHECK_ONE(params);
    294 
    295        /*
    296         * This function and functions in this file provide an example of how
    297         * an application defined checker can be hooked into libpkix.
    298         */
    299 
    300        PKIX_CHECK(pkix_EkuChecker_Create
    301                    (params, &state, plContext),
    302                    PKIX_EKUCHECKERSTATECREATEFAILED);
    303 
    304        PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext),
    305                    PKIX_LISTCREATEFAILED);
    306 
    307        PKIX_CHECK(PKIX_List_AppendItem
    308                    (critExtOIDsList,
    309                    (PKIX_PL_Object *)state->ekuOID,
    310                    plContext),
    311                    PKIX_LISTAPPENDITEMFAILED);
    312 
    313        PKIX_CHECK(PKIX_CertChainChecker_Create
    314                (pkix_EkuChecker_Check,
    315                PKIX_TRUE,                 /* forwardCheckingSupported */
    316                PKIX_FALSE,                /* forwardDirectionExpected */
    317                critExtOIDsList,
    318                (PKIX_PL_Object *) state,
    319                pEkuChecker,
    320                plContext),
    321                PKIX_CERTCHAINCHECKERCREATEFAILED);
    322 cleanup:
    323 
    324        PKIX_DECREF(critExtOIDsList);
    325        PKIX_DECREF(state);
    326 
    327        PKIX_RETURN(EKUCHECKER);
    328 }