tor-browser

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

pkix_basicconstraintschecker.c (10455B)


      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_basicconstraintschecker.c
      6 *
      7 * Functions for basic constraints validation
      8 *
      9 */
     10 
     11 #include "pkix_basicconstraintschecker.h"
     12 
     13 /* --Private-BasicConstraintsCheckerState-Functions------------------------- */
     14 
     15 /*
     16 * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy
     17 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
     18 */
     19 static PKIX_Error *
     20 pkix_BasicConstraintsCheckerState_Destroy(
     21        PKIX_PL_Object *object,
     22        void *plContext)
     23 {
     24        pkix_BasicConstraintsCheckerState *state = NULL;
     25 
     26        PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
     27                    "pkix_BasicConstraintsCheckerState_Destroy");
     28 
     29        PKIX_NULLCHECK_ONE(object);
     30 
     31        /* Check that this object is a basic constraints checker state */
     32        PKIX_CHECK(pkix_CheckType
     33                (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext),
     34                PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE);
     35 
     36        state = (pkix_BasicConstraintsCheckerState *)object;
     37 
     38        PKIX_DECREF(state->basicConstraintsOID);
     39 
     40 cleanup:
     41 
     42        PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
     43 }
     44 
     45 /*
     46 * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf
     47 * DESCRIPTION:
     48 *  Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
     49 * THREAD SAFETY:
     50 *  Not Thread Safe - for performance and complexity reasons
     51 *
     52 *  Since this function is only called by PKIX_PL_Initialize, which should
     53 *  only be called once, it is acceptable that this function is not
     54 *  thread-safe.
     55 */
     56 PKIX_Error *
     57 pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext)
     58 {
     59        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
     60        pkix_ClassTable_Entry entry;
     61 
     62        PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
     63                "pkix_BasicConstraintsCheckerState_RegisterSelf");
     64 
     65        entry.description = "BasicConstraintsCheckerState";
     66        entry.objCounter = 0;
     67        entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState);
     68        entry.destructor = pkix_BasicConstraintsCheckerState_Destroy;
     69        entry.equalsFunction = NULL;
     70        entry.hashcodeFunction = NULL;
     71        entry.toStringFunction = NULL;
     72        entry.comparator = NULL;
     73        entry.duplicateFunction = NULL;
     74 
     75        systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry;
     76 
     77        PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
     78 }
     79 
     80 /*
     81 * FUNCTION: pkix_BasicConstraintsCheckerState_Create
     82 * DESCRIPTION:
     83 *
     84 *  Creates a new BasicConstraintsCheckerState using the number of certs in
     85 *  the chain represented by "certsRemaining" and stores it at "pState".
     86 *
     87 * PARAMETERS:
     88 *  "certsRemaining"
     89 *      Number of certificates in the chain.
     90 *  "pState"
     91 *      Address where object pointer will be stored. Must be non-NULL.
     92 *  "plContext"
     93 *      Platform-specific context pointer.
     94 * THREAD SAFETY:
     95 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     96 * RETURNS:
     97 *  Returns NULL if the function succeeds.
     98 *  Returns a BasicConstraintsCheckerState Error if the function fails in a
     99 *      non-fatal way.
    100 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    101 */
    102 static PKIX_Error *
    103 pkix_BasicConstraintsCheckerState_Create(
    104        PKIX_UInt32 certsRemaining,
    105        pkix_BasicConstraintsCheckerState **pState,
    106        void *plContext)
    107 {
    108        pkix_BasicConstraintsCheckerState *state = NULL;
    109 
    110        PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
    111                    "pkix_BasicConstraintsCheckerState_Create");
    112 
    113        PKIX_NULLCHECK_ONE(pState);
    114 
    115        PKIX_CHECK(PKIX_PL_Object_Alloc
    116                    (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE,
    117                    sizeof (pkix_BasicConstraintsCheckerState),
    118                    (PKIX_PL_Object **)&state,
    119                    plContext),
    120                    PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT);
    121 
    122        /* initialize fields */
    123        state->certsRemaining = certsRemaining;
    124        state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
    125 
    126        PKIX_CHECK(PKIX_PL_OID_Create
    127                    (PKIX_BASICCONSTRAINTS_OID,
    128                    &state->basicConstraintsOID,
    129                    plContext),
    130                    PKIX_OIDCREATEFAILED);
    131 
    132        *pState = state;
    133        state = NULL;
    134 
    135 cleanup:
    136 
    137        PKIX_DECREF(state);
    138 
    139        PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
    140 }
    141 
    142 /* --Private-BasicConstraintsChecker-Functions------------------------------ */
    143 
    144 /*
    145 * FUNCTION: pkix_BasicConstraintsChecker_Check
    146 * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
    147 */
    148 PKIX_Error *
    149 pkix_BasicConstraintsChecker_Check(
    150        PKIX_CertChainChecker *checker,
    151        PKIX_PL_Cert *cert,
    152        PKIX_List *unresolvedCriticalExtensions,  /* list of PKIX_PL_OID */
    153        void **pNBIOContext,
    154        void *plContext)
    155 {
    156        PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
    157        pkix_BasicConstraintsCheckerState *state = NULL;
    158        PKIX_Boolean caFlag = PKIX_FALSE;
    159        PKIX_Int32 pathLength = 0;
    160        PKIX_Int32 maxPathLength_now;
    161        PKIX_Boolean isSelfIssued = PKIX_FALSE;
    162 
    163        PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check");
    164        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
    165 
    166        *pNBIOContext = NULL; /* we never block on pending I/O */
    167 
    168        PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
    169                    (checker, (PKIX_PL_Object **)&state, plContext),
    170                    PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
    171 
    172        state->certsRemaining--;
    173 
    174        if (state->certsRemaining != 0) {
    175 
    176                PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
    177                    (cert, &basicConstraints, plContext),
    178                    PKIX_CERTGETBASICCONSTRAINTSFAILED);
    179 
    180                /* get CA Flag and path length */
    181                if (basicConstraints != NULL) {
    182                        PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
    183                            (basicConstraints,
    184                            &caFlag,
    185                            plContext),
    186                            PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
    187 
    188                if (caFlag == PKIX_TRUE) {
    189                        PKIX_CHECK
    190                            (PKIX_PL_BasicConstraints_GetPathLenConstraint
    191                            (basicConstraints,
    192                            &pathLength,
    193                            plContext),
    194                            PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
    195                }
    196 
    197                }else{
    198                        caFlag = PKIX_FALSE;
    199                        pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
    200                }
    201 
    202                PKIX_CHECK(pkix_IsCertSelfIssued
    203                        (cert,
    204                        &isSelfIssued,
    205                        plContext),
    206                        PKIX_ISCERTSELFISSUEDFAILED);
    207 
    208                maxPathLength_now = state->maxPathLength;
    209 
    210                if (isSelfIssued != PKIX_TRUE) {
    211 
    212                    /* Not last CA Cert, but maxPathLength is down to zero */
    213                    if (maxPathLength_now == 0) {
    214                        PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN);
    215                    }
    216 
    217                    if (caFlag == PKIX_FALSE) {
    218                        PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA);
    219                    }
    220 
    221                    if (maxPathLength_now > 0) { /* can be unlimited (-1) */
    222                        maxPathLength_now--;
    223                    }
    224 
    225                }
    226 
    227                if (caFlag == PKIX_TRUE) {
    228                    if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){
    229                            maxPathLength_now = pathLength;
    230                    } else {
    231                            /* If pathLength is not specified, don't set */
    232                        if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) {
    233                            maxPathLength_now =
    234                                    (maxPathLength_now > pathLength)?
    235                                    pathLength:maxPathLength_now;
    236                        }
    237                    }
    238                }
    239 
    240                state->maxPathLength = maxPathLength_now;
    241        }
    242 
    243        /* Remove Basic Constraints Extension OID from list */
    244        if (unresolvedCriticalExtensions != NULL) {
    245 
    246                PKIX_CHECK(pkix_List_Remove
    247                            (unresolvedCriticalExtensions,
    248                            (PKIX_PL_Object *) state->basicConstraintsOID,
    249                            plContext),
    250                            PKIX_LISTREMOVEFAILED);
    251        }
    252 
    253 
    254        PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
    255                    (checker, (PKIX_PL_Object *)state, plContext),
    256                    PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
    257 
    258 
    259 cleanup:
    260        PKIX_DECREF(state);
    261        PKIX_DECREF(basicConstraints);
    262        PKIX_RETURN(CERTCHAINCHECKER);
    263 
    264 }
    265 
    266 /*
    267 * FUNCTION: pkix_BasicConstraintsChecker_Initialize
    268 * DESCRIPTION:
    269 *  Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
    270 * THREAD SAFETY:
    271 *  Not Thread Safe - for performance and complexity reasons
    272 *
    273 *  Since this function is only called by PKIX_PL_Initialize, which should
    274 *  only be called once, it is acceptable that this function is not
    275 *  thread-safe.
    276 */
    277 PKIX_Error *
    278 pkix_BasicConstraintsChecker_Initialize(
    279        PKIX_UInt32 certsRemaining,
    280        PKIX_CertChainChecker **pChecker,
    281        void *plContext)
    282 {
    283        pkix_BasicConstraintsCheckerState *state = NULL;
    284 
    285        PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize");
    286        PKIX_NULLCHECK_ONE(pChecker);
    287 
    288        PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create
    289                    (certsRemaining, &state, plContext),
    290                    PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED);
    291 
    292        PKIX_CHECK(PKIX_CertChainChecker_Create
    293                    (pkix_BasicConstraintsChecker_Check,
    294                    PKIX_FALSE,
    295                    PKIX_FALSE,
    296                    NULL,
    297                    (PKIX_PL_Object *)state,
    298                    pChecker,
    299                    plContext),
    300                    PKIX_CERTCHAINCHECKERCHECKFAILED);
    301 
    302 cleanup:
    303        PKIX_DECREF(state);
    304 
    305        PKIX_RETURN(CERTCHAINCHECKER);
    306 }