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_pl_basicconstraints.c
6  *
7  * BasicConstraints Object Functions
8  *
9  */
10 
11 #include "pkix_pl_basicconstraints.h"
12 
13 /*
14  * FUNCTION: pkix_pl_CertBasicConstraints_Create
15  * DESCRIPTION:
16  *
17  *  Creates a new CertBasicConstraints object whose CA Flag has the value
18  *  given by the Boolean value of "isCA" and whose path length field has the
19  *  value given by the "pathLen" argument and stores it at "pObject".
20  *
21  * PARAMETERS
22  *  "isCA"
23  *      Boolean value with the desired value of CA Flag.
24  *  "pathLen"
25  *      a PKIX_Int32 with the desired value of path length
26  *  "pObject"
27  *      Address of object pointer's destination. Must be non-NULL.
28  *  "plContext" - Platform-specific context pointer.
29  * THREAD SAFETY:
30  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
31  * RETURNS:
32  *  Returns NULL if the function succeeds.
33  *  Returns a CertBasicConstraints Error if the function fails
34  *  in a non-fatal way.
35  *  Returns a Fatal Error if the function fails in an unrecoverable way.
36  */
37 PKIX_Error *
pkix_pl_CertBasicConstraints_Create(PKIX_Boolean isCA,PKIX_Int32 pathLen,PKIX_PL_CertBasicConstraints ** pObject,void * plContext)38 pkix_pl_CertBasicConstraints_Create(
39         PKIX_Boolean isCA,
40         PKIX_Int32 pathLen,
41         PKIX_PL_CertBasicConstraints **pObject,
42         void *plContext)
43 {
44         PKIX_PL_CertBasicConstraints *basic = NULL;
45 
46         PKIX_ENTER(CERTBASICCONSTRAINTS,
47                     "pkix_pl_CertBasicConstraints_Create");
48         PKIX_NULLCHECK_ONE(pObject);
49 
50         PKIX_CHECK(PKIX_PL_Object_Alloc
51                     (PKIX_CERTBASICCONSTRAINTS_TYPE,
52                     sizeof (PKIX_PL_CertBasicConstraints),
53                     (PKIX_PL_Object **)&basic,
54                     plContext),
55                     PKIX_COULDNOTCREATECERTBASICCONSTRAINTSOBJECT);
56 
57         basic->isCA = isCA;
58 
59         /* pathLen has meaning only for CAs, but it's not worth checking */
60         basic->pathLen = pathLen;
61 
62         *pObject = basic;
63 
64 cleanup:
65 
66         PKIX_RETURN(CERTBASICCONSTRAINTS);
67 }
68 
69 /*
70  * FUNCTION: pkix_pl_CertBasicConstraints_Destroy
71  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
72  */
73 static PKIX_Error *
pkix_pl_CertBasicConstraints_Destroy(PKIX_PL_Object * object,void * plContext)74 pkix_pl_CertBasicConstraints_Destroy(
75         PKIX_PL_Object *object,
76         void *plContext)
77 {
78         PKIX_PL_CertBasicConstraints *certB = NULL;
79 
80         PKIX_ENTER(CERTBASICCONSTRAINTS,
81                 "pkix_pl_CertBasicConstraints_Destroy");
82         PKIX_NULLCHECK_ONE(object);
83 
84         PKIX_CHECK(pkix_CheckType
85                     (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
86                     PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
87 
88         certB = (PKIX_PL_CertBasicConstraints*)object;
89 
90         certB->isCA = PKIX_FALSE;
91         certB->pathLen = 0;
92 
93 cleanup:
94 
95         PKIX_RETURN(CERTBASICCONSTRAINTS);
96 }
97 
98 /*
99  * FUNCTION: pkix_pl_CertBasicConstraints_ToString
100  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
101  */
102 static PKIX_Error *
pkix_pl_CertBasicConstraints_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pString,void * plContext)103 pkix_pl_CertBasicConstraints_ToString(
104         PKIX_PL_Object *object,
105         PKIX_PL_String **pString,
106         void *plContext)
107 {
108         PKIX_PL_String *certBasicConstraintsString = NULL;
109         PKIX_PL_CertBasicConstraints *certB = NULL;
110         PKIX_Boolean isCA = PKIX_FALSE;
111         PKIX_Int32 pathLen = 0;
112         PKIX_PL_String *outString = NULL;
113         char *fmtString = NULL;
114         PKIX_Boolean pathlenArg = PKIX_FALSE;
115 
116         PKIX_ENTER(CERTBASICCONSTRAINTS,
117                 "pkix_pl_CertBasicConstraints_toString");
118         PKIX_NULLCHECK_TWO(object, pString);
119 
120         PKIX_CHECK(pkix_CheckType
121                     (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
122                     PKIX_FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT);
123 
124         certB = (PKIX_PL_CertBasicConstraints *)object;
125 
126         /*
127          * if CA == TRUE
128          *      if pathLen == CERT_UNLIMITED_PATH_CONSTRAINT
129          *              print "CA(-1)"
130          *      else print "CA(nnn)"
131          * if CA == FALSE, print "~CA"
132          */
133 
134         isCA = certB->isCA;
135 
136         if (isCA) {
137                 pathLen = certB->pathLen;
138 
139                 if (pathLen == CERT_UNLIMITED_PATH_CONSTRAINT) {
140                         /* print "CA(-1)" */
141                         fmtString = "CA(-1)";
142                         pathlenArg = PKIX_FALSE;
143                 } else {
144                         /* print "CA(pathLen)" */
145                         fmtString = "CA(%d)";
146                         pathlenArg = PKIX_TRUE;
147                 }
148         } else {
149                 /* print "~CA" */
150                 fmtString = "~CA";
151                 pathlenArg = PKIX_FALSE;
152         }
153 
154         PKIX_CHECK(PKIX_PL_String_Create
155                     (PKIX_ESCASCII,
156                     fmtString,
157                     0,
158                     &certBasicConstraintsString,
159                     plContext),
160                     PKIX_STRINGCREATEFAILED);
161 
162         if (pathlenArg) {
163                 PKIX_CHECK(PKIX_PL_Sprintf
164                             (&outString,
165                             plContext,
166                             certBasicConstraintsString,
167                             pathLen),
168                             PKIX_SPRINTFFAILED);
169         } else {
170                 PKIX_CHECK(PKIX_PL_Sprintf
171                             (&outString,
172                             plContext,
173                             certBasicConstraintsString),
174                             PKIX_SPRINTFFAILED);
175         }
176 
177         *pString = outString;
178 
179 cleanup:
180 
181         PKIX_DECREF(certBasicConstraintsString);
182 
183         PKIX_RETURN(CERTBASICCONSTRAINTS);
184 }
185 
186 /*
187  * FUNCTION: pkix_pl_CertBasicConstraints_Hashcode
188  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
189  */
190 static PKIX_Error *
pkix_pl_CertBasicConstraints_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)191 pkix_pl_CertBasicConstraints_Hashcode(
192         PKIX_PL_Object *object,
193         PKIX_UInt32 *pHashcode,
194         void *plContext)
195 {
196         PKIX_PL_CertBasicConstraints *certB = NULL;
197         PKIX_Boolean isCA = PKIX_FALSE;
198         PKIX_Int32 pathLen = 0;
199         PKIX_Int32 hashInput = 0;
200         PKIX_UInt32 cbcHash = 0;
201 
202         PKIX_ENTER(CERTBASICCONSTRAINTS,
203                 "pkix_pl_CertBasicConstraints_Hashcode");
204         PKIX_NULLCHECK_TWO(object, pHashcode);
205 
206         PKIX_CHECK(pkix_CheckType
207                     (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
208                     PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
209 
210         certB = (PKIX_PL_CertBasicConstraints *)object;
211 
212         /*
213          * if CA == TRUE
214          *      hash(pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT)
215          * if CA == FALSE, hash(0)
216          */
217 
218         isCA = certB->isCA;
219 
220         if (isCA) {
221                 pathLen = certB->pathLen;
222 
223                 hashInput = pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT;
224         }
225 
226         PKIX_CHECK(pkix_hash
227                     ((const unsigned char *)&hashInput,
228                     sizeof (hashInput),
229                     &cbcHash,
230                     plContext),
231                     PKIX_HASHFAILED);
232 
233         *pHashcode = cbcHash;
234 
235 cleanup:
236 
237         PKIX_RETURN(CERTBASICCONSTRAINTS);
238 }
239 
240 
241 /*
242  * FUNCTION: pkix_pl_CertBasicConstraints_Equals
243  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
244  */
245 static PKIX_Error *
pkix_pl_CertBasicConstraints_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)246 pkix_pl_CertBasicConstraints_Equals(
247         PKIX_PL_Object *firstObject,
248         PKIX_PL_Object *secondObject,
249         PKIX_Boolean *pResult,
250         void *plContext)
251 {
252         PKIX_PL_CertBasicConstraints *firstCBC = NULL;
253         PKIX_PL_CertBasicConstraints *secondCBC = NULL;
254         PKIX_UInt32 secondType;
255         PKIX_Boolean firstIsCA = PKIX_FALSE;
256         PKIX_Boolean secondIsCA = PKIX_FALSE;
257         PKIX_Int32 firstPathLen = 0;
258         PKIX_Int32 secondPathLen = 0;
259 
260         PKIX_ENTER(CERTBASICCONSTRAINTS,
261                 "pkix_pl_CertBasicConstraints_Equals");
262         PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
263 
264         /* test that firstObject is a CertBasicConstraints */
265         PKIX_CHECK(pkix_CheckType
266                     (firstObject, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
267                     PKIX_FIRSTOBJECTNOTCERTBASICCONSTRAINTS);
268 
269         /*
270          * Since we know firstObject is a CertBasicConstraints,
271          * if both references are identical, they must be equal
272          */
273         if (firstObject == secondObject){
274                 *pResult = PKIX_TRUE;
275                 goto cleanup;
276         }
277 
278         /*
279          * If secondObject isn't a CertBasicConstraints, we
280          * don't throw an error. We simply return FALSE.
281          */
282         PKIX_CHECK(PKIX_PL_Object_GetType
283                     (secondObject, &secondType, plContext),
284                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
285         if (secondType != PKIX_CERTBASICCONSTRAINTS_TYPE) {
286                 *pResult = PKIX_FALSE;
287                 goto cleanup;
288         }
289 
290         firstCBC = (PKIX_PL_CertBasicConstraints *)firstObject;
291         secondCBC = (PKIX_PL_CertBasicConstraints *)secondObject;
292 
293         /*
294          * Compare the value of the CAFlag components
295          */
296 
297         firstIsCA = firstCBC->isCA;
298 
299         /*
300          * Failure here would be an error, not merely a miscompare,
301          * since we know second is a CertBasicConstraints.
302          */
303         secondIsCA = secondCBC->isCA;
304 
305         /*
306          * If isCA flags differ, the objects are not equal.
307          */
308         if (secondIsCA != firstIsCA) {
309                 *pResult = PKIX_FALSE;
310                 goto cleanup;
311         }
312 
313         /*
314          * If isCA was FALSE, the objects are equal, because
315          * pathLen is meaningless in that case.
316          */
317         if (!firstIsCA) {
318                 *pResult = PKIX_TRUE;
319                 goto cleanup;
320         }
321 
322         firstPathLen = firstCBC->pathLen;
323         secondPathLen = secondCBC->pathLen;
324 
325         *pResult = (secondPathLen == firstPathLen);
326 
327 cleanup:
328 
329         PKIX_RETURN(CERTBASICCONSTRAINTS);
330 }
331 
332 /*
333  * FUNCTION: pkix_pl_CertBasicConstraints_RegisterSelf
334  * DESCRIPTION:
335  *  Registers PKIX_CERTBASICCONSTRAINTS_TYPE and its related
336  *  functions with systemClasses[]
337  * THREAD SAFETY:
338  *  Not Thread Safe - for performance and complexity reasons
339  *
340  *  Since this function is only called by PKIX_PL_Initialize,
341  *  which should only be called once, it is acceptable that
342  *  this function is not thread-safe.
343  */
344 PKIX_Error *
pkix_pl_CertBasicConstraints_RegisterSelf(void * plContext)345 pkix_pl_CertBasicConstraints_RegisterSelf(void *plContext)
346 {
347 
348         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
349         pkix_ClassTable_Entry entry;
350 
351         PKIX_ENTER(CERTBASICCONSTRAINTS,
352                 "pkix_pl_CertBasicConstraints_RegisterSelf");
353 
354         entry.description = "CertBasicConstraints";
355         entry.objCounter = 0;
356         entry.typeObjectSize = sizeof(PKIX_PL_CertBasicConstraints);
357         entry.destructor = pkix_pl_CertBasicConstraints_Destroy;
358         entry.equalsFunction = pkix_pl_CertBasicConstraints_Equals;
359         entry.hashcodeFunction = pkix_pl_CertBasicConstraints_Hashcode;
360         entry.toStringFunction = pkix_pl_CertBasicConstraints_ToString;
361         entry.comparator = NULL;
362         entry.duplicateFunction = pkix_duplicateImmutable;
363 
364         systemClasses[PKIX_CERTBASICCONSTRAINTS_TYPE] = entry;
365 
366         PKIX_RETURN(CERTBASICCONSTRAINTS);
367 }
368 
369 /* --Public-Functions------------------------------------------------------- */
370 
371 /*
372  * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag
373  * (see comments in pkix_pl_pki.h)
374  */
375 PKIX_Error *
PKIX_PL_BasicConstraints_GetCAFlag(PKIX_PL_CertBasicConstraints * basicConstraints,PKIX_Boolean * pResult,void * plContext)376 PKIX_PL_BasicConstraints_GetCAFlag(
377         PKIX_PL_CertBasicConstraints *basicConstraints,
378         PKIX_Boolean *pResult,
379         void *plContext)
380 {
381         PKIX_ENTER(CERTBASICCONSTRAINTS,
382                 "PKIX_PL_BasicConstraintsGetCAFlag");
383         PKIX_NULLCHECK_TWO(basicConstraints, pResult);
384 
385         *pResult = basicConstraints->isCA;
386 
387         PKIX_RETURN(CERTBASICCONSTRAINTS);
388 }
389 
390 /*
391  * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint
392  * (see comments in pkix_pl_pki.h)
393  */
394 PKIX_Error *
PKIX_PL_BasicConstraints_GetPathLenConstraint(PKIX_PL_CertBasicConstraints * basicConstraints,PKIX_Int32 * pPathLenConstraint,void * plContext)395 PKIX_PL_BasicConstraints_GetPathLenConstraint(
396         PKIX_PL_CertBasicConstraints *basicConstraints,
397         PKIX_Int32 *pPathLenConstraint,
398         void *plContext)
399 {
400         PKIX_ENTER(CERTBASICCONSTRAINTS,
401                 "PKIX_PL_BasicConstraintsGetPathLenConstraint");
402         PKIX_NULLCHECK_TWO(basicConstraints, pPathLenConstraint);
403 
404         *pPathLenConstraint = basicConstraints->pathLen;
405 
406         PKIX_RETURN(CERTBASICCONSTRAINTS);
407 }
408