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 }