|
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_basicconstraintschecker.c |
|
6 * |
|
7 * Functions for basic constraints validation |
|
8 * |
|
9 */ |
|
10 |
|
11 #include "pkix_basicconstraintschecker.h" |
|
12 |
|
13 /* --Private-BasicConstraintsCheckerState-Functions------------------------- */ |
|
14 |
|
15 /* |
|
16 * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy |
|
17 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
|
18 */ |
|
19 static PKIX_Error * |
|
20 pkix_BasicConstraintsCheckerState_Destroy( |
|
21 PKIX_PL_Object *object, |
|
22 void *plContext) |
|
23 { |
|
24 pkix_BasicConstraintsCheckerState *state = NULL; |
|
25 |
|
26 PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, |
|
27 "pkix_BasicConstraintsCheckerState_Destroy"); |
|
28 |
|
29 PKIX_NULLCHECK_ONE(object); |
|
30 |
|
31 /* Check that this object is a basic constraints checker state */ |
|
32 PKIX_CHECK(pkix_CheckType |
|
33 (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext), |
|
34 PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE); |
|
35 |
|
36 state = (pkix_BasicConstraintsCheckerState *)object; |
|
37 |
|
38 PKIX_DECREF(state->basicConstraintsOID); |
|
39 |
|
40 cleanup: |
|
41 |
|
42 PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); |
|
43 } |
|
44 |
|
45 /* |
|
46 * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf |
|
47 * DESCRIPTION: |
|
48 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] |
|
49 * THREAD SAFETY: |
|
50 * Not Thread Safe - for performance and complexity reasons |
|
51 * |
|
52 * Since this function is only called by PKIX_PL_Initialize, which should |
|
53 * only be called once, it is acceptable that this function is not |
|
54 * thread-safe. |
|
55 */ |
|
56 PKIX_Error * |
|
57 pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext) |
|
58 { |
|
59 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
|
60 pkix_ClassTable_Entry entry; |
|
61 |
|
62 PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, |
|
63 "pkix_BasicConstraintsCheckerState_RegisterSelf"); |
|
64 |
|
65 entry.description = "BasicConstraintsCheckerState"; |
|
66 entry.objCounter = 0; |
|
67 entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState); |
|
68 entry.destructor = pkix_BasicConstraintsCheckerState_Destroy; |
|
69 entry.equalsFunction = NULL; |
|
70 entry.hashcodeFunction = NULL; |
|
71 entry.toStringFunction = NULL; |
|
72 entry.comparator = NULL; |
|
73 entry.duplicateFunction = NULL; |
|
74 |
|
75 systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry; |
|
76 |
|
77 PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); |
|
78 } |
|
79 |
|
80 /* |
|
81 * FUNCTION: pkix_BasicConstraintsCheckerState_Create |
|
82 * DESCRIPTION: |
|
83 * |
|
84 * Creates a new BasicConstraintsCheckerState using the number of certs in |
|
85 * the chain represented by "certsRemaining" and stores it at "pState". |
|
86 * |
|
87 * PARAMETERS: |
|
88 * "certsRemaining" |
|
89 * Number of certificates in the chain. |
|
90 * "pState" |
|
91 * Address where object pointer will be stored. Must be non-NULL. |
|
92 * "plContext" |
|
93 * Platform-specific context pointer. |
|
94 * THREAD SAFETY: |
|
95 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
|
96 * RETURNS: |
|
97 * Returns NULL if the function succeeds. |
|
98 * Returns a BasicConstraintsCheckerState Error if the function fails in a |
|
99 * non-fatal way. |
|
100 * Returns a Fatal Error if the function fails in an unrecoverable way. |
|
101 */ |
|
102 static PKIX_Error * |
|
103 pkix_BasicConstraintsCheckerState_Create( |
|
104 PKIX_UInt32 certsRemaining, |
|
105 pkix_BasicConstraintsCheckerState **pState, |
|
106 void *plContext) |
|
107 { |
|
108 pkix_BasicConstraintsCheckerState *state = NULL; |
|
109 |
|
110 PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE, |
|
111 "pkix_BasicConstraintsCheckerState_Create"); |
|
112 |
|
113 PKIX_NULLCHECK_ONE(pState); |
|
114 |
|
115 PKIX_CHECK(PKIX_PL_Object_Alloc |
|
116 (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, |
|
117 sizeof (pkix_BasicConstraintsCheckerState), |
|
118 (PKIX_PL_Object **)&state, |
|
119 plContext), |
|
120 PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT); |
|
121 |
|
122 /* initialize fields */ |
|
123 state->certsRemaining = certsRemaining; |
|
124 state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT; |
|
125 |
|
126 PKIX_CHECK(PKIX_PL_OID_Create |
|
127 (PKIX_BASICCONSTRAINTS_OID, |
|
128 &state->basicConstraintsOID, |
|
129 plContext), |
|
130 PKIX_OIDCREATEFAILED); |
|
131 |
|
132 *pState = state; |
|
133 state = NULL; |
|
134 |
|
135 cleanup: |
|
136 |
|
137 PKIX_DECREF(state); |
|
138 |
|
139 PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE); |
|
140 } |
|
141 |
|
142 /* --Private-BasicConstraintsChecker-Functions------------------------------ */ |
|
143 |
|
144 /* |
|
145 * FUNCTION: pkix_BasicConstraintsChecker_Check |
|
146 * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) |
|
147 */ |
|
148 PKIX_Error * |
|
149 pkix_BasicConstraintsChecker_Check( |
|
150 PKIX_CertChainChecker *checker, |
|
151 PKIX_PL_Cert *cert, |
|
152 PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */ |
|
153 void **pNBIOContext, |
|
154 void *plContext) |
|
155 { |
|
156 PKIX_PL_CertBasicConstraints *basicConstraints = NULL; |
|
157 pkix_BasicConstraintsCheckerState *state = NULL; |
|
158 PKIX_Boolean caFlag = PKIX_FALSE; |
|
159 PKIX_Int32 pathLength = 0; |
|
160 PKIX_Int32 maxPathLength_now; |
|
161 PKIX_Boolean isSelfIssued = PKIX_FALSE; |
|
162 |
|
163 PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check"); |
|
164 PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); |
|
165 |
|
166 *pNBIOContext = NULL; /* we never block on pending I/O */ |
|
167 |
|
168 PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState |
|
169 (checker, (PKIX_PL_Object **)&state, plContext), |
|
170 PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); |
|
171 |
|
172 state->certsRemaining--; |
|
173 |
|
174 if (state->certsRemaining != 0) { |
|
175 |
|
176 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints |
|
177 (cert, &basicConstraints, plContext), |
|
178 PKIX_CERTGETBASICCONSTRAINTSFAILED); |
|
179 |
|
180 /* get CA Flag and path length */ |
|
181 if (basicConstraints != NULL) { |
|
182 PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag |
|
183 (basicConstraints, |
|
184 &caFlag, |
|
185 plContext), |
|
186 PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); |
|
187 |
|
188 if (caFlag == PKIX_TRUE) { |
|
189 PKIX_CHECK |
|
190 (PKIX_PL_BasicConstraints_GetPathLenConstraint |
|
191 (basicConstraints, |
|
192 &pathLength, |
|
193 plContext), |
|
194 PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED); |
|
195 } |
|
196 |
|
197 }else{ |
|
198 caFlag = PKIX_FALSE; |
|
199 pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT; |
|
200 } |
|
201 |
|
202 PKIX_CHECK(pkix_IsCertSelfIssued |
|
203 (cert, |
|
204 &isSelfIssued, |
|
205 plContext), |
|
206 PKIX_ISCERTSELFISSUEDFAILED); |
|
207 |
|
208 maxPathLength_now = state->maxPathLength; |
|
209 |
|
210 if (isSelfIssued != PKIX_TRUE) { |
|
211 |
|
212 /* Not last CA Cert, but maxPathLength is down to zero */ |
|
213 if (maxPathLength_now == 0) { |
|
214 PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN); |
|
215 } |
|
216 |
|
217 if (caFlag == PKIX_FALSE) { |
|
218 PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA); |
|
219 } |
|
220 |
|
221 if (maxPathLength_now > 0) { /* can be unlimited (-1) */ |
|
222 maxPathLength_now--; |
|
223 } |
|
224 |
|
225 } |
|
226 |
|
227 if (caFlag == PKIX_TRUE) { |
|
228 if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){ |
|
229 maxPathLength_now = pathLength; |
|
230 } else { |
|
231 /* If pathLength is not specified, don't set */ |
|
232 if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) { |
|
233 maxPathLength_now = |
|
234 (maxPathLength_now > pathLength)? |
|
235 pathLength:maxPathLength_now; |
|
236 } |
|
237 } |
|
238 } |
|
239 |
|
240 state->maxPathLength = maxPathLength_now; |
|
241 } |
|
242 |
|
243 /* Remove Basic Constraints Extension OID from list */ |
|
244 if (unresolvedCriticalExtensions != NULL) { |
|
245 |
|
246 PKIX_CHECK(pkix_List_Remove |
|
247 (unresolvedCriticalExtensions, |
|
248 (PKIX_PL_Object *) state->basicConstraintsOID, |
|
249 plContext), |
|
250 PKIX_LISTREMOVEFAILED); |
|
251 } |
|
252 |
|
253 |
|
254 PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState |
|
255 (checker, (PKIX_PL_Object *)state, plContext), |
|
256 PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); |
|
257 |
|
258 |
|
259 cleanup: |
|
260 PKIX_DECREF(state); |
|
261 PKIX_DECREF(basicConstraints); |
|
262 PKIX_RETURN(CERTCHAINCHECKER); |
|
263 |
|
264 } |
|
265 |
|
266 /* |
|
267 * FUNCTION: pkix_BasicConstraintsChecker_Initialize |
|
268 * DESCRIPTION: |
|
269 * Registers PKIX_CERT_TYPE and its related functions with systemClasses[] |
|
270 * THREAD SAFETY: |
|
271 * Not Thread Safe - for performance and complexity reasons |
|
272 * |
|
273 * Since this function is only called by PKIX_PL_Initialize, which should |
|
274 * only be called once, it is acceptable that this function is not |
|
275 * thread-safe. |
|
276 */ |
|
277 PKIX_Error * |
|
278 pkix_BasicConstraintsChecker_Initialize( |
|
279 PKIX_UInt32 certsRemaining, |
|
280 PKIX_CertChainChecker **pChecker, |
|
281 void *plContext) |
|
282 { |
|
283 pkix_BasicConstraintsCheckerState *state = NULL; |
|
284 |
|
285 PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize"); |
|
286 PKIX_NULLCHECK_ONE(pChecker); |
|
287 |
|
288 PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create |
|
289 (certsRemaining, &state, plContext), |
|
290 PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED); |
|
291 |
|
292 PKIX_CHECK(PKIX_CertChainChecker_Create |
|
293 (pkix_BasicConstraintsChecker_Check, |
|
294 PKIX_FALSE, |
|
295 PKIX_FALSE, |
|
296 NULL, |
|
297 (PKIX_PL_Object *)state, |
|
298 pChecker, |
|
299 plContext), |
|
300 PKIX_CERTCHAINCHECKERCHECKFAILED); |
|
301 |
|
302 cleanup: |
|
303 PKIX_DECREF(state); |
|
304 |
|
305 PKIX_RETURN(CERTCHAINCHECKER); |
|
306 } |