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 ©, 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, ©, 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 }