|
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 } |