tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_verifynode.c (36688B)


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