| OLD | NEW |
| (Empty) |
| 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 } | |
| OLD | NEW |