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_verifynode.c
6  *
7  * Verify Node Object Type Definition
8  *
9  */
10 
11 #include "pkix_verifynode.h"
12 
13 /* --Private-VerifyNode-Functions---------------------------------- */
14 
15 /*
16  * FUNCTION: pkix_VerifyNode_Create
17  * DESCRIPTION:
18  *
19  *  This function creates a VerifyNode using the Cert pointed to by "cert",
20  *  the depth given by "depth", and the Error pointed to by "error", storing
21  *  the result at "pObject".
22  *
23  * PARAMETERS
24  *  "cert"
25  *      Address of Cert for the node. Must be non-NULL
26  *  "depth"
27  *      UInt32 value of the depth for this node.
28  *  "error"
29  *      Address of Error for the node.
30  *  "pObject"
31  *      Address where the VerifyNode pointer will be stored. Must be non-NULL.
32  *  "plContext"
33  *      Platform-specific context pointer.
34  * THREAD SAFETY:
35  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
36  * RETURNS:
37  *  Returns NULL if the function succeeds.
38  *  Returns a Fatal Error if the function fails in an unrecoverable way.
39  */
40 PKIX_Error *
pkix_VerifyNode_Create(PKIX_PL_Cert * cert,PKIX_UInt32 depth,PKIX_Error * error,PKIX_VerifyNode ** pObject,void * plContext)41 pkix_VerifyNode_Create(
42         PKIX_PL_Cert *cert,
43         PKIX_UInt32 depth,
44         PKIX_Error *error,
45         PKIX_VerifyNode **pObject,
46         void *plContext)
47 {
48         PKIX_VerifyNode *node = NULL;
49 
50         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create");
51         PKIX_NULLCHECK_TWO(cert, pObject);
52 
53         PKIX_CHECK(PKIX_PL_Object_Alloc
54                 (PKIX_VERIFYNODE_TYPE,
55                 sizeof (PKIX_VerifyNode),
56                 (PKIX_PL_Object **)&node,
57                 plContext),
58                 PKIX_COULDNOTCREATEVERIFYNODEOBJECT);
59 
60         PKIX_INCREF(cert);
61         node->verifyCert = cert;
62 
63         PKIX_INCREF(error);
64         node->error = error;
65 
66         node->depth = depth;
67 
68         node->children = NULL;
69 
70         *pObject = node;
71         node = NULL;
72 
73 cleanup:
74 
75         PKIX_DECREF(node);
76 
77         PKIX_RETURN(VERIFYNODE);
78 }
79 
80 /*
81  * FUNCTION: pkix_VerifyNode_AddToChain
82  * DESCRIPTION:
83  *
84  *  Adds the VerifyNode pointed to by "child", at the appropriate depth, to the
85  *  List of children of the VerifyNode pointed to by "parentNode". The chain of
86  *  VerifyNodes is traversed until a VerifyNode is found at a depth one less
87  *  than that specified in "child". An Error is returned if there is no parent
88  *  at a suitable depth.
89  *
90  *  If "parentNode" has a NULL pointer for the List of children, a new List is
91  *  created containing "child". Otherwise "child" is appended to the existing
92  *  List.
93  *
94  *  Depth, in this context, means distance from the root node, which
95  *  is at depth zero.
96  *
97  * PARAMETERS:
98  *  "parentNode"
99  *      Address of VerifyNode whose List of child VerifyNodes is to be
100  *      created or appended to. Must be non-NULL.
101  *  "child"
102  *      Address of VerifyNode to be added to parentNode's List. Must be
103  *      non-NULL.
104  *  "plContext"
105  *      Platform-specific context pointer.
106  * THREAD SAFETY:
107  *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
108  * RETURNS:
109  *  Returns NULL if the function succeeds.
110  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
111  *  Returns a Fatal Error if the function fails in an unrecoverable way.
112  */
113 PKIX_Error *
pkix_VerifyNode_AddToChain(PKIX_VerifyNode * parentNode,PKIX_VerifyNode * child,void * plContext)114 pkix_VerifyNode_AddToChain(
115         PKIX_VerifyNode *parentNode,
116         PKIX_VerifyNode *child,
117         void *plContext)
118 {
119         PKIX_VerifyNode *successor = NULL;
120         PKIX_List *listOfChildren = NULL;
121         PKIX_UInt32 numChildren = 0;
122         PKIX_UInt32 parentDepth = 0;
123 
124         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain");
125         PKIX_NULLCHECK_TWO(parentNode, child);
126 
127         parentDepth = parentNode->depth;
128         listOfChildren = parentNode->children;
129         if (listOfChildren == NULL) {
130 
131                 if (parentDepth != (child->depth - 1)) {
132                         PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN);
133                 }
134 
135                 PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
136                         PKIX_LISTCREATEFAILED);
137 
138                 PKIX_CHECK(PKIX_List_AppendItem
139                         (listOfChildren, (PKIX_PL_Object *)child, plContext),
140                         PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
141 
142                 parentNode->children = listOfChildren;
143         } else {
144                 /* get number of children */
145                 PKIX_CHECK(PKIX_List_GetLength
146                         (listOfChildren, &numChildren, plContext),
147                         PKIX_LISTGETLENGTHFAILED);
148 
149                 if (numChildren != 1) {
150                         PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE);
151                 }
152 
153                 /* successor = listOfChildren[0] */
154                 PKIX_CHECK(PKIX_List_GetItem
155                         (listOfChildren,
156                         0,
157                         (PKIX_PL_Object **)&successor,
158                         plContext),
159                         PKIX_LISTGETITEMFAILED);
160 
161                 PKIX_CHECK(pkix_VerifyNode_AddToChain
162                         (successor, child, plContext),
163                         PKIX_VERIFYNODEADDTOCHAINFAILED);
164         }
165 
166         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
167                 ((PKIX_PL_Object *)parentNode, plContext),
168                 PKIX_OBJECTINVALIDATECACHEFAILED);
169 
170 cleanup:
171         PKIX_DECREF(successor);
172 
173         PKIX_RETURN(VERIFYNODE);
174 }
175 
176 /*
177  * FUNCTION: pkix_VerifyNode_SetDepth
178  * DESCRIPTION:
179  *
180  *  The function sets the depth field of each VerifyNode in the List "children"
181  *  to the value given by "depth", and recursively sets the depth of any
182  *  successive generations to the successive values.
183  *
184  * PARAMETERS:
185  *  "children"
186  *      The List of VerifyNodes. Must be non-NULL.
187  *  "depth"
188  *      The value of the depth field to be set in members of the List.
189  *  "plContext"
190  *      Platform-specific context pointer.
191  * THREAD SAFETY:
192  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
193  * RETURNS:
194  *  Returns NULL if the function succeeds.
195  *  Returns a Fatal Error if the function fails in an unrecoverable way.
196  */
197 static PKIX_Error *
pkix_VerifyNode_SetDepth(PKIX_List * children,PKIX_UInt32 depth,void * plContext)198 pkix_VerifyNode_SetDepth(PKIX_List *children,
199         PKIX_UInt32 depth,
200         void *plContext)
201 {
202         PKIX_UInt32 numChildren = 0;
203         PKIX_UInt32 chIx = 0;
204         PKIX_VerifyNode *child = NULL;
205 
206         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth");
207         PKIX_NULLCHECK_ONE(children);
208 
209         PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
210                 PKIX_LISTGETLENGTHFAILED);
211 
212         for (chIx = 0; chIx < numChildren; chIx++) {
213                PKIX_CHECK(PKIX_List_GetItem
214                         (children, chIx, (PKIX_PL_Object **)&child, plContext),
215                         PKIX_LISTGETITEMFAILED);
216 
217                 child->depth = depth;
218 
219                 if (child->children != NULL) {
220                         PKIX_CHECK(pkix_VerifyNode_SetDepth
221                                 (child->children, depth + 1, plContext),
222                                 PKIX_VERIFYNODESETDEPTHFAILED);
223                 }
224 
225                 PKIX_DECREF(child);
226         }
227 
228 cleanup:
229 
230         PKIX_DECREF(child);
231 
232         PKIX_RETURN(VERIFYNODE);
233 }
234 
235 /*
236  * FUNCTION: pkix_VerifyNode_AddToTree
237  * DESCRIPTION:
238  *
239  *  Adds the VerifyNode pointed to by "child" to the List of children of the
240  *  VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer
241  *  for the List of children, a new List is created containing "child".
242  *  Otherwise "child" is appended to the existing List. The depth field of
243  *  "child" is set to one more than the corresponding value in "parent", and
244  *  if the "child" itself has child nodes, their depth fields are updated
245  *  accordingly.
246  *
247  *  Depth, in this context, means distance from the root node, which
248  *  is at depth zero.
249  *
250  * PARAMETERS:
251  *  "parentNode"
252  *      Address of VerifyNode whose List of child VerifyNodes is to be
253  *      created or appended to. Must be non-NULL.
254  *  "child"
255  *      Address of VerifyNode to be added to parentNode's List. Must be
256  *      non-NULL.
257  *  "plContext"
258  *      Platform-specific context pointer.
259  * THREAD SAFETY:
260  *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
261  * RETURNS:
262  *  Returns NULL if the function succeeds.
263  *  Returns a Fatal Error if the function fails in an unrecoverable way.
264  */
265 PKIX_Error *
pkix_VerifyNode_AddToTree(PKIX_VerifyNode * parentNode,PKIX_VerifyNode * child,void * plContext)266 pkix_VerifyNode_AddToTree(
267         PKIX_VerifyNode *parentNode,
268         PKIX_VerifyNode *child,
269         void *plContext)
270 {
271         PKIX_List *listOfChildren = NULL;
272         PKIX_UInt32 parentDepth = 0;
273 
274         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree");
275         PKIX_NULLCHECK_TWO(parentNode, child);
276 
277         parentDepth = parentNode->depth;
278         listOfChildren = parentNode->children;
279         if (listOfChildren == NULL) {
280 
281                 PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
282                         PKIX_LISTCREATEFAILED);
283 
284                 parentNode->children = listOfChildren;
285         }
286 
287         child->depth = parentDepth + 1;
288 
289         PKIX_CHECK(PKIX_List_AppendItem
290                 (parentNode->children, (PKIX_PL_Object *)child, plContext),
291                 PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
292 
293         if (child->children != NULL) {
294                 PKIX_CHECK(pkix_VerifyNode_SetDepth
295                         (child->children, child->depth + 1, plContext),
296                         PKIX_VERIFYNODESETDEPTHFAILED);
297         }
298 
299 
300 cleanup:
301 
302         PKIX_RETURN(VERIFYNODE);
303 }
304 
305 /*
306  * FUNCTION: pkix_SingleVerifyNode_ToString
307  * DESCRIPTION:
308  *
309  *  Creates a String representation of the attributes of the VerifyNode pointed
310  *  to by "node", other than its children, and stores the result at "pString".
311  *
312  * PARAMETERS:
313  *  "node"
314  *      Address of VerifyNode to be described by the string. Must be non-NULL.
315  *  "pString"
316  *      Address where object pointer will be stored. Must be non-NULL.
317  *  "plContext"
318  *      Platform-specific context pointer.
319  * THREAD SAFETY:
320  *  Conditionally Thread Safe
321  *  (see Thread Safety Definitions in Programmer's Guide)
322  * RETURNS:
323  *  Returns NULL if function succeeds
324  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
325  *  Returns a Fatal Error if the function fails in a fatal way
326  */
327 PKIX_Error *
pkix_SingleVerifyNode_ToString(PKIX_VerifyNode * node,PKIX_PL_String ** pString,void * plContext)328 pkix_SingleVerifyNode_ToString(
329         PKIX_VerifyNode *node,
330         PKIX_PL_String **pString,
331         void *plContext)
332 {
333         PKIX_PL_String *fmtString = NULL;
334         PKIX_PL_String *errorString = NULL;
335         PKIX_PL_String *outString = NULL;
336 
337         PKIX_PL_X500Name *issuerName = NULL;
338         PKIX_PL_X500Name *subjectName = NULL;
339         PKIX_PL_String *issuerString = NULL;
340         PKIX_PL_String *subjectString = NULL;
341 
342         PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString");
343         PKIX_NULLCHECK_THREE(node, pString, node->verifyCert);
344 
345         PKIX_TOSTRING(node->error, &errorString, plContext,
346                 PKIX_ERRORTOSTRINGFAILED);
347 
348         PKIX_CHECK(PKIX_PL_Cert_GetIssuer
349                 (node->verifyCert, &issuerName, plContext),
350                 PKIX_CERTGETISSUERFAILED);
351 
352         PKIX_TOSTRING(issuerName, &issuerString, plContext,
353                 PKIX_X500NAMETOSTRINGFAILED);
354 
355         PKIX_CHECK(PKIX_PL_Cert_GetSubject
356                 (node->verifyCert, &subjectName, plContext),
357                 PKIX_CERTGETSUBJECTFAILED);
358 
359         PKIX_TOSTRING(subjectName, &subjectString, plContext,
360                 PKIX_X500NAMETOSTRINGFAILED);
361 
362         PKIX_CHECK(PKIX_PL_String_Create
363                 (PKIX_ESCASCII,
364                 "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s",
365                 0,
366                 &fmtString,
367                 plContext),
368                 PKIX_CANTCREATESTRING);
369 
370         PKIX_CHECK(PKIX_PL_Sprintf
371                 (&outString,
372                 plContext,
373                 fmtString,
374                 issuerString,
375                 subjectString,
376                 node->depth,
377                 errorString),
378                 PKIX_SPRINTFFAILED);
379 
380         *pString = outString;
381 
382 cleanup:
383 
384         PKIX_DECREF(fmtString);
385         PKIX_DECREF(errorString);
386         PKIX_DECREF(issuerName);
387         PKIX_DECREF(subjectName);
388         PKIX_DECREF(issuerString);
389         PKIX_DECREF(subjectString);
390         PKIX_RETURN(VERIFYNODE);
391 }
392 
393 /*
394  * FUNCTION: pkix_VerifyNode_ToString_Helper
395  * DESCRIPTION:
396  *
397  *  Produces a String representation of a VerifyNode tree below the VerifyNode
398  *  pointed to by "rootNode", with each line of output prefixed by the String
399  *  pointed to by "indent", and stores the result at "pTreeString". It is
400  *  called recursively, with ever-increasing indentation, for successively
401  *  lower nodes on the tree.
402  *
403  * PARAMETERS:
404  *  "rootNode"
405  *      Address of VerifyNode subtree. Must be non-NULL.
406  *  "indent"
407  *      Address of String to be prefixed to each line of output. May be NULL
408  *      if no indentation is desired
409  *  "pTreeString"
410  *      Address where the resulting String will be stored; must be non-NULL
411  *  "plContext"
412  *      Platform-specific context pointer.
413  * THREAD SAFETY:
414  *  Conditionally Thread Safe
415  *  (see Thread Safety Definitions in Programmer's Guide)
416  * RETURNS:
417  *  Returns NULL if the function succeeds.
418  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
419  *  Returns a Fatal Error if the function fails in an unrecoverable way.
420  */
421 static PKIX_Error *
pkix_VerifyNode_ToString_Helper(PKIX_VerifyNode * rootNode,PKIX_PL_String * indent,PKIX_PL_String ** pTreeString,void * plContext)422 pkix_VerifyNode_ToString_Helper(
423         PKIX_VerifyNode *rootNode,
424         PKIX_PL_String *indent,
425         PKIX_PL_String **pTreeString,
426         void *plContext)
427 {
428         PKIX_PL_String *nextIndentFormat = NULL;
429         PKIX_PL_String *thisNodeFormat = NULL;
430         PKIX_PL_String *childrenFormat = NULL;
431         PKIX_PL_String *nextIndentString = NULL;
432         PKIX_PL_String *resultString = NULL;
433         PKIX_PL_String *thisItemString = NULL;
434         PKIX_PL_String *childString = NULL;
435         PKIX_VerifyNode *childNode = NULL;
436         PKIX_UInt32 numberOfChildren = 0;
437         PKIX_UInt32 childIndex = 0;
438 
439         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper");
440 
441         PKIX_NULLCHECK_TWO(rootNode, pTreeString);
442 
443         /* Create a string for this node */
444         PKIX_CHECK(pkix_SingleVerifyNode_ToString
445                 (rootNode, &thisItemString, plContext),
446                 PKIX_ERRORINSINGLEVERIFYNODETOSTRING);
447 
448         if (indent) {
449                 PKIX_CHECK(PKIX_PL_String_Create
450                         (PKIX_ESCASCII,
451                         "%s%s",
452                         0,
453                         &thisNodeFormat,
454                         plContext),
455                         PKIX_ERRORCREATINGFORMATSTRING);
456 
457                 PKIX_CHECK(PKIX_PL_Sprintf
458                         (&resultString,
459                         plContext,
460                         thisNodeFormat,
461                         indent,
462                         thisItemString),
463                         PKIX_ERRORINSPRINTF);
464         } else {
465                 PKIX_CHECK(PKIX_PL_String_Create
466                         (PKIX_ESCASCII,
467                         "%s",
468                         0,
469                         &thisNodeFormat,
470                         plContext),
471                         PKIX_ERRORCREATINGFORMATSTRING);
472 
473                 PKIX_CHECK(PKIX_PL_Sprintf
474                         (&resultString,
475                         plContext,
476                         thisNodeFormat,
477                         thisItemString),
478                         PKIX_ERRORINSPRINTF);
479         }
480 
481         PKIX_DECREF(thisItemString);
482         thisItemString = resultString;
483 
484         /* if no children, we are done */
485         if (rootNode->children) {
486                 PKIX_CHECK(PKIX_List_GetLength
487                         (rootNode->children, &numberOfChildren, plContext),
488                         PKIX_LISTGETLENGTHFAILED);
489         }
490 
491         if (numberOfChildren != 0) {
492                 /*
493                  * We create a string for each child in turn,
494                  * concatenating them to thisItemString.
495                  */
496 
497                 /* Prepare an indent string for each child */
498                 if (indent) {
499                         PKIX_CHECK(PKIX_PL_String_Create
500                                 (PKIX_ESCASCII,
501                                 "%s. ",
502                                 0,
503                                 &nextIndentFormat,
504                                 plContext),
505                                 PKIX_ERRORCREATINGFORMATSTRING);
506 
507                         PKIX_CHECK(PKIX_PL_Sprintf
508                                 (&nextIndentString,
509                                 plContext,
510                                 nextIndentFormat,
511                                 indent),
512                                 PKIX_ERRORINSPRINTF);
513                 } else {
514                         PKIX_CHECK(PKIX_PL_String_Create
515                                 (PKIX_ESCASCII,
516                                 ". ",
517                                 0,
518                                 &nextIndentString,
519                                 plContext),
520                                 PKIX_ERRORCREATINGINDENTSTRING);
521                 }
522 
523                 /* Prepare the format for concatenation. */
524                 PKIX_CHECK(PKIX_PL_String_Create
525                         (PKIX_ESCASCII,
526                         "%s\n%s",
527                         0,
528                         &childrenFormat,
529                         plContext),
530                         PKIX_ERRORCREATINGFORMATSTRING);
531 
532                 for (childIndex = 0;
533                         childIndex < numberOfChildren;
534                         childIndex++) {
535                         PKIX_CHECK(PKIX_List_GetItem
536                                 (rootNode->children,
537                                 childIndex,
538                                 (PKIX_PL_Object **)&childNode,
539                                 plContext),
540                                 PKIX_LISTGETITEMFAILED);
541 
542                         PKIX_CHECK(pkix_VerifyNode_ToString_Helper
543                                 (childNode,
544                                 nextIndentString,
545                                 &childString,
546                                 plContext),
547                                 PKIX_ERRORCREATINGCHILDSTRING);
548 
549 
550                         PKIX_CHECK(PKIX_PL_Sprintf
551                                 (&resultString,
552                                 plContext,
553                                 childrenFormat,
554                                 thisItemString,
555                                 childString),
556                         PKIX_ERRORINSPRINTF);
557 
558                         PKIX_DECREF(childNode);
559                         PKIX_DECREF(childString);
560                         PKIX_DECREF(thisItemString);
561 
562                         thisItemString = resultString;
563                 }
564         }
565 
566         *pTreeString = thisItemString;
567 
568 cleanup:
569         if (PKIX_ERROR_RECEIVED) {
570                 PKIX_DECREF(thisItemString);
571         }
572 
573         PKIX_DECREF(nextIndentFormat);
574         PKIX_DECREF(thisNodeFormat);
575         PKIX_DECREF(childrenFormat);
576         PKIX_DECREF(nextIndentString);
577         PKIX_DECREF(childString);
578         PKIX_DECREF(childNode);
579 
580         PKIX_RETURN(VERIFYNODE);
581 }
582 
583 /*
584  * FUNCTION: pkix_VerifyNode_ToString
585  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
586  */
587 static PKIX_Error *
pkix_VerifyNode_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pTreeString,void * plContext)588 pkix_VerifyNode_ToString(
589         PKIX_PL_Object *object,
590         PKIX_PL_String **pTreeString,
591         void *plContext)
592 {
593         PKIX_VerifyNode *rootNode = NULL;
594         PKIX_PL_String *resultString = NULL;
595 
596         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString");
597 
598         PKIX_NULLCHECK_TWO(object, pTreeString);
599 
600         PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
601                 PKIX_OBJECTNOTVERIFYNODE);
602 
603         rootNode = (PKIX_VerifyNode *)object;
604 
605         PKIX_CHECK(pkix_VerifyNode_ToString_Helper
606                 (rootNode, NULL, &resultString, plContext),
607                 PKIX_ERRORCREATINGSUBTREESTRING);
608 
609         *pTreeString = resultString;
610 
611 cleanup:
612 
613         PKIX_RETURN(VERIFYNODE);
614 }
615 
616 /*
617  * FUNCTION: pkix_VerifyNode_Destroy
618  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
619  */
620 static PKIX_Error *
pkix_VerifyNode_Destroy(PKIX_PL_Object * object,void * plContext)621 pkix_VerifyNode_Destroy(
622         PKIX_PL_Object *object,
623         void *plContext)
624 {
625         PKIX_VerifyNode *node = NULL;
626 
627         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy");
628 
629         PKIX_NULLCHECK_ONE(object);
630 
631         PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
632                 PKIX_OBJECTNOTVERIFYNODE);
633 
634         node = (PKIX_VerifyNode*)object;
635 
636         PKIX_DECREF(node->verifyCert);
637         PKIX_DECREF(node->children);
638         PKIX_DECREF(node->error);
639 
640         node->depth = 0;
641 
642 cleanup:
643 
644         PKIX_RETURN(VERIFYNODE);
645 }
646 
647 /*
648  * FUNCTION: pkix_SingleVerifyNode_Hashcode
649  * DESCRIPTION:
650  *
651  *  Computes the hashcode of the attributes of the VerifyNode pointed to by
652  *  "node", other than its parents and children, and stores the result at
653  *  "pHashcode".
654  *
655  * PARAMETERS:
656  *  "node"
657  *      Address of VerifyNode to be hashcoded; must be non-NULL
658  *  "pHashcode"
659  *      Address where UInt32 result will be stored; must be non-NULL
660  *  "plContext"
661  *      Platform-specific context pointer.
662  * THREAD SAFETY:
663  *  Conditionally Thread Safe
664  *  (see Thread Safety Definitions in Programmer's Guide)
665  * RETURNS:
666  *  Returns NULL if function succeeds
667  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
668  *  Returns a Fatal Error if the function fails in a fatal way
669  */
670 static PKIX_Error *
pkix_SingleVerifyNode_Hashcode(PKIX_VerifyNode * node,PKIX_UInt32 * pHashcode,void * plContext)671 pkix_SingleVerifyNode_Hashcode(
672         PKIX_VerifyNode *node,
673         PKIX_UInt32 *pHashcode,
674         void *plContext)
675 {
676         PKIX_UInt32 errorHash = 0;
677         PKIX_UInt32 nodeHash = 0;
678 
679         PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode");
680         PKIX_NULLCHECK_TWO(node, pHashcode);
681 
682         PKIX_HASHCODE
683                 (node->verifyCert,
684                 &nodeHash,
685                 plContext,
686                 PKIX_FAILUREHASHINGCERT);
687 
688         PKIX_CHECK(PKIX_PL_Object_Hashcode
689                 ((PKIX_PL_Object *)node->error,
690                 &errorHash,
691                 plContext),
692                 PKIX_FAILUREHASHINGERROR);
693 
694         nodeHash = 31*nodeHash + errorHash;
695         *pHashcode = nodeHash;
696 
697 cleanup:
698 
699         PKIX_RETURN(VERIFYNODE);
700 }
701 
702 /*
703  * FUNCTION: pkix_VerifyNode_Hashcode
704  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
705  */
706 static PKIX_Error *
pkix_VerifyNode_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)707 pkix_VerifyNode_Hashcode(
708         PKIX_PL_Object *object,
709         PKIX_UInt32 *pHashcode,
710         void *plContext)
711 {
712         PKIX_VerifyNode *node = NULL;
713         PKIX_UInt32 childrenHash = 0;
714         PKIX_UInt32 nodeHash = 0;
715 
716         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode");
717         PKIX_NULLCHECK_TWO(object, pHashcode);
718 
719         PKIX_CHECK(pkix_CheckType
720                 (object, PKIX_VERIFYNODE_TYPE, plContext),
721                 PKIX_OBJECTNOTVERIFYNODE);
722 
723         node = (PKIX_VerifyNode *)object;
724 
725         PKIX_CHECK(pkix_SingleVerifyNode_Hashcode
726                 (node, &nodeHash, plContext),
727                 PKIX_SINGLEVERIFYNODEHASHCODEFAILED);
728 
729         PKIX_HASHCODE
730                 (node->children,
731                 &childrenHash,
732                 plContext,
733                 PKIX_OBJECTHASHCODEFAILED);
734 
735         nodeHash = 31*nodeHash + childrenHash;
736 
737         *pHashcode = nodeHash;
738 
739 cleanup:
740 
741         PKIX_RETURN(VERIFYNODE);
742 }
743 
744 /*
745  * FUNCTION: pkix_SingleVerifyNode_Equals
746  * DESCRIPTION:
747  *
748  *  Compares for equality the components of the VerifyNode pointed to by
749  *  "firstPN", other than its parents and children, with those of the
750  *  VerifyNode pointed to by "secondPN" and stores the result at "pResult"
751  *  (PKIX_TRUE if equal; PKIX_FALSE if not).
752  *
753  * PARAMETERS:
754  *  "firstPN"
755  *      Address of first of the VerifyNodes to be compared; must be non-NULL
756  *  "secondPN"
757  *      Address of second of the VerifyNodes to be compared; must be non-NULL
758  *  "pResult"
759  *      Address where Boolean will be stored; must be non-NULL
760  *  "plContext"
761  *      Platform-specific context pointer.
762  * THREAD SAFETY:
763  *  Conditionally Thread Safe
764  *  (see Thread Safety Definitions in Programmer's Guide)
765  * RETURNS:
766  *  Returns NULL if function succeeds
767  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
768  *  Returns a Fatal Error if the function fails in a fatal way
769  */
770 static PKIX_Error *
pkix_SingleVerifyNode_Equals(PKIX_VerifyNode * firstVN,PKIX_VerifyNode * secondVN,PKIX_Boolean * pResult,void * plContext)771 pkix_SingleVerifyNode_Equals(
772         PKIX_VerifyNode *firstVN,
773         PKIX_VerifyNode *secondVN,
774         PKIX_Boolean *pResult,
775         void *plContext)
776 {
777         PKIX_Boolean compResult = PKIX_FALSE;
778 
779         PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals");
780         PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult);
781 
782         /* If both references are identical, they must be equal */
783         if (firstVN == secondVN) {
784                 compResult = PKIX_TRUE;
785                 goto cleanup;
786         }
787 
788         /*
789          * It seems we have to do the comparisons. Do
790          * the easiest ones first.
791          */
792         if ((firstVN->depth) != (secondVN->depth)) {
793                 goto cleanup;
794         }
795 
796         /* These fields must be non-NULL */
797         PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert);
798 
799         PKIX_EQUALS
800                 (firstVN->verifyCert,
801                 secondVN->verifyCert,
802                 &compResult,
803                 plContext,
804                 PKIX_OBJECTEQUALSFAILED);
805 
806         if (compResult == PKIX_FALSE) {
807                 goto cleanup;
808         }
809 
810         PKIX_EQUALS
811                 (firstVN->error,
812                 secondVN->error,
813                 &compResult,
814                 plContext,
815                 PKIX_OBJECTEQUALSFAILED);
816 
817 cleanup:
818 
819         *pResult = compResult;
820 
821         PKIX_RETURN(VERIFYNODE);
822 }
823 
824 /*
825  * FUNCTION: pkix_VerifyNode_Equals
826  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
827  */
828 static PKIX_Error *
pkix_VerifyNode_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)829 pkix_VerifyNode_Equals(
830         PKIX_PL_Object *firstObject,
831         PKIX_PL_Object *secondObject,
832         PKIX_Boolean *pResult,
833         void *plContext)
834 {
835         PKIX_VerifyNode *firstVN = NULL;
836         PKIX_VerifyNode *secondVN = NULL;
837         PKIX_UInt32 secondType;
838         PKIX_Boolean compResult = PKIX_FALSE;
839 
840         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals");
841         PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
842 
843         /* test that firstObject is a VerifyNode */
844         PKIX_CHECK(pkix_CheckType
845                 (firstObject, PKIX_VERIFYNODE_TYPE, plContext),
846                 PKIX_FIRSTOBJECTNOTVERIFYNODE);
847 
848         /*
849          * Since we know firstObject is a VerifyNode,
850          * if both references are identical, they must be equal
851          */
852         if (firstObject == secondObject){
853                 compResult = PKIX_TRUE;
854                 goto cleanup;
855         }
856 
857         /*
858          * If secondObject isn't a VerifyNode, we
859          * don't throw an error. We simply return FALSE.
860          */
861         PKIX_CHECK(PKIX_PL_Object_GetType
862                     (secondObject, &secondType, plContext),
863                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
864 
865         if (secondType != PKIX_VERIFYNODE_TYPE) {
866                 goto cleanup;
867         }
868 
869         /*
870          * Oh, well, we have to do the comparisons. Do
871          * the easiest ones first.
872          */
873         firstVN = (PKIX_VerifyNode *)firstObject;
874         secondVN = (PKIX_VerifyNode *)secondObject;
875 
876         PKIX_CHECK(pkix_SingleVerifyNode_Equals
877                 (firstVN, secondVN, &compResult, plContext),
878                 PKIX_SINGLEVERIFYNODEEQUALSFAILED);
879 
880         if (compResult == PKIX_FALSE) {
881                 goto cleanup;
882         }
883 
884         PKIX_EQUALS
885                 (firstVN->children,
886                 secondVN->children,
887                 &compResult,
888                 plContext,
889                 PKIX_OBJECTEQUALSFAILEDONCHILDREN);
890 
891 cleanup:
892 
893         *pResult = compResult;
894 
895         PKIX_RETURN(VERIFYNODE);
896 }
897 
898 /*
899  * FUNCTION: pkix_VerifyNode_DuplicateHelper
900  * DESCRIPTION:
901  *
902  *  Duplicates the VerifyNode whose address is pointed to by "original",
903  *  and stores the result at "pNewNode", if a non-NULL pointer is provided
904  *  for "pNewNode". In addition, the created VerifyNode is added as a child
905  *  to "parent", if a non-NULL pointer is provided for "parent". Then this
906  *  function is called recursively to duplicate each of the children of
907  *  "original". At the top level this function is called with a null
908  *  "parent" and a non-NULL "pNewNode". Below the top level "parent" will
909  *  be non-NULL and "pNewNode" will be NULL.
910  *
911  * PARAMETERS:
912  *  "original"
913  *      Address of VerifyNode to be copied; must be non-NULL
914  *  "parent"
915  *      Address of VerifyNode to which the created node is to be added as a
916  *      child; NULL for the top-level call and non-NULL below the top level
917  *  "pNewNode"
918  *      Address to store the node created; should be NULL if "parent" is
919  *      non-NULL and vice versa
920  *  "plContext"
921  *      Platform-specific context pointer.
922  * THREAD SAFETY:
923  *  Conditionally Thread Safe
924  *  (see Thread Safety Definitions in Programmer's Guide)
925  * RETURNS:
926  *  Returns NULL if function succeeds
927  *  Returns a VerifyNode Error if the function fails in a non-fatal way.
928  *  Returns a Fatal Error if the function fails in a fatal way
929  */
930 static PKIX_Error *
pkix_VerifyNode_DuplicateHelper(PKIX_VerifyNode * original,PKIX_VerifyNode * parent,PKIX_VerifyNode ** pNewNode,void * plContext)931 pkix_VerifyNode_DuplicateHelper(
932         PKIX_VerifyNode *original,
933         PKIX_VerifyNode *parent,
934         PKIX_VerifyNode **pNewNode,
935         void *plContext)
936 {
937         PKIX_UInt32 numChildren = 0;
938         PKIX_UInt32 childIndex = 0;
939         PKIX_List *children = NULL; /* List of PKIX_VerifyNode */
940         PKIX_VerifyNode *copy = NULL;
941         PKIX_VerifyNode *child = NULL;
942 
943         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper");
944 
945         PKIX_NULLCHECK_TWO
946                 (original, original->verifyCert);
947 
948         /*
949          * These components are immutable, so copying the pointers
950          * is sufficient. The create function increments the reference
951          * counts as it stores the pointers into the new object.
952          */
953         PKIX_CHECK(pkix_VerifyNode_Create
954                 (original->verifyCert,
955                 original->depth,
956                 original->error,
957                 &copy,
958                 plContext),
959                 PKIX_VERIFYNODECREATEFAILED);
960 
961         /* Are there any children to duplicate? */
962         children = original->children;
963 
964         if (children) {
965             PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
966                 PKIX_LISTGETLENGTHFAILED);
967         }
968 
969         for (childIndex = 0; childIndex < numChildren; childIndex++) {
970                 PKIX_CHECK(PKIX_List_GetItem
971                         (children,
972                         childIndex,
973                         (PKIX_PL_Object **)&child,
974                         plContext),
975                         PKIX_LISTGETITEMFAILED);
976 
977                 PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
978                         (child, copy, NULL, plContext),
979                         PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
980 
981                 PKIX_DECREF(child);
982         }
983 
984         if (pNewNode) {
985                 *pNewNode = copy;
986                 copy = NULL; /* no DecRef if we give our handle away */
987         }
988 
989 cleanup:
990         PKIX_DECREF(copy);
991         PKIX_DECREF(child);
992 
993         PKIX_RETURN(VERIFYNODE);
994 }
995 
996 /*
997  * FUNCTION: pkix_VerifyNode_Duplicate
998  * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
999  */
1000 static PKIX_Error *
pkix_VerifyNode_Duplicate(PKIX_PL_Object * object,PKIX_PL_Object ** pNewObject,void * plContext)1001 pkix_VerifyNode_Duplicate(
1002         PKIX_PL_Object *object,
1003         PKIX_PL_Object **pNewObject,
1004         void *plContext)
1005 {
1006         PKIX_VerifyNode *original = NULL;
1007         PKIX_VerifyNode *copy = NULL;
1008 
1009         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate");
1010 
1011         PKIX_NULLCHECK_TWO(object, pNewObject);
1012 
1013         PKIX_CHECK(pkix_CheckType
1014                 (object, PKIX_VERIFYNODE_TYPE, plContext),
1015                 PKIX_OBJECTNOTVERIFYNODE);
1016 
1017         original = (PKIX_VerifyNode *)object;
1018 
1019         PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
1020                 (original, NULL, &copy, plContext),
1021                 PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
1022 
1023         *pNewObject = (PKIX_PL_Object *)copy;
1024 
1025 cleanup:
1026 
1027         PKIX_RETURN(VERIFYNODE);
1028 }
1029 
1030 /*
1031  * FUNCTION: pkix_VerifyNode_RegisterSelf
1032  * DESCRIPTION:
1033  *
1034  *  Registers PKIX_VERIFYNODE_TYPE and its related
1035  *  functions with systemClasses[]
1036  *
1037  * THREAD SAFETY:
1038  *  Not Thread Safe - for performance and complexity reasons
1039  *
1040  *  Since this function is only called by PKIX_PL_Initialize,
1041  *  which should only be called once, it is acceptable that
1042  *  this function is not thread-safe.
1043  */
1044 PKIX_Error *
pkix_VerifyNode_RegisterSelf(void * plContext)1045 pkix_VerifyNode_RegisterSelf(void *plContext)
1046 {
1047 
1048         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1049         pkix_ClassTable_Entry entry;
1050 
1051         PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf");
1052 
1053         entry.description = "VerifyNode";
1054         entry.objCounter = 0;
1055         entry.typeObjectSize = sizeof(PKIX_VerifyNode);
1056         entry.destructor = pkix_VerifyNode_Destroy;
1057         entry.equalsFunction = pkix_VerifyNode_Equals;
1058         entry.hashcodeFunction = pkix_VerifyNode_Hashcode;
1059         entry.toStringFunction = pkix_VerifyNode_ToString;
1060         entry.comparator = NULL;
1061         entry.duplicateFunction = pkix_VerifyNode_Duplicate;
1062 
1063         systemClasses[PKIX_VERIFYNODE_TYPE] = entry;
1064 
1065         PKIX_RETURN(VERIFYNODE);
1066 }
1067 
1068 /* --Public-VerifyNode-Functions----------------------------------- */
1069 
1070 /*
1071  * FUNCTION: PKIX_VerifyNode_SetError
1072  * DESCRIPTION:
1073  *
1074  *  This function sets the Error field of the VerifyNode pointed to by "node"
1075  *  to contain the Error pointed to by "error".
1076  *
1077  * PARAMETERS:
1078  *  "node"
1079  *      The address of the VerifyNode to be modified. Must be non-NULL.
1080  *  "error"
1081  *      The address of the Error to be stored.
1082  *  "plContext"
1083  *      Platform-specific context pointer.
1084  * THREAD SAFETY:
1085  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1086  * RETURNS:
1087  *  Returns NULL if the function succeeds.
1088  *  Returns a Fatal Error if the function fails in an unrecoverable way.
1089  */
1090 PKIX_Error *
pkix_VerifyNode_SetError(PKIX_VerifyNode * node,PKIX_Error * error,void * plContext)1091 pkix_VerifyNode_SetError(
1092         PKIX_VerifyNode *node,
1093         PKIX_Error *error,
1094         void *plContext)
1095 {
1096 
1097         PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError");
1098 
1099         PKIX_NULLCHECK_TWO(node, error);
1100 
1101         PKIX_DECREF(node->error); /* should have been NULL */
1102         PKIX_INCREF(error);
1103         node->error = error;
1104 
1105 cleanup:
1106         PKIX_RETURN(VERIFYNODE);
1107 }
1108 
1109 /*
1110  * FUNCTION: PKIX_VerifyNode_FindError
1111  * DESCRIPTION:
1112  *
1113  * Finds meaningful error in the log. For now, just returns the first
1114  * error it finds in. In the future the function should be changed to
1115  * return a top priority error.
1116  *
1117  * PARAMETERS:
1118  *  "node"
1119  *      The address of the VerifyNode to be modified. Must be non-NULL.
1120  *  "error"
1121  *      The address of a pointer the error will be returned to.
1122  *  "plContext"
1123  *      Platform-specific context pointer.
1124  * THREAD SAFETY:
1125  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1126  * RETURNS:
1127  *  Returns NULL if the function succeeds.
1128  *  Returns a Fatal Error if the function fails in an unrecoverable way.
1129  */
1130 PKIX_Error *
pkix_VerifyNode_FindError(PKIX_VerifyNode * node,PKIX_Error ** error,void * plContext)1131 pkix_VerifyNode_FindError(
1132         PKIX_VerifyNode *node,
1133         PKIX_Error **error,
1134         void *plContext)
1135 {
1136     PKIX_VerifyNode *childNode = NULL;
1137 
1138     PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError");
1139 
1140     /* Make sure the return address is initialized with NULL */
1141     PKIX_DECREF(*error);
1142 
1143     if (!node)
1144         goto cleanup;
1145 
1146     /* First, try to get error from lowest level. */
1147     if (node->children) {
1148         PKIX_UInt32 length = 0;
1149         PKIX_UInt32 index = 0;
1150 
1151         PKIX_CHECK(
1152             PKIX_List_GetLength(node->children, &length,
1153                                 plContext),
1154             PKIX_LISTGETLENGTHFAILED);
1155         for (index = 0;index < length;index++) {
1156             PKIX_CHECK(
1157                 PKIX_List_GetItem(node->children, index,
1158                                   (PKIX_PL_Object**)&childNode, plContext),
1159                 PKIX_LISTGETITEMFAILED);
1160             if (!childNode)
1161                 continue;
1162             PKIX_CHECK(
1163                 pkix_VerifyNode_FindError(childNode, error,
1164                                           plContext),
1165                 PKIX_VERIFYNODEFINDERRORFAILED);
1166             PKIX_DECREF(childNode);
1167             if (*error) {
1168                 goto cleanup;
1169             }
1170         }
1171     }
1172 
1173     if (node->error && node->error->plErr) {
1174         PKIX_INCREF(node->error);
1175         *error = node->error;
1176     }
1177 
1178 cleanup:
1179     PKIX_DECREF(childNode);
1180 
1181     PKIX_RETURN(VERIFYNODE);
1182 }
1183