1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,306 @@ 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_basicconstraintschecker.c 1.9 + * 1.10 + * Functions for basic constraints validation 1.11 + * 1.12 + */ 1.13 + 1.14 +#include "pkix_basicconstraintschecker.h" 1.15 + 1.16 +/* --Private-BasicConstraintsCheckerState-Functions------------------------- */ 1.17 + 1.18 +/* 1.19 + * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy 1.20 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 1.21 + */ 1.22 +static PKIX_Error * 1.23 +pkix_BasicConstraintsCheckerState_Destroy( 1.24 + PKIX_PL_Object *object, 1.25 + void *plContext) 1.26 +{ 1.27 + pkix_BasicConstraintsCheckerState *state = NULL; 1.28 + 1.29 + PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, 1.30 + "pkix_BasicConstraintsCheckerState_Destroy"); 1.31 + 1.32 + PKIX_NULLCHECK_ONE(object); 1.33 + 1.34 + /* Check that this object is a basic constraints checker state */ 1.35 + PKIX_CHECK(pkix_CheckType 1.36 + (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext), 1.37 + PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE); 1.38 + 1.39 + state = (pkix_BasicConstraintsCheckerState *)object; 1.40 + 1.41 + PKIX_DECREF(state->basicConstraintsOID); 1.42 + 1.43 +cleanup: 1.44 + 1.45 + PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); 1.46 +} 1.47 + 1.48 +/* 1.49 + * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf 1.50 + * DESCRIPTION: 1.51 + * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] 1.52 + * THREAD SAFETY: 1.53 + * Not Thread Safe - for performance and complexity reasons 1.54 + * 1.55 + * Since this function is only called by PKIX_PL_Initialize, which should 1.56 + * only be called once, it is acceptable that this function is not 1.57 + * thread-safe. 1.58 + */ 1.59 +PKIX_Error * 1.60 +pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext) 1.61 +{ 1.62 + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1.63 + pkix_ClassTable_Entry entry; 1.64 + 1.65 + PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, 1.66 + "pkix_BasicConstraintsCheckerState_RegisterSelf"); 1.67 + 1.68 + entry.description = "BasicConstraintsCheckerState"; 1.69 + entry.objCounter = 0; 1.70 + entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState); 1.71 + entry.destructor = pkix_BasicConstraintsCheckerState_Destroy; 1.72 + entry.equalsFunction = NULL; 1.73 + entry.hashcodeFunction = NULL; 1.74 + entry.toStringFunction = NULL; 1.75 + entry.comparator = NULL; 1.76 + entry.duplicateFunction = NULL; 1.77 + 1.78 + systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry; 1.79 + 1.80 + PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); 1.81 +} 1.82 + 1.83 +/* 1.84 + * FUNCTION: pkix_BasicConstraintsCheckerState_Create 1.85 + * DESCRIPTION: 1.86 + * 1.87 + * Creates a new BasicConstraintsCheckerState using the number of certs in 1.88 + * the chain represented by "certsRemaining" and stores it at "pState". 1.89 + * 1.90 + * PARAMETERS: 1.91 + * "certsRemaining" 1.92 + * Number of certificates in the chain. 1.93 + * "pState" 1.94 + * Address where object pointer will be stored. Must be non-NULL. 1.95 + * "plContext" 1.96 + * Platform-specific context pointer. 1.97 + * THREAD SAFETY: 1.98 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.99 + * RETURNS: 1.100 + * Returns NULL if the function succeeds. 1.101 + * Returns a BasicConstraintsCheckerState Error if the function fails in a 1.102 + * non-fatal way. 1.103 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.104 + */ 1.105 +static PKIX_Error * 1.106 +pkix_BasicConstraintsCheckerState_Create( 1.107 + PKIX_UInt32 certsRemaining, 1.108 + pkix_BasicConstraintsCheckerState **pState, 1.109 + void *plContext) 1.110 +{ 1.111 + pkix_BasicConstraintsCheckerState *state = NULL; 1.112 + 1.113 + PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, 1.114 + "pkix_BasicConstraintsCheckerState_Create"); 1.115 + 1.116 + PKIX_NULLCHECK_ONE(pState); 1.117 + 1.118 + PKIX_CHECK(PKIX_PL_Object_Alloc 1.119 + (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, 1.120 + sizeof (pkix_BasicConstraintsCheckerState), 1.121 + (PKIX_PL_Object **)&state, 1.122 + plContext), 1.123 + PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT); 1.124 + 1.125 + /* initialize fields */ 1.126 + state->certsRemaining = certsRemaining; 1.127 + state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT; 1.128 + 1.129 + PKIX_CHECK(PKIX_PL_OID_Create 1.130 + (PKIX_BASICCONSTRAINTS_OID, 1.131 + &state->basicConstraintsOID, 1.132 + plContext), 1.133 + PKIX_OIDCREATEFAILED); 1.134 + 1.135 + *pState = state; 1.136 + state = NULL; 1.137 + 1.138 +cleanup: 1.139 + 1.140 + PKIX_DECREF(state); 1.141 + 1.142 + PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); 1.143 +} 1.144 + 1.145 +/* --Private-BasicConstraintsChecker-Functions------------------------------ */ 1.146 + 1.147 +/* 1.148 + * FUNCTION: pkix_BasicConstraintsChecker_Check 1.149 + * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) 1.150 + */ 1.151 +PKIX_Error * 1.152 +pkix_BasicConstraintsChecker_Check( 1.153 + PKIX_CertChainChecker *checker, 1.154 + PKIX_PL_Cert *cert, 1.155 + PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */ 1.156 + void **pNBIOContext, 1.157 + void *plContext) 1.158 +{ 1.159 + PKIX_PL_CertBasicConstraints *basicConstraints = NULL; 1.160 + pkix_BasicConstraintsCheckerState *state = NULL; 1.161 + PKIX_Boolean caFlag = PKIX_FALSE; 1.162 + PKIX_Int32 pathLength = 0; 1.163 + PKIX_Int32 maxPathLength_now; 1.164 + PKIX_Boolean isSelfIssued = PKIX_FALSE; 1.165 + 1.166 + PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check"); 1.167 + PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); 1.168 + 1.169 + *pNBIOContext = NULL; /* we never block on pending I/O */ 1.170 + 1.171 + PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState 1.172 + (checker, (PKIX_PL_Object **)&state, plContext), 1.173 + PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); 1.174 + 1.175 + state->certsRemaining--; 1.176 + 1.177 + if (state->certsRemaining != 0) { 1.178 + 1.179 + PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints 1.180 + (cert, &basicConstraints, plContext), 1.181 + PKIX_CERTGETBASICCONSTRAINTSFAILED); 1.182 + 1.183 + /* get CA Flag and path length */ 1.184 + if (basicConstraints != NULL) { 1.185 + PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag 1.186 + (basicConstraints, 1.187 + &caFlag, 1.188 + plContext), 1.189 + PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); 1.190 + 1.191 + if (caFlag == PKIX_TRUE) { 1.192 + PKIX_CHECK 1.193 + (PKIX_PL_BasicConstraints_GetPathLenConstraint 1.194 + (basicConstraints, 1.195 + &pathLength, 1.196 + plContext), 1.197 + PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED); 1.198 + } 1.199 + 1.200 + }else{ 1.201 + caFlag = PKIX_FALSE; 1.202 + pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT; 1.203 + } 1.204 + 1.205 + PKIX_CHECK(pkix_IsCertSelfIssued 1.206 + (cert, 1.207 + &isSelfIssued, 1.208 + plContext), 1.209 + PKIX_ISCERTSELFISSUEDFAILED); 1.210 + 1.211 + maxPathLength_now = state->maxPathLength; 1.212 + 1.213 + if (isSelfIssued != PKIX_TRUE) { 1.214 + 1.215 + /* Not last CA Cert, but maxPathLength is down to zero */ 1.216 + if (maxPathLength_now == 0) { 1.217 + PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN); 1.218 + } 1.219 + 1.220 + if (caFlag == PKIX_FALSE) { 1.221 + PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA); 1.222 + } 1.223 + 1.224 + if (maxPathLength_now > 0) { /* can be unlimited (-1) */ 1.225 + maxPathLength_now--; 1.226 + } 1.227 + 1.228 + } 1.229 + 1.230 + if (caFlag == PKIX_TRUE) { 1.231 + if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){ 1.232 + maxPathLength_now = pathLength; 1.233 + } else { 1.234 + /* If pathLength is not specified, don't set */ 1.235 + if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) { 1.236 + maxPathLength_now = 1.237 + (maxPathLength_now > pathLength)? 1.238 + pathLength:maxPathLength_now; 1.239 + } 1.240 + } 1.241 + } 1.242 + 1.243 + state->maxPathLength = maxPathLength_now; 1.244 + } 1.245 + 1.246 + /* Remove Basic Constraints Extension OID from list */ 1.247 + if (unresolvedCriticalExtensions != NULL) { 1.248 + 1.249 + PKIX_CHECK(pkix_List_Remove 1.250 + (unresolvedCriticalExtensions, 1.251 + (PKIX_PL_Object *) state->basicConstraintsOID, 1.252 + plContext), 1.253 + PKIX_LISTREMOVEFAILED); 1.254 + } 1.255 + 1.256 + 1.257 + PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState 1.258 + (checker, (PKIX_PL_Object *)state, plContext), 1.259 + PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); 1.260 + 1.261 + 1.262 +cleanup: 1.263 + PKIX_DECREF(state); 1.264 + PKIX_DECREF(basicConstraints); 1.265 + PKIX_RETURN(CERTCHAINCHECKER); 1.266 + 1.267 +} 1.268 + 1.269 +/* 1.270 + * FUNCTION: pkix_BasicConstraintsChecker_Initialize 1.271 + * DESCRIPTION: 1.272 + * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] 1.273 + * THREAD SAFETY: 1.274 + * Not Thread Safe - for performance and complexity reasons 1.275 + * 1.276 + * Since this function is only called by PKIX_PL_Initialize, which should 1.277 + * only be called once, it is acceptable that this function is not 1.278 + * thread-safe. 1.279 + */ 1.280 +PKIX_Error * 1.281 +pkix_BasicConstraintsChecker_Initialize( 1.282 + PKIX_UInt32 certsRemaining, 1.283 + PKIX_CertChainChecker **pChecker, 1.284 + void *plContext) 1.285 +{ 1.286 + pkix_BasicConstraintsCheckerState *state = NULL; 1.287 + 1.288 + PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize"); 1.289 + PKIX_NULLCHECK_ONE(pChecker); 1.290 + 1.291 + PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create 1.292 + (certsRemaining, &state, plContext), 1.293 + PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED); 1.294 + 1.295 + PKIX_CHECK(PKIX_CertChainChecker_Create 1.296 + (pkix_BasicConstraintsChecker_Check, 1.297 + PKIX_FALSE, 1.298 + PKIX_FALSE, 1.299 + NULL, 1.300 + (PKIX_PL_Object *)state, 1.301 + pChecker, 1.302 + plContext), 1.303 + PKIX_CERTCHAINCHECKERCHECKFAILED); 1.304 + 1.305 +cleanup: 1.306 + PKIX_DECREF(state); 1.307 + 1.308 + PKIX_RETURN(CERTCHAINCHECKER); 1.309 +}