pkix_ekuchecker.c (10309B)
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_ekuchecker.c 6 * 7 * User Defined ExtenedKeyUsage Function Definitions 8 * 9 */ 10 11 #include "pkix_ekuchecker.h" 12 13 SECOidTag ekuOidStrings[] = { 14 PKIX_KEY_USAGE_SERVER_AUTH_OID, 15 PKIX_KEY_USAGE_CLIENT_AUTH_OID, 16 PKIX_KEY_USAGE_CODE_SIGN_OID, 17 PKIX_KEY_USAGE_EMAIL_PROTECT_OID, 18 PKIX_KEY_USAGE_TIME_STAMP_OID, 19 PKIX_KEY_USAGE_OCSP_RESPONDER_OID, 20 PKIX_UNKNOWN_OID 21 }; 22 23 typedef struct pkix_EkuCheckerStruct { 24 PKIX_List *requiredExtKeyUsageOids; 25 PKIX_PL_OID *ekuOID; 26 } pkix_EkuChecker; 27 28 29 /* 30 * FUNCTION: pkix_EkuChecker_Destroy 31 * (see comments for PKIX_DestructorCallback in pkix_pl_system.h) 32 */ 33 static PKIX_Error * 34 pkix_EkuChecker_Destroy( 35 PKIX_PL_Object *object, 36 void *plContext) 37 { 38 pkix_EkuChecker *ekuCheckerState = NULL; 39 40 PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy"); 41 PKIX_NULLCHECK_ONE(object); 42 43 PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext), 44 PKIX_OBJECTNOTANEKUCHECKERSTATE); 45 46 ekuCheckerState = (pkix_EkuChecker *)object; 47 48 PKIX_DECREF(ekuCheckerState->ekuOID); 49 PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids); 50 51 cleanup: 52 53 PKIX_RETURN(EKUCHECKER); 54 } 55 56 /* 57 * FUNCTION: pkix_EkuChecker_RegisterSelf 58 * 59 * DESCRIPTION: 60 * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related 61 * functions with systemClasses[] 62 * 63 * THREAD SAFETY: 64 * Not Thread Safe - for performance and complexity reasons 65 * 66 * Since this function is only called by PKIX_PL_Initialize, which should 67 * only be called once, it is acceptable that this function is not 68 * thread-safe. 69 */ 70 PKIX_Error * 71 pkix_EkuChecker_RegisterSelf(void *plContext) 72 { 73 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 74 pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE]; 75 76 PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf"); 77 78 entry->description = "EkuChecker"; 79 entry->typeObjectSize = sizeof(pkix_EkuChecker); 80 entry->destructor = pkix_EkuChecker_Destroy; 81 82 PKIX_RETURN(EKUCHECKER); 83 } 84 85 /* 86 * FUNCTION: pkix_EkuChecker_Create 87 * DESCRIPTION: 88 * 89 * Creates a new Extend Key Usage CheckerState using "params" to retrieve 90 * application specified EKU for verification and stores it at "pState". 91 * 92 * PARAMETERS: 93 * "params" 94 * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of 95 * Extended Key Usage OIDs specified by application can be retrieved for 96 * verification. 97 * "pState" 98 * Address where state pointer will be stored. Must be non-NULL. 99 * "plContext" 100 * Platform-specific context pointer. 101 * THREAD SAFETY: 102 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 103 * RETURNS: 104 * Returns NULL if the function succeeds. 105 * Returns a UserDefinedModules Error if the function fails in a 106 * non-fatal way. 107 * Returns a Fatal Error if the function fails in an unrecoverable way. 108 */ 109 static PKIX_Error * 110 pkix_EkuChecker_Create( 111 PKIX_ProcessingParams *params, 112 pkix_EkuChecker **pState, 113 void *plContext) 114 { 115 pkix_EkuChecker *state = NULL; 116 PKIX_CertSelector *certSelector = NULL; 117 PKIX_ComCertSelParams *comCertSelParams = NULL; 118 PKIX_List *requiredOids = NULL; 119 120 PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create"); 121 PKIX_NULLCHECK_TWO(params, pState); 122 123 PKIX_CHECK(PKIX_PL_Object_Alloc 124 (PKIX_EKUCHECKER_TYPE, 125 sizeof (pkix_EkuChecker), 126 (PKIX_PL_Object **)&state, 127 plContext), 128 PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT); 129 130 131 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints 132 (params, &certSelector, plContext), 133 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); 134 135 if (certSelector != NULL) { 136 137 /* Get initial EKU OIDs from ComCertSelParams, if set */ 138 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams 139 (certSelector, &comCertSelParams, plContext), 140 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); 141 142 if (comCertSelParams != NULL) { 143 PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage 144 (comCertSelParams, &requiredOids, plContext), 145 PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); 146 147 } 148 } 149 150 PKIX_CHECK(PKIX_PL_OID_Create 151 (PKIX_EXTENDEDKEYUSAGE_OID, 152 &state->ekuOID, 153 plContext), 154 PKIX_OIDCREATEFAILED); 155 156 state->requiredExtKeyUsageOids = requiredOids; 157 requiredOids = NULL; 158 *pState = state; 159 state = NULL; 160 161 cleanup: 162 163 PKIX_DECREF(certSelector); 164 PKIX_DECREF(comCertSelParams); 165 PKIX_DECREF(requiredOids); 166 PKIX_DECREF(state); 167 168 PKIX_RETURN(EKUCHECKER); 169 } 170 171 /* 172 * FUNCTION: pkix_EkuChecker_Check 173 * DESCRIPTION: 174 * 175 * This function determines the Extended Key Usage OIDs specified by the 176 * application is included in the Extended Key Usage OIDs of this "cert". 177 * 178 * PARAMETERS: 179 * "checker" 180 * Address of CertChainChecker which has the state data. 181 * Must be non-NULL. 182 * "cert" 183 * Address of Certificate that is to be validated. Must be non-NULL. 184 * "unresolvedCriticalExtensions" 185 * A List OIDs. The OID for Extended Key Usage is removed. 186 * "plContext" 187 * Platform-specific context pointer. 188 * THREAD SAFETY: 189 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 190 * RETURNS: 191 * Returns NULL if the function succeeds. 192 * Returns a UserDefinedModules Error if the function fails in 193 * a non-fatal way. 194 * Returns a Fatal Error if the function fails in an unrecoverable way. 195 */ 196 static PKIX_Error * 197 pkix_EkuChecker_Check( 198 PKIX_CertChainChecker *checker, 199 PKIX_PL_Cert *cert, 200 PKIX_List *unresolvedCriticalExtensions, 201 void **pNBIOContext, 202 void *plContext) 203 { 204 pkix_EkuChecker *state = NULL; 205 PKIX_List *requiredExtKeyUsageList = NULL; 206 PKIX_List *certExtKeyUsageList = NULL; 207 PKIX_PL_OID *ekuOid = NULL; 208 PKIX_Boolean isContained = PKIX_FALSE; 209 PKIX_UInt32 numItems = 0; 210 PKIX_UInt32 i; 211 PKIX_Boolean checkResult = PKIX_TRUE; 212 213 PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check"); 214 PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); 215 216 *pNBIOContext = NULL; /* no non-blocking IO */ 217 218 PKIX_CHECK( 219 PKIX_CertChainChecker_GetCertChainCheckerState 220 (checker, (PKIX_PL_Object **)&state, plContext), 221 PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); 222 223 requiredExtKeyUsageList = state->requiredExtKeyUsageOids; 224 if (requiredExtKeyUsageList == NULL) { 225 goto cleanup; 226 } 227 228 PKIX_CHECK( 229 PKIX_List_GetLength(requiredExtKeyUsageList, &numItems, 230 plContext), 231 PKIX_LISTGETLENGTHFAILED); 232 if (numItems == 0) { 233 goto cleanup; 234 } 235 236 PKIX_CHECK( 237 PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList, 238 plContext), 239 PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); 240 241 if (certExtKeyUsageList == NULL) { 242 goto cleanup; 243 } 244 245 for (i = 0; i < numItems; i++) { 246 247 PKIX_CHECK( 248 PKIX_List_GetItem(requiredExtKeyUsageList, i, 249 (PKIX_PL_Object **)&ekuOid, plContext), 250 PKIX_LISTGETITEMFAILED); 251 252 PKIX_CHECK( 253 pkix_List_Contains(certExtKeyUsageList, 254 (PKIX_PL_Object *)ekuOid, 255 &isContained, 256 plContext), 257 PKIX_LISTCONTAINSFAILED); 258 259 PKIX_DECREF(ekuOid); 260 if (isContained != PKIX_TRUE) { 261 checkResult = PKIX_FALSE; 262 goto cleanup; 263 } 264 } 265 266 cleanup: 267 if (!pkixErrorResult && checkResult == PKIX_FALSE) { 268 pkixErrorReceived = PKIX_TRUE; 269 pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED; 270 } 271 272 PKIX_DECREF(ekuOid); 273 PKIX_DECREF(certExtKeyUsageList); 274 PKIX_DECREF(state); 275 276 PKIX_RETURN(EKUCHECKER); 277 } 278 279 /* 280 * FUNCTION: pkix_EkuChecker_Initialize 281 * (see comments in pkix_sample_modules.h) 282 */ 283 PKIX_Error * 284 PKIX_EkuChecker_Create( 285 PKIX_ProcessingParams *params, 286 PKIX_CertChainChecker **pEkuChecker, 287 void *plContext) 288 { 289 pkix_EkuChecker *state = NULL; 290 PKIX_List *critExtOIDsList = NULL; 291 292 PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize"); 293 PKIX_NULLCHECK_ONE(params); 294 295 /* 296 * This function and functions in this file provide an example of how 297 * an application defined checker can be hooked into libpkix. 298 */ 299 300 PKIX_CHECK(pkix_EkuChecker_Create 301 (params, &state, plContext), 302 PKIX_EKUCHECKERSTATECREATEFAILED); 303 304 PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext), 305 PKIX_LISTCREATEFAILED); 306 307 PKIX_CHECK(PKIX_List_AppendItem 308 (critExtOIDsList, 309 (PKIX_PL_Object *)state->ekuOID, 310 plContext), 311 PKIX_LISTAPPENDITEMFAILED); 312 313 PKIX_CHECK(PKIX_CertChainChecker_Create 314 (pkix_EkuChecker_Check, 315 PKIX_TRUE, /* forwardCheckingSupported */ 316 PKIX_FALSE, /* forwardDirectionExpected */ 317 critExtOIDsList, 318 (PKIX_PL_Object *) state, 319 pEkuChecker, 320 plContext), 321 PKIX_CERTCHAINCHECKERCREATEFAILED); 322 cleanup: 323 324 PKIX_DECREF(critExtOIDsList); 325 PKIX_DECREF(state); 326 327 PKIX_RETURN(EKUCHECKER); 328 }