1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,438 @@ 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_defaultcrlchecker.c 1.9 + * 1.10 + * Functions for default CRL Checkers 1.11 + * 1.12 + */ 1.13 +#include "pkix.h" 1.14 +#include "pkix_crlchecker.h" 1.15 +#include "pkix_tools.h" 1.16 + 1.17 +/* --Private-CRLChecker-Data-and-Types------------------------------- */ 1.18 + 1.19 +typedef struct pkix_CrlCheckerStruct { 1.20 + /* RevocationMethod is the super class of CrlChecker. */ 1.21 + pkix_RevocationMethod method; 1.22 + PKIX_List *certStores; /* list of CertStore */ 1.23 + PKIX_PL_VerifyCallback crlVerifyFn; 1.24 +} pkix_CrlChecker; 1.25 + 1.26 + 1.27 +/* --Private-CRLChecker-Functions----------------------------------- */ 1.28 + 1.29 +/* 1.30 + * FUNCTION: pkix_CrlCheckerstate_Destroy 1.31 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 1.32 + */ 1.33 +static PKIX_Error * 1.34 +pkix_CrlChecker_Destroy( 1.35 + PKIX_PL_Object *object, 1.36 + void *plContext) 1.37 +{ 1.38 + pkix_CrlChecker *state = NULL; 1.39 + 1.40 + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy"); 1.41 + PKIX_NULLCHECK_ONE(object); 1.42 + 1.43 + /* Check that this object is a default CRL checker state */ 1.44 + PKIX_CHECK( 1.45 + pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext), 1.46 + PKIX_OBJECTNOTCRLCHECKER); 1.47 + 1.48 + state = (pkix_CrlChecker *)object; 1.49 + 1.50 + PKIX_DECREF(state->certStores); 1.51 + 1.52 +cleanup: 1.53 + 1.54 + PKIX_RETURN(CRLCHECKER); 1.55 +} 1.56 + 1.57 +/* 1.58 + * FUNCTION: pkix_CrlChecker_RegisterSelf 1.59 + * 1.60 + * DESCRIPTION: 1.61 + * Registers PKIX_CRLCHECKER_TYPE and its related functions 1.62 + * with systemClasses[] 1.63 + * 1.64 + * THREAD SAFETY: 1.65 + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.66 + * 1.67 + * Since this function is only called by PKIX_PL_Initialize, which should 1.68 + * only be called once, it is acceptable that this function is not 1.69 + * thread-safe. 1.70 + */ 1.71 +PKIX_Error * 1.72 +pkix_CrlChecker_RegisterSelf(void *plContext) 1.73 +{ 1.74 + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1.75 + pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE]; 1.76 + 1.77 + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf"); 1.78 + 1.79 + entry->description = "CRLChecker"; 1.80 + entry->typeObjectSize = sizeof(pkix_CrlChecker); 1.81 + entry->destructor = pkix_CrlChecker_Destroy; 1.82 + 1.83 + PKIX_RETURN(CRLCHECKER); 1.84 +} 1.85 + 1.86 +/* 1.87 + * FUNCTION: pkix_CrlChecker_Create 1.88 + * 1.89 + * DESCRIPTION: 1.90 + * Allocate and initialize CRLChecker state data. 1.91 + * 1.92 + * PARAMETERS 1.93 + * "certStores" 1.94 + * Address of CertStore List to be stored in state. Must be non-NULL. 1.95 + * "testDate" 1.96 + * Address of PKIX_PL_Date to be checked. May be NULL. 1.97 + * "trustedPubKey" 1.98 + * Trusted Anchor Public Key for verifying first Cert in the chain. 1.99 + * Must be non-NULL. 1.100 + * "certsRemaining" 1.101 + * Number of certificates remaining in the chain. 1.102 + * "nistCRLPolicyEnabled" 1.103 + * If enabled, enforce nist crl policy. 1.104 + * "pChecker" 1.105 + * Address of CRLChecker that is returned. Must be non-NULL. 1.106 + * "plContext" 1.107 + * Platform-specific context pointer. 1.108 + * 1.109 + * THREAD SAFETY: 1.110 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.111 + * 1.112 + * RETURNS: 1.113 + * Returns NULL if the function succeeds. 1.114 + * Returns a DefaultCrlChecker Error if the function fails in a 1.115 + * non-fatal way. 1.116 + * Returns a Fatal Error 1.117 + */ 1.118 +PKIX_Error * 1.119 +pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType, 1.120 + PKIX_UInt32 flags, 1.121 + PKIX_UInt32 priority, 1.122 + pkix_LocalRevocationCheckFn localRevChecker, 1.123 + pkix_ExternalRevocationCheckFn externalRevChecker, 1.124 + PKIX_List *certStores, 1.125 + PKIX_PL_VerifyCallback crlVerifyFn, 1.126 + pkix_RevocationMethod **pChecker, 1.127 + void *plContext) 1.128 +{ 1.129 + pkix_CrlChecker *crlChecker = NULL; 1.130 + 1.131 + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create"); 1.132 + PKIX_NULLCHECK_TWO(certStores, pChecker); 1.133 + 1.134 + PKIX_CHECK(PKIX_PL_Object_Alloc 1.135 + (PKIX_CRLCHECKER_TYPE, 1.136 + sizeof (pkix_CrlChecker), 1.137 + (PKIX_PL_Object **)&crlChecker, 1.138 + plContext), 1.139 + PKIX_COULDNOTCREATECRLCHECKEROBJECT); 1.140 + 1.141 + pkixErrorResult = pkix_RevocationMethod_Init( 1.142 + (pkix_RevocationMethod*)crlChecker, methodType, flags, priority, 1.143 + localRevChecker, externalRevChecker, plContext); 1.144 + if (pkixErrorResult) { 1.145 + goto cleanup; 1.146 + } 1.147 + 1.148 + /* Initialize fields */ 1.149 + PKIX_INCREF(certStores); 1.150 + crlChecker->certStores = certStores; 1.151 + 1.152 + crlChecker->crlVerifyFn = crlVerifyFn; 1.153 + *pChecker = (pkix_RevocationMethod*)crlChecker; 1.154 + crlChecker = NULL; 1.155 + 1.156 +cleanup: 1.157 + PKIX_DECREF(crlChecker); 1.158 + 1.159 + PKIX_RETURN(CRLCHECKER); 1.160 +} 1.161 + 1.162 +/* --Private-CRLChecker-Functions------------------------------------ */ 1.163 + 1.164 +/* 1.165 + * FUNCTION: pkix_CrlChecker_CheckLocal 1.166 + * 1.167 + * DESCRIPTION: 1.168 + * Check if the Cert has been revoked based the CRLs data. This function 1.169 + * maintains the checker state to be current. 1.170 + * 1.171 + * PARAMETERS 1.172 + * "checker" 1.173 + * Address of CertChainChecker which has the state data. 1.174 + * Must be non-NULL. 1.175 + * "cert" 1.176 + * Address of Certificate that is to be validated. Must be non-NULL. 1.177 + * "unreslvdCrtExts" 1.178 + * A List OIDs. Not **yet** used in this checker function. 1.179 + * "plContext" 1.180 + * Platform-specific context pointer. 1.181 + * 1.182 + * THREAD SAFETY: 1.183 + * Not Thread Safe 1.184 + * (see Thread Safety Definitions in Programmer's Guide) 1.185 + * 1.186 + * RETURNS: 1.187 + * Returns NULL if the function succeeds. 1.188 + * Returns a CertChainChecker Error if the function fails in a non-fatal way. 1.189 + * Returns a Fatal Error 1.190 + */ 1.191 +PKIX_Error * 1.192 +pkix_CrlChecker_CheckLocal( 1.193 + PKIX_PL_Cert *cert, 1.194 + PKIX_PL_Cert *issuer, 1.195 + PKIX_PL_Date *date, 1.196 + pkix_RevocationMethod *checkerObject, 1.197 + PKIX_ProcessingParams *procParams, 1.198 + PKIX_UInt32 methodFlags, 1.199 + PKIX_Boolean chainVerificationState, 1.200 + PKIX_RevocationStatus *pRevStatus, 1.201 + PKIX_UInt32 *pReasonCode, 1.202 + void *plContext) 1.203 +{ 1.204 + PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn; 1.205 + PKIX_CertStore *certStore = NULL; 1.206 + pkix_CrlChecker *state = NULL; 1.207 + PKIX_UInt32 crlStoreIndex = 0; 1.208 + PKIX_UInt32 numCrlStores = 0; 1.209 + PKIX_Boolean storeIsLocal = PKIX_FALSE; 1.210 + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; 1.211 + 1.212 + PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal"); 1.213 + PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject); 1.214 + 1.215 + state = (pkix_CrlChecker*)checkerObject; 1.216 + 1.217 + PKIX_CHECK( 1.218 + PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), 1.219 + PKIX_LISTGETLENGTHFAILED); 1.220 + 1.221 + for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { 1.222 + PKIX_CHECK( 1.223 + PKIX_List_GetItem(state->certStores, crlStoreIndex, 1.224 + (PKIX_PL_Object **)&certStore, 1.225 + plContext), 1.226 + PKIX_LISTGETITEMFAILED); 1.227 + 1.228 + PKIX_CHECK( 1.229 + PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, 1.230 + plContext), 1.231 + PKIX_CERTSTOREGETLOCALFLAGFAILED); 1.232 + if (storeIsLocal) { 1.233 + PKIX_CHECK( 1.234 + PKIX_CertStore_GetCrlCheckerFn(certStore, 1.235 + &storeCheckRevocationFn, 1.236 + plContext), 1.237 + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); 1.238 + 1.239 + if (storeCheckRevocationFn) { 1.240 + PKIX_CHECK( 1.241 + (*storeCheckRevocationFn)(certStore, cert, issuer, 1.242 + /* delay sig check if building 1.243 + * a chain by not specifying the time*/ 1.244 + chainVerificationState ? date : NULL, 1.245 + /* crl downloading is not done. */ 1.246 + PKIX_FALSE, 1.247 + pReasonCode, &revStatus, plContext), 1.248 + PKIX_CERTSTORECRLCHECKFAILED); 1.249 + if (revStatus == PKIX_RevStatus_Revoked) { 1.250 + break; 1.251 + } 1.252 + } 1.253 + } 1.254 + PKIX_DECREF(certStore); 1.255 + } /* while */ 1.256 + 1.257 +cleanup: 1.258 + *pRevStatus = revStatus; 1.259 + PKIX_DECREF(certStore); 1.260 + 1.261 + PKIX_RETURN(CERTCHAINCHECKER); 1.262 +} 1.263 + 1.264 +/* 1.265 + * FUNCTION: pkix_CrlChecker_CheckRemote 1.266 + * 1.267 + * DESCRIPTION: 1.268 + * Check if the Cert has been revoked based the CRLs data. This function 1.269 + * maintains the checker state to be current. 1.270 + * 1.271 + * PARAMETERS 1.272 + * "checker" 1.273 + * Address of CertChainChecker which has the state data. 1.274 + * Must be non-NULL. 1.275 + * "cert" 1.276 + * Address of Certificate that is to be validated. Must be non-NULL. 1.277 + * "unreslvdCrtExts" 1.278 + * A List OIDs. Not **yet** used in this checker function. 1.279 + * "plContext" 1.280 + * Platform-specific context pointer. 1.281 + * 1.282 + * THREAD SAFETY: 1.283 + * Not Thread Safe 1.284 + * (see Thread Safety Definitions in Programmer's Guide) 1.285 + * 1.286 + * RETURNS: 1.287 + * Returns NULL if the function succeeds. 1.288 + * Returns a CertChainChecker Error if the function fails in a non-fatal way. 1.289 + * Returns a Fatal Error 1.290 + */ 1.291 +PKIX_Error * 1.292 +pkix_CrlChecker_CheckExternal( 1.293 + PKIX_PL_Cert *cert, 1.294 + PKIX_PL_Cert *issuer, 1.295 + PKIX_PL_Date *date, 1.296 + pkix_RevocationMethod *checkerObject, 1.297 + PKIX_ProcessingParams *procParams, 1.298 + PKIX_UInt32 methodFlags, 1.299 + PKIX_RevocationStatus *pRevStatus, 1.300 + PKIX_UInt32 *pReasonCode, 1.301 + void **pNBIOContext, 1.302 + void *plContext) 1.303 +{ 1.304 + PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL; 1.305 + PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL; 1.306 + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; 1.307 + PKIX_CertStore *certStore = NULL; 1.308 + PKIX_CertStore *localStore = NULL; 1.309 + PKIX_CRLSelector *crlSelector = NULL; 1.310 + PKIX_PL_X500Name *issuerName = NULL; 1.311 + pkix_CrlChecker *state = NULL; 1.312 + PKIX_UInt32 crlStoreIndex = 0; 1.313 + PKIX_UInt32 numCrlStores = 0; 1.314 + PKIX_Boolean storeIsLocal = PKIX_FALSE; 1.315 + PKIX_List *crlList = NULL; 1.316 + PKIX_List *dpList = NULL; 1.317 + void *nbioContext = NULL; 1.318 + 1.319 + PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal"); 1.320 + PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext); 1.321 + 1.322 + nbioContext = *pNBIOContext; 1.323 + *pNBIOContext = NULL; /* prepare for Error exit */ 1.324 + 1.325 + state = (pkix_CrlChecker*)checkerObject; 1.326 + 1.327 + PKIX_CHECK( 1.328 + PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), 1.329 + PKIX_LISTGETLENGTHFAILED); 1.330 + 1.331 + /* Find a cert store that is capable of storing crls */ 1.332 + for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { 1.333 + PKIX_CHECK( 1.334 + PKIX_List_GetItem(state->certStores, crlStoreIndex, 1.335 + (PKIX_PL_Object **)&certStore, 1.336 + plContext), 1.337 + PKIX_LISTGETITEMFAILED); 1.338 + 1.339 + PKIX_CHECK( 1.340 + PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, 1.341 + plContext), 1.342 + PKIX_CERTSTOREGETLOCALFLAGFAILED); 1.343 + if (storeIsLocal) { 1.344 + PKIX_CHECK( 1.345 + PKIX_CertStore_GetImportCrlCallback(certStore, 1.346 + &storeImportCrlFn, 1.347 + plContext), 1.348 + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); 1.349 + 1.350 + PKIX_CHECK( 1.351 + PKIX_CertStore_GetCrlCheckerFn(certStore, 1.352 + &storeCheckRevocationFn, 1.353 + plContext), 1.354 + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); 1.355 + 1.356 + if (storeImportCrlFn && storeCheckRevocationFn) { 1.357 + localStore = certStore; 1.358 + certStore = NULL; 1.359 + break; 1.360 + } 1.361 + } 1.362 + PKIX_DECREF(certStore); 1.363 + } /* while */ 1.364 + 1.365 + /* Report unknown status if we can not check crl in one of the 1.366 + * local stores. */ 1.367 + if (!localStore) { 1.368 + PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND); 1.369 + } 1.370 + PKIX_CHECK( 1.371 + PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext), 1.372 + PKIX_CERTCHECKKEYUSAGEFAILED); 1.373 + PKIX_CHECK( 1.374 + PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext), 1.375 + PKIX_CERTGETCRLDPFAILED); 1.376 + if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) && 1.377 + (!dpList || !dpList->length)) { 1.378 + goto cleanup; 1.379 + } 1.380 + PKIX_CHECK( 1.381 + PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext), 1.382 + PKIX_CERTGETISSUERFAILED); 1.383 + PKIX_CHECK( 1.384 + PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext), 1.385 + PKIX_CRLCHECKERSETSELECTORFAILED); 1.386 + /* Fetch crl and store in a local cert store */ 1.387 + for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) { 1.388 + PKIX_CertStore_CRLCallback getCrlsFn; 1.389 + 1.390 + PKIX_CHECK( 1.391 + PKIX_List_GetItem(state->certStores, crlStoreIndex, 1.392 + (PKIX_PL_Object **)&certStore, 1.393 + plContext), 1.394 + PKIX_LISTGETITEMFAILED); 1.395 + 1.396 + PKIX_CHECK( 1.397 + PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn, 1.398 + plContext), 1.399 + PKIX_CERTSTOREGETCRLCALLBACKFAILED); 1.400 + 1.401 + PKIX_CHECK( 1.402 + (*getCrlsFn)(certStore, crlSelector, &nbioContext, 1.403 + &crlList, plContext), 1.404 + PKIX_GETCRLSFAILED); 1.405 + 1.406 + PKIX_CHECK( 1.407 + (*storeImportCrlFn)(localStore, issuerName, crlList, plContext), 1.408 + PKIX_CERTSTOREFAILTOIMPORTCRLLIST); 1.409 + 1.410 + PKIX_CHECK( 1.411 + (*storeCheckRevocationFn)(certStore, cert, issuer, date, 1.412 + /* done with crl downloading */ 1.413 + PKIX_TRUE, 1.414 + pReasonCode, &revStatus, plContext), 1.415 + PKIX_CERTSTORECRLCHECKFAILED); 1.416 + if (revStatus != PKIX_RevStatus_NoInfo) { 1.417 + break; 1.418 + } 1.419 + PKIX_DECREF(crlList); 1.420 + PKIX_DECREF(certStore); 1.421 + } /* while */ 1.422 + 1.423 +cleanup: 1.424 + /* Update return flags */ 1.425 + if (revStatus == PKIX_RevStatus_NoInfo && 1.426 + ((dpList && dpList->length > 0) || 1.427 + (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) && 1.428 + methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) { 1.429 + revStatus = PKIX_RevStatus_Revoked; 1.430 + } 1.431 + *pRevStatus = revStatus; 1.432 + 1.433 + PKIX_DECREF(dpList); 1.434 + PKIX_DECREF(crlList); 1.435 + PKIX_DECREF(certStore); 1.436 + PKIX_DECREF(issuerName); 1.437 + PKIX_DECREF(localStore); 1.438 + PKIX_DECREF(crlSelector); 1.439 + 1.440 + PKIX_RETURN(CERTCHAINCHECKER); 1.441 +}