Imported Upstream version 3.13.6
[platform/upstream/nss.git] / mozilla / security / nss / lib / libpkix / pkix / checker / pkix_basicconstraintschecker.c
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is the PKIX-C library.
15  *
16  * The Initial Developer of the Original Code is
17  * Sun Microsystems, Inc.
18  * Portions created by the Initial Developer are
19  * Copyright 2004-2007 Sun Microsystems, Inc.  All Rights Reserved.
20  *
21  * Contributor(s):
22  *   Sun Microsystems, Inc.
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37 /*
38  * pkix_basicconstraintschecker.c
39  *
40  * Functions for basic constraints validation
41  *
42  */
43
44 #include "pkix_basicconstraintschecker.h"
45
46 /* --Private-BasicConstraintsCheckerState-Functions------------------------- */
47
48 /*
49  * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy
50  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
51  */
52 static PKIX_Error *
53 pkix_BasicConstraintsCheckerState_Destroy(
54         PKIX_PL_Object *object,
55         void *plContext)
56 {
57         pkix_BasicConstraintsCheckerState *state = NULL;
58
59         PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
60                     "pkix_BasicConstraintsCheckerState_Destroy");
61
62         PKIX_NULLCHECK_ONE(object);
63
64         /* Check that this object is a basic constraints checker state */
65         PKIX_CHECK(pkix_CheckType
66                 (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext),
67                 PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE);
68
69         state = (pkix_BasicConstraintsCheckerState *)object;
70
71         PKIX_DECREF(state->basicConstraintsOID);
72
73 cleanup:
74
75         PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
76 }
77
78 /*
79  * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf
80  * DESCRIPTION:
81  *  Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
82  * THREAD SAFETY:
83  *  Not Thread Safe - for performance and complexity reasons
84  *
85  *  Since this function is only called by PKIX_PL_Initialize, which should
86  *  only be called once, it is acceptable that this function is not
87  *  thread-safe.
88  */
89 PKIX_Error *
90 pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext)
91 {
92         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
93         pkix_ClassTable_Entry entry;
94
95         PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
96                 "pkix_BasicConstraintsCheckerState_RegisterSelf");
97
98         entry.description = "BasicConstraintsCheckerState";
99         entry.objCounter = 0;
100         entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState);
101         entry.destructor = pkix_BasicConstraintsCheckerState_Destroy;
102         entry.equalsFunction = NULL;
103         entry.hashcodeFunction = NULL;
104         entry.toStringFunction = NULL;
105         entry.comparator = NULL;
106         entry.duplicateFunction = NULL;
107
108         systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry;
109
110         PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
111 }
112
113 /*
114  * FUNCTION: pkix_BasicConstraintsCheckerState_Create
115  * DESCRIPTION:
116  *
117  *  Creates a new BasicConstraintsCheckerState using the number of certs in
118  *  the chain represented by "certsRemaining" and stores it at "pState".
119  *
120  * PARAMETERS:
121  *  "certsRemaining"
122  *      Number of certificates in the chain.
123  *  "pState"
124  *      Address where object pointer will be stored. Must be non-NULL.
125  *  "plContext"
126  *      Platform-specific context pointer.
127  * THREAD SAFETY:
128  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
129  * RETURNS:
130  *  Returns NULL if the function succeeds.
131  *  Returns a BasicConstraintsCheckerState Error if the function fails in a
132  *      non-fatal way.
133  *  Returns a Fatal Error if the function fails in an unrecoverable way.
134  */
135 static PKIX_Error *
136 pkix_BasicConstraintsCheckerState_Create(
137         PKIX_UInt32 certsRemaining,
138         pkix_BasicConstraintsCheckerState **pState,
139         void *plContext)
140 {
141         pkix_BasicConstraintsCheckerState *state = NULL;
142
143         PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
144                     "pkix_BasicConstraintsCheckerState_Create");
145
146         PKIX_NULLCHECK_ONE(pState);
147
148         PKIX_CHECK(PKIX_PL_Object_Alloc
149                     (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE,
150                     sizeof (pkix_BasicConstraintsCheckerState),
151                     (PKIX_PL_Object **)&state,
152                     plContext),
153                     PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT);
154
155         /* initialize fields */
156         state->certsRemaining = certsRemaining;
157         state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
158
159         PKIX_CHECK(PKIX_PL_OID_Create
160                     (PKIX_BASICCONSTRAINTS_OID,
161                     &state->basicConstraintsOID,
162                     plContext),
163                     PKIX_OIDCREATEFAILED);
164
165         *pState = state;
166         state = NULL;
167
168 cleanup:
169
170         PKIX_DECREF(state);
171
172         PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
173 }
174
175 /* --Private-BasicConstraintsChecker-Functions------------------------------ */
176
177 /*
178  * FUNCTION: pkix_BasicConstraintsChecker_Check
179  * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
180  */
181 PKIX_Error *
182 pkix_BasicConstraintsChecker_Check(
183         PKIX_CertChainChecker *checker,
184         PKIX_PL_Cert *cert,
185         PKIX_List *unresolvedCriticalExtensions,  /* list of PKIX_PL_OID */
186         void **pNBIOContext,
187         void *plContext)
188 {
189         PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
190         pkix_BasicConstraintsCheckerState *state = NULL;
191         PKIX_Boolean caFlag = PKIX_FALSE;
192         PKIX_Int32 pathLength = 0;
193         PKIX_Int32 maxPathLength_now;
194         PKIX_Boolean isSelfIssued = PKIX_FALSE;
195
196         PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check");
197         PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
198
199         *pNBIOContext = NULL; /* we never block on pending I/O */
200
201         PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
202                     (checker, (PKIX_PL_Object **)&state, plContext),
203                     PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
204
205         state->certsRemaining--;
206
207         if (state->certsRemaining != 0) {
208
209                 PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
210                     (cert, &basicConstraints, plContext),
211                     PKIX_CERTGETBASICCONSTRAINTSFAILED);
212
213                 /* get CA Flag and path length */
214                 if (basicConstraints != NULL) {
215                         PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
216                             (basicConstraints,
217                             &caFlag,
218                             plContext),
219                             PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
220
221                 if (caFlag == PKIX_TRUE) {
222                         PKIX_CHECK
223                             (PKIX_PL_BasicConstraints_GetPathLenConstraint
224                             (basicConstraints,
225                             &pathLength,
226                             plContext),
227                             PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
228                 }
229
230                 }else{
231                         caFlag = PKIX_FALSE;
232                         pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
233                 }
234
235                 PKIX_CHECK(pkix_IsCertSelfIssued
236                         (cert,
237                         &isSelfIssued,
238                         plContext),
239                         PKIX_ISCERTSELFISSUEDFAILED);
240
241                 maxPathLength_now = state->maxPathLength;
242
243                 if (isSelfIssued != PKIX_TRUE) {
244
245                     /* Not last CA Cert, but maxPathLength is down to zero */
246                     if (maxPathLength_now == 0) {
247                         PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN);
248                     }
249
250                     if (caFlag == PKIX_FALSE) {
251                         PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA);
252                     }
253
254                     if (maxPathLength_now > 0) { /* can be unlimited (-1) */
255                         maxPathLength_now--;
256                     }
257
258                 }
259
260                 if (caFlag == PKIX_TRUE) {
261                     if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){
262                             maxPathLength_now = pathLength;
263                     } else {
264                             /* If pathLength is not specified, don't set */
265                         if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) {
266                             maxPathLength_now =
267                                     (maxPathLength_now > pathLength)?
268                                     pathLength:maxPathLength_now;
269                         }
270                     }
271                 }
272
273                 state->maxPathLength = maxPathLength_now;
274         }
275
276         /* Remove Basic Constraints Extension OID from list */
277         if (unresolvedCriticalExtensions != NULL) {
278
279                 PKIX_CHECK(pkix_List_Remove
280                             (unresolvedCriticalExtensions,
281                             (PKIX_PL_Object *) state->basicConstraintsOID,
282                             plContext),
283                             PKIX_LISTREMOVEFAILED);
284         }
285
286
287         PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
288                     (checker, (PKIX_PL_Object *)state, plContext),
289                     PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
290
291
292 cleanup:
293         PKIX_DECREF(state);
294         PKIX_DECREF(basicConstraints);
295         PKIX_RETURN(CERTCHAINCHECKER);
296
297 }
298
299 /*
300  * FUNCTION: pkix_BasicConstraintsChecker_Initialize
301  * DESCRIPTION:
302  *  Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
303  * THREAD SAFETY:
304  *  Not Thread Safe - for performance and complexity reasons
305  *
306  *  Since this function is only called by PKIX_PL_Initialize, which should
307  *  only be called once, it is acceptable that this function is not
308  *  thread-safe.
309  */
310 PKIX_Error *
311 pkix_BasicConstraintsChecker_Initialize(
312         PKIX_UInt32 certsRemaining,
313         PKIX_CertChainChecker **pChecker,
314         void *plContext)
315 {
316         pkix_BasicConstraintsCheckerState *state = NULL;
317
318         PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize");
319         PKIX_NULLCHECK_ONE(pChecker);
320
321         PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create
322                     (certsRemaining, &state, plContext),
323                     PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED);
324
325         PKIX_CHECK(PKIX_CertChainChecker_Create
326                     (pkix_BasicConstraintsChecker_Check,
327                     PKIX_FALSE,
328                     PKIX_FALSE,
329                     NULL,
330                     (PKIX_PL_Object *)state,
331                     pChecker,
332                     plContext),
333                     PKIX_CERTCHAINCHECKERCHECKFAILED);
334
335 cleanup:
336         PKIX_DECREF(state);
337
338         PKIX_RETURN(CERTCHAINCHECKER);
339 }