1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,328 @@ 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_ekuchecker.c 1.9 + * 1.10 + * User Defined ExtenedKeyUsage Function Definitions 1.11 + * 1.12 + */ 1.13 + 1.14 +#include "pkix_ekuchecker.h" 1.15 + 1.16 +SECOidTag ekuOidStrings[] = { 1.17 + PKIX_KEY_USAGE_SERVER_AUTH_OID, 1.18 + PKIX_KEY_USAGE_CLIENT_AUTH_OID, 1.19 + PKIX_KEY_USAGE_CODE_SIGN_OID, 1.20 + PKIX_KEY_USAGE_EMAIL_PROTECT_OID, 1.21 + PKIX_KEY_USAGE_TIME_STAMP_OID, 1.22 + PKIX_KEY_USAGE_OCSP_RESPONDER_OID, 1.23 + PKIX_UNKNOWN_OID 1.24 +}; 1.25 + 1.26 +typedef struct pkix_EkuCheckerStruct { 1.27 + PKIX_List *requiredExtKeyUsageOids; 1.28 + PKIX_PL_OID *ekuOID; 1.29 +} pkix_EkuChecker; 1.30 + 1.31 + 1.32 +/* 1.33 + * FUNCTION: pkix_EkuChecker_Destroy 1.34 + * (see comments for PKIX_DestructorCallback in pkix_pl_system.h) 1.35 + */ 1.36 +static PKIX_Error * 1.37 +pkix_EkuChecker_Destroy( 1.38 + PKIX_PL_Object *object, 1.39 + void *plContext) 1.40 +{ 1.41 + pkix_EkuChecker *ekuCheckerState = NULL; 1.42 + 1.43 + PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy"); 1.44 + PKIX_NULLCHECK_ONE(object); 1.45 + 1.46 + PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext), 1.47 + PKIX_OBJECTNOTANEKUCHECKERSTATE); 1.48 + 1.49 + ekuCheckerState = (pkix_EkuChecker *)object; 1.50 + 1.51 + PKIX_DECREF(ekuCheckerState->ekuOID); 1.52 + PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids); 1.53 + 1.54 +cleanup: 1.55 + 1.56 + PKIX_RETURN(EKUCHECKER); 1.57 +} 1.58 + 1.59 +/* 1.60 + * FUNCTION: pkix_EkuChecker_RegisterSelf 1.61 + * 1.62 + * DESCRIPTION: 1.63 + * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related 1.64 + * functions with systemClasses[] 1.65 + * 1.66 + * THREAD SAFETY: 1.67 + * Not Thread Safe - for performance and complexity reasons 1.68 + * 1.69 + * Since this function is only called by PKIX_PL_Initialize, which should 1.70 + * only be called once, it is acceptable that this function is not 1.71 + * thread-safe. 1.72 + */ 1.73 +PKIX_Error * 1.74 +pkix_EkuChecker_RegisterSelf(void *plContext) 1.75 +{ 1.76 + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1.77 + pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE]; 1.78 + 1.79 + PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf"); 1.80 + 1.81 + entry->description = "EkuChecker"; 1.82 + entry->typeObjectSize = sizeof(pkix_EkuChecker); 1.83 + entry->destructor = pkix_EkuChecker_Destroy; 1.84 + 1.85 + PKIX_RETURN(EKUCHECKER); 1.86 +} 1.87 + 1.88 +/* 1.89 + * FUNCTION: pkix_EkuChecker_Create 1.90 + * DESCRIPTION: 1.91 + * 1.92 + * Creates a new Extend Key Usage CheckerState using "params" to retrieve 1.93 + * application specified EKU for verification and stores it at "pState". 1.94 + * 1.95 + * PARAMETERS: 1.96 + * "params" 1.97 + * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of 1.98 + * Extended Key Usage OIDs specified by application can be retrieved for 1.99 + * verification. 1.100 + * "pState" 1.101 + * Address where state pointer will be stored. Must be non-NULL. 1.102 + * "plContext" 1.103 + * Platform-specific context pointer. 1.104 + * THREAD SAFETY: 1.105 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.106 + * RETURNS: 1.107 + * Returns NULL if the function succeeds. 1.108 + * Returns a UserDefinedModules Error if the function fails in a 1.109 + * non-fatal way. 1.110 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.111 + */ 1.112 +static PKIX_Error * 1.113 +pkix_EkuChecker_Create( 1.114 + PKIX_ProcessingParams *params, 1.115 + pkix_EkuChecker **pState, 1.116 + void *plContext) 1.117 +{ 1.118 + pkix_EkuChecker *state = NULL; 1.119 + PKIX_CertSelector *certSelector = NULL; 1.120 + PKIX_ComCertSelParams *comCertSelParams = NULL; 1.121 + PKIX_List *requiredOids = NULL; 1.122 + 1.123 + PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create"); 1.124 + PKIX_NULLCHECK_TWO(params, pState); 1.125 + 1.126 + PKIX_CHECK(PKIX_PL_Object_Alloc 1.127 + (PKIX_EKUCHECKER_TYPE, 1.128 + sizeof (pkix_EkuChecker), 1.129 + (PKIX_PL_Object **)&state, 1.130 + plContext), 1.131 + PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT); 1.132 + 1.133 + 1.134 + PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints 1.135 + (params, &certSelector, plContext), 1.136 + PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); 1.137 + 1.138 + if (certSelector != NULL) { 1.139 + 1.140 + /* Get initial EKU OIDs from ComCertSelParams, if set */ 1.141 + PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams 1.142 + (certSelector, &comCertSelParams, plContext), 1.143 + PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); 1.144 + 1.145 + if (comCertSelParams != NULL) { 1.146 + PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage 1.147 + (comCertSelParams, &requiredOids, plContext), 1.148 + PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); 1.149 + 1.150 + } 1.151 + } 1.152 + 1.153 + PKIX_CHECK(PKIX_PL_OID_Create 1.154 + (PKIX_EXTENDEDKEYUSAGE_OID, 1.155 + &state->ekuOID, 1.156 + plContext), 1.157 + PKIX_OIDCREATEFAILED); 1.158 + 1.159 + state->requiredExtKeyUsageOids = requiredOids; 1.160 + requiredOids = NULL; 1.161 + *pState = state; 1.162 + state = NULL; 1.163 + 1.164 +cleanup: 1.165 + 1.166 + PKIX_DECREF(certSelector); 1.167 + PKIX_DECREF(comCertSelParams); 1.168 + PKIX_DECREF(requiredOids); 1.169 + PKIX_DECREF(state); 1.170 + 1.171 + PKIX_RETURN(EKUCHECKER); 1.172 +} 1.173 + 1.174 +/* 1.175 + * FUNCTION: pkix_EkuChecker_Check 1.176 + * DESCRIPTION: 1.177 + * 1.178 + * This function determines the Extended Key Usage OIDs specified by the 1.179 + * application is included in the Extended Key Usage OIDs of this "cert". 1.180 + * 1.181 + * PARAMETERS: 1.182 + * "checker" 1.183 + * Address of CertChainChecker which has the state data. 1.184 + * Must be non-NULL. 1.185 + * "cert" 1.186 + * Address of Certificate that is to be validated. Must be non-NULL. 1.187 + * "unresolvedCriticalExtensions" 1.188 + * A List OIDs. The OID for Extended Key Usage is removed. 1.189 + * "plContext" 1.190 + * Platform-specific context pointer. 1.191 + * THREAD SAFETY: 1.192 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.193 + * RETURNS: 1.194 + * Returns NULL if the function succeeds. 1.195 + * Returns a UserDefinedModules Error if the function fails in 1.196 + * a non-fatal way. 1.197 + * Returns a Fatal Error if the function fails in an unrecoverable way. 1.198 + */ 1.199 +static PKIX_Error * 1.200 +pkix_EkuChecker_Check( 1.201 + PKIX_CertChainChecker *checker, 1.202 + PKIX_PL_Cert *cert, 1.203 + PKIX_List *unresolvedCriticalExtensions, 1.204 + void **pNBIOContext, 1.205 + void *plContext) 1.206 +{ 1.207 + pkix_EkuChecker *state = NULL; 1.208 + PKIX_List *requiredExtKeyUsageList = NULL; 1.209 + PKIX_List *certExtKeyUsageList = NULL; 1.210 + PKIX_PL_OID *ekuOid = NULL; 1.211 + PKIX_Boolean isContained = PKIX_FALSE; 1.212 + PKIX_UInt32 numItems = 0; 1.213 + PKIX_UInt32 i; 1.214 + PKIX_Boolean checkResult = PKIX_TRUE; 1.215 + 1.216 + PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check"); 1.217 + PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); 1.218 + 1.219 + *pNBIOContext = NULL; /* no non-blocking IO */ 1.220 + 1.221 + PKIX_CHECK( 1.222 + PKIX_CertChainChecker_GetCertChainCheckerState 1.223 + (checker, (PKIX_PL_Object **)&state, plContext), 1.224 + PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); 1.225 + 1.226 + requiredExtKeyUsageList = state->requiredExtKeyUsageOids; 1.227 + if (requiredExtKeyUsageList == NULL) { 1.228 + goto cleanup; 1.229 + } 1.230 + 1.231 + PKIX_CHECK( 1.232 + PKIX_List_GetLength(requiredExtKeyUsageList, &numItems, 1.233 + plContext), 1.234 + PKIX_LISTGETLENGTHFAILED); 1.235 + if (numItems == 0) { 1.236 + goto cleanup; 1.237 + } 1.238 + 1.239 + PKIX_CHECK( 1.240 + PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList, 1.241 + plContext), 1.242 + PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); 1.243 + 1.244 + if (certExtKeyUsageList == NULL) { 1.245 + goto cleanup; 1.246 + } 1.247 + 1.248 + for (i = 0; i < numItems; i++) { 1.249 + 1.250 + PKIX_CHECK( 1.251 + PKIX_List_GetItem(requiredExtKeyUsageList, i, 1.252 + (PKIX_PL_Object **)&ekuOid, plContext), 1.253 + PKIX_LISTGETITEMFAILED); 1.254 + 1.255 + PKIX_CHECK( 1.256 + pkix_List_Contains(certExtKeyUsageList, 1.257 + (PKIX_PL_Object *)ekuOid, 1.258 + &isContained, 1.259 + plContext), 1.260 + PKIX_LISTCONTAINSFAILED); 1.261 + 1.262 + PKIX_DECREF(ekuOid); 1.263 + if (isContained != PKIX_TRUE) { 1.264 + checkResult = PKIX_FALSE; 1.265 + goto cleanup; 1.266 + } 1.267 + } 1.268 + 1.269 +cleanup: 1.270 + if (!pkixErrorResult && checkResult == PKIX_FALSE) { 1.271 + pkixErrorReceived = PKIX_TRUE; 1.272 + pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED; 1.273 + } 1.274 + 1.275 + PKIX_DECREF(ekuOid); 1.276 + PKIX_DECREF(certExtKeyUsageList); 1.277 + PKIX_DECREF(state); 1.278 + 1.279 + PKIX_RETURN(EKUCHECKER); 1.280 +} 1.281 + 1.282 +/* 1.283 + * FUNCTION: pkix_EkuChecker_Initialize 1.284 + * (see comments in pkix_sample_modules.h) 1.285 + */ 1.286 +PKIX_Error * 1.287 +PKIX_EkuChecker_Create( 1.288 + PKIX_ProcessingParams *params, 1.289 + PKIX_CertChainChecker **pEkuChecker, 1.290 + void *plContext) 1.291 +{ 1.292 + pkix_EkuChecker *state = NULL; 1.293 + PKIX_List *critExtOIDsList = NULL; 1.294 + 1.295 + PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize"); 1.296 + PKIX_NULLCHECK_ONE(params); 1.297 + 1.298 + /* 1.299 + * This function and functions in this file provide an example of how 1.300 + * an application defined checker can be hooked into libpkix. 1.301 + */ 1.302 + 1.303 + PKIX_CHECK(pkix_EkuChecker_Create 1.304 + (params, &state, plContext), 1.305 + PKIX_EKUCHECKERSTATECREATEFAILED); 1.306 + 1.307 + PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext), 1.308 + PKIX_LISTCREATEFAILED); 1.309 + 1.310 + PKIX_CHECK(PKIX_List_AppendItem 1.311 + (critExtOIDsList, 1.312 + (PKIX_PL_Object *)state->ekuOID, 1.313 + plContext), 1.314 + PKIX_LISTAPPENDITEMFAILED); 1.315 + 1.316 + PKIX_CHECK(PKIX_CertChainChecker_Create 1.317 + (pkix_EkuChecker_Check, 1.318 + PKIX_TRUE, /* forwardCheckingSupported */ 1.319 + PKIX_FALSE, /* forwardDirectionExpected */ 1.320 + critExtOIDsList, 1.321 + (PKIX_PL_Object *) state, 1.322 + pEkuChecker, 1.323 + plContext), 1.324 + PKIX_CERTCHAINCHECKERCREATEFAILED); 1.325 +cleanup: 1.326 + 1.327 + PKIX_DECREF(critExtOIDsList); 1.328 + PKIX_DECREF(state); 1.329 + 1.330 + PKIX_RETURN(EKUCHECKER); 1.331 +}