pkix_pl_common.c (37447B)
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_common.c 6 * 7 * Common utility functions used by various PKIX_PL functions 8 * 9 */ 10 11 #include "pkix_pl_common.h" 12 13 /* --Private-Functions-------------------------------------------- */ 14 15 /* 16 * FUNCTION: pkix_LockObject 17 * DESCRIPTION: 18 * 19 * Locks the object pointed to by "object". 20 * 21 * PARAMETERS: 22 * "object" 23 * Address of object. Must be non-NULL 24 * "plContext" 25 * Platform-specific context pointer. 26 * THREAD SAFETY: 27 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 28 * RETURNS: 29 * Returns NULL if the function succeeds 30 * Returns a Fatal Error if the function fails in an unrecoverable way. 31 */ 32 PKIX_Error * 33 pkix_LockObject( 34 PKIX_PL_Object *object, 35 void *plContext) 36 { 37 PKIX_PL_Object *objectHeader; 38 39 PKIX_ENTER(OBJECT, "pkix_LockObject"); 40 PKIX_NULLCHECK_ONE(object); 41 42 if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) { 43 goto cleanup; 44 } 45 46 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); 47 /* The header is sizeof(PKIX_PL_Object) before the object pointer */ 48 49 objectHeader = object-1; 50 51 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); 52 PR_Lock(objectHeader->lock); 53 54 cleanup: 55 56 PKIX_RETURN(OBJECT); 57 } 58 59 /* 60 * FUNCTION: pkix_UnlockObject 61 * DESCRIPTION: 62 * 63 * Unlocks the object pointed to by "object". 64 * 65 * PARAMETERS: 66 * "object" 67 * Address of Object. Must be non-NULL 68 * "plContext" 69 * Platform-specific context pointer. 70 * THREAD SAFETY: 71 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 72 * RETURNS: 73 * Returns NULL if the function succeeds. 74 * Returns a Fatal Error if the function fails in an unrecoverable way. 75 */ 76 PKIX_Error * 77 pkix_UnlockObject( 78 PKIX_PL_Object *object, 79 void *plContext) 80 { 81 PKIX_PL_Object *objectHeader; 82 PRStatus result; 83 84 PKIX_ENTER(OBJECT, "pkix_UnlockObject"); 85 PKIX_NULLCHECK_ONE(object); 86 87 if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) { 88 goto cleanup; 89 } 90 91 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); 92 /* The header is sizeof(PKIX_PL_Object) before the object pointer */ 93 94 objectHeader = object-1; 95 96 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); 97 result = PR_Unlock(objectHeader->lock); 98 99 if (result == PR_FAILURE) { 100 PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n"); 101 PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT); 102 } 103 104 cleanup: 105 106 PKIX_RETURN(OBJECT); 107 } 108 109 /* 110 * FUNCTION: pkix_pl_UInt32_Overflows 111 * DESCRIPTION: 112 * 113 * Returns a PKIX_Boolean indicating whether the unsigned integer 114 * represented by "string" is too large to fit in 32-bits (i.e. 115 * whether it overflows). With the exception of the string "0", 116 * all other strings are stripped of any leading zeros. It is assumed 117 * that every character in "string" is from the set {'0' - '9'}. 118 * 119 * PARAMETERS 120 * "string" 121 * Address of array of bytes representing PKIX_UInt32 that's being tested 122 * for 32-bit overflow 123 * THREAD SAFETY: 124 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 125 * RETURNS: 126 * PKIX_TRUE if PKIX_UInt32 represented by "string" overflows; 127 * PKIX_FALSE otherwise 128 */ 129 PKIX_Boolean 130 pkix_pl_UInt32_Overflows(char *string){ 131 char *firstNonZero = NULL; 132 PKIX_UInt32 length, i; 133 char *MAX_UINT32_STRING = "4294967295"; 134 135 PKIX_DEBUG_ENTER(OID); 136 137 PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); 138 length = PL_strlen(string); 139 140 if (length < MAX_DIGITS_32){ 141 return (PKIX_FALSE); 142 } 143 144 firstNonZero = string; 145 for (i = 0; i < length; i++){ 146 if (*string == '0'){ 147 firstNonZero++; 148 } 149 } 150 151 PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); 152 length = PL_strlen(firstNonZero); 153 154 if (length > MAX_DIGITS_32){ 155 return (PKIX_TRUE); 156 } 157 158 PKIX_OID_DEBUG("\tCalling PL_strlen).\n"); 159 if (length == MAX_DIGITS_32){ 160 PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n"); 161 if (PORT_Strcmp(firstNonZero, MAX_UINT32_STRING) > 0){ 162 return (PKIX_TRUE); 163 } 164 } 165 166 return (PKIX_FALSE); 167 } 168 169 /* 170 * FUNCTION: pkix_pl_getOIDToken 171 * DESCRIPTION: 172 * 173 * Takes the array of DER-encoded bytes pointed to by "derBytes" 174 * (representing an OID) and the value of "index" representing the index into 175 * the array, and decodes the bytes until an integer token is retrieved. If 176 * successful, this function stores the integer component at "pToken" and 177 * stores the index representing the next byte in the array at "pIndex" 178 * (following the last byte that was used in the decoding). This new output 179 * index can be used in subsequent calls as an input index, allowing each 180 * token of the OID to be retrieved consecutively. Note that there is a 181 * special case for the first byte, in that it encodes two separate integer 182 * tokens. For example, the byte {2a} represents the integer tokens {1,2}. 183 * This special case is not handled here and must be handled by the caller. 184 * 185 * PARAMETERS 186 * "derBytes" 187 * Address of array of bytes representing a DER-encoded OID. 188 * Must be non-NULL. 189 * "index" 190 * Index into the array that this function will begin decoding at. 191 * "pToken" 192 * Destination for decoded OID token. Must be non-NULL. 193 * "pIndex" 194 * Destination for index of next byte following last byte used. 195 * Must be non-NULL. 196 * "plContext" 197 * Platform-specific context pointer. 198 * THREAD SAFETY: 199 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 200 * RETURNS: 201 * Returns NULL if the function succeeds. 202 * Returns an Object Error if the function fails in a non-fatal way. 203 * Returns a Fatal Error if the function fails in an unrecoverable way. 204 */ 205 static PKIX_Error * 206 pkix_pl_getOIDToken( 207 char *derBytes, 208 PKIX_UInt32 index, 209 PKIX_UInt32 *pToken, 210 PKIX_UInt32 *pIndex, 211 void *plContext) 212 { 213 PKIX_UInt32 retval, i, tmp; 214 215 PKIX_ENTER(OID, "pkix_pl_getOIDToken"); 216 PKIX_NULLCHECK_THREE(derBytes, pToken, pIndex); 217 218 /* 219 * We should only need to parse a maximum of four bytes, because 220 * RFC 3280 "mandates support for OIDs which have arc elements 221 * with values that are less than 2^28, that is, they MUST be between 222 * 0 and 268,435,455, inclusive. This allows each arc element to be 223 * represented within a single 32 bit word." 224 */ 225 226 for (i = 0, retval = 0; i < 4; i++) { 227 retval <<= 7; 228 tmp = derBytes[index]; 229 index++; 230 retval |= (tmp & 0x07f); 231 if ((tmp & 0x080) == 0){ 232 *pToken = retval; 233 *pIndex = index; 234 goto cleanup; 235 } 236 } 237 238 PKIX_ERROR(PKIX_INVALIDENCODINGOIDTOKENVALUETOOBIG); 239 240 cleanup: 241 242 PKIX_RETURN(OID); 243 244 } 245 246 /* 247 * FUNCTION: pkix_pl_helperBytes2Ascii 248 * DESCRIPTION: 249 * 250 * Converts an array of integers pointed to by "tokens" with a length of 251 * "numTokens", to an ASCII string consisting of those integers with dots in 252 * between them and stores the result at "pAscii". The ASCII representation is 253 * guaranteed to end with a NUL character. This is particularly useful for 254 * OID's and IP Addresses. 255 * 256 * The return value "pAscii" is not reference-counted and will need to 257 * be freed with PKIX_PL_Free. 258 * 259 * PARAMETERS 260 * "tokens" 261 * Address of array of integers. Must be non-NULL. 262 * "numTokens" 263 * Length of array of integers. Must be non-zero. 264 * "pAscii" 265 * Address where object pointer will be stored. Must be non-NULL. 266 * "plContext" 267 * Platform-specific context pointer. 268 * THREAD SAFETY: 269 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 270 * RETURNS: 271 * Returns NULL if the function succeeds. 272 * Returns an Object Error if the function fails in a non-fatal way. 273 * Returns a Fatal Error if the function fails in an unrecoverable way. 274 */ 275 PKIX_Error * 276 pkix_pl_helperBytes2Ascii( 277 PKIX_UInt32 *tokens, 278 PKIX_UInt32 numTokens, 279 char **pAscii, 280 void *plContext) 281 { 282 char *tempString = NULL; 283 char *outputString = NULL; 284 char *format = "%d"; 285 PKIX_UInt32 i = 0; 286 PKIX_UInt32 outputLen = 0; 287 PKIX_Int32 error; 288 289 PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii"); 290 PKIX_NULLCHECK_TWO(tokens, pAscii); 291 292 if (numTokens == 0) { 293 PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO); 294 } 295 296 /* 297 * tempString will hold the string representation of a PKIX_UInt32 type 298 * The maximum value that can be held by an unsigned 32-bit integer 299 * is (2^32 - 1) = 4294967295 (which is ten digits long) 300 * Since tempString will hold the string representation of a 301 * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0') 302 */ 303 304 PKIX_CHECK(PKIX_PL_Malloc 305 (MAX_DIGITS_32 + 1, (void **)&tempString, plContext), 306 PKIX_MALLOCFAILED); 307 308 for (i = 0; i < numTokens; i++){ 309 PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); 310 error = PR_snprintf(tempString, 311 MAX_DIGITS_32 + 1, 312 format, 313 tokens[i]); 314 if (error == -1){ 315 PKIX_ERROR(PKIX_PRSNPRINTFFAILED); 316 } 317 318 PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n"); 319 outputLen += PL_strlen(tempString); 320 321 /* Include a dot to separate each number */ 322 outputLen++; 323 } 324 325 /* Allocate space for the destination string */ 326 PKIX_CHECK(PKIX_PL_Malloc 327 (outputLen, (void **)&outputString, plContext), 328 PKIX_MALLOCFAILED); 329 330 *outputString = '\0'; 331 332 /* Concatenate all strings together */ 333 for (i = 0; i < numTokens; i++){ 334 335 PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); 336 error = PR_snprintf(tempString, 337 MAX_DIGITS_32 + 1, 338 format, 339 tokens[i]); 340 if (error == -1){ 341 PKIX_ERROR(PKIX_PRSNPRINTFFAILED); 342 } 343 344 PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); 345 (void) PL_strcat(outputString, tempString); 346 347 /* we don't want to put a "." at the very end */ 348 if (i < (numTokens - 1)){ 349 PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); 350 (void) PL_strcat(outputString, "."); 351 } 352 } 353 354 /* Ensure output string ends with terminating null */ 355 outputString[outputLen-1] = '\0'; 356 357 *pAscii = outputString; 358 outputString = NULL; 359 360 cleanup: 361 362 PKIX_FREE(outputString); 363 PKIX_FREE(tempString); 364 365 PKIX_RETURN(OBJECT); 366 367 } 368 369 /* 370 * FUNCTION: pkix_pl_ipAddrBytes2Ascii 371 * DESCRIPTION: 372 * 373 * Converts the DER encoding of an IPAddress pointed to by "secItem" to an 374 * ASCII representation and stores the result at "pAscii". The ASCII 375 * representation is guaranteed to end with a NUL character. The input 376 * SECItem must contain non-NULL data and must have a positive length. 377 * 378 * The return value "pAscii" is not reference-counted and will need to 379 * be freed with PKIX_PL_Free. 380 * XXX this function assumes that IPv4 addresses are being used 381 * XXX what about IPv6? can NSS tell the difference 382 * 383 * PARAMETERS 384 * "secItem" 385 * Address of SECItem which contains bytes and length of DER encoding. 386 * Must be non-NULL. 387 * "pAscii" 388 * Address where object pointer will be stored. Must be non-NULL. 389 * "plContext" 390 * Platform-specific context pointer. 391 * THREAD SAFETY: 392 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 393 * RETURNS: 394 * Returns NULL if the function succeeds. 395 * Returns an Object Error if the function fails in a non-fatal way. 396 * Returns a Fatal Error if the function fails in an unrecoverable way. 397 */ 398 PKIX_Error * 399 pkix_pl_ipAddrBytes2Ascii( 400 SECItem *secItem, 401 char **pAscii, 402 void *plContext) 403 { 404 char *data = NULL; 405 PKIX_UInt32 *tokens = NULL; 406 PKIX_UInt32 numTokens = 0; 407 PKIX_UInt32 i = 0; 408 char *asciiString = NULL; 409 410 PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii"); 411 PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); 412 413 if (secItem->len == 0) { 414 PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO); 415 } 416 417 data = (char *)(secItem->data); 418 numTokens = secItem->len; 419 420 /* allocate space for array of integers */ 421 PKIX_CHECK(PKIX_PL_Malloc 422 (numTokens * sizeof (PKIX_UInt32), 423 (void **)&tokens, 424 plContext), 425 PKIX_MALLOCFAILED); 426 427 /* populate array of integers */ 428 for (i = 0; i < numTokens; i++){ 429 tokens[i] = data[i]; 430 } 431 432 /* convert array of integers to ASCII */ 433 PKIX_CHECK(pkix_pl_helperBytes2Ascii 434 (tokens, numTokens, &asciiString, plContext), 435 PKIX_HELPERBYTES2ASCIIFAILED); 436 437 *pAscii = asciiString; 438 439 cleanup: 440 441 PKIX_FREE(tokens); 442 443 PKIX_RETURN(OBJECT); 444 } 445 446 447 /* 448 * FUNCTION: pkix_pl_oidBytes2Ascii 449 * DESCRIPTION: 450 * 451 * Converts the DER encoding of an OID pointed to by "secItem" to an ASCII 452 * representation and stores it at "pAscii". The ASCII representation is 453 * guaranteed to end with a NUL character. The input SECItem must contain 454 * non-NULL data and must have a positive length. 455 * 456 * Example: the six bytes {2a 86 48 86 f7 0d} represent the 457 * four integer tokens {1, 2, 840, 113549}, which we will convert 458 * into ASCII yielding "1.2.840.113549" 459 * 460 * The return value "pAscii" is not reference-counted and will need to 461 * be freed with PKIX_PL_Free. 462 * 463 * PARAMETERS 464 * "secItem" 465 * Address of SECItem which contains bytes and length of DER encoding. 466 * Must be non-NULL. 467 * "pAscii" 468 * Address where object pointer will be stored. Must be non-NULL. 469 * "plContext" 470 * Platform-specific context pointer. 471 * THREAD SAFETY: 472 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 473 * RETURNS: 474 * Returns NULL if the function succeeds. 475 * Returns an OID Error if the function fails in a non-fatal way. 476 * Returns a Fatal Error if the function fails in an unrecoverable way. 477 */ 478 PKIX_Error * 479 pkix_pl_oidBytes2Ascii( 480 SECItem *secItem, 481 char **pAscii, 482 void *plContext) 483 { 484 char *data = NULL; 485 PKIX_UInt32 *tokens = NULL; 486 PKIX_UInt32 token = 0; 487 PKIX_UInt32 numBytes = 0; 488 PKIX_UInt32 numTokens = 0; 489 PKIX_UInt32 i = 0, x = 0, y = 0; 490 PKIX_UInt32 index = 0; 491 char *asciiString = NULL; 492 493 PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii"); 494 PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); 495 496 if (secItem->len == 0) { 497 PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO); 498 } 499 500 data = (char *)(secItem->data); 501 numBytes = secItem->len; 502 numTokens = 0; 503 504 /* calculate how many integer tokens are represented by the bytes. */ 505 for (i = 0; i < numBytes; i++){ 506 if ((data[i] & 0x080) == 0){ 507 numTokens++; 508 } 509 } 510 511 /* if we are unable to retrieve any tokens at all, we throw an error */ 512 if (numTokens == 0){ 513 PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID); 514 } 515 516 /* add one more token b/c the first byte always contains two tokens */ 517 numTokens++; 518 519 /* allocate space for array of integers */ 520 PKIX_CHECK(PKIX_PL_Malloc 521 (numTokens * sizeof (PKIX_UInt32), 522 (void **)&tokens, 523 plContext), 524 PKIX_MALLOCFAILED); 525 526 /* populate array of integers */ 527 for (i = 0; i < numTokens; i++){ 528 529 /* retrieve integer token */ 530 PKIX_CHECK(pkix_pl_getOIDToken 531 (data, index, &token, &index, plContext), 532 PKIX_GETOIDTOKENFAILED); 533 534 if (i == 0){ 535 536 /* 537 * special case: the first DER-encoded byte represents 538 * two tokens. We take advantage of fact that first 539 * token must be 0, 1, or 2; and second token must be 540 * between {0, 39} inclusive if first token is 0 or 1. 541 */ 542 543 if (token < 40) 544 x = 0; 545 else if (token < 80) 546 x = 1; 547 else 548 x = 2; 549 y = token - (x * 40); 550 551 tokens[0] = x; 552 tokens[1] = y; 553 i++; 554 } else { 555 tokens[i] = token; 556 } 557 } 558 559 /* convert array of integers to ASCII */ 560 PKIX_CHECK(pkix_pl_helperBytes2Ascii 561 (tokens, numTokens, &asciiString, plContext), 562 PKIX_HELPERBYTES2ASCIIFAILED); 563 564 *pAscii = asciiString; 565 566 cleanup: 567 568 PKIX_FREE(tokens); 569 PKIX_RETURN(OID); 570 571 } 572 573 /* 574 * FUNCTION: pkix_UTF16_to_EscASCII 575 * DESCRIPTION: 576 * 577 * Converts array of bytes pointed to by "utf16String" with length of 578 * "utf16Length" (which must be even) into a freshly allocated Escaped ASCII 579 * string and stores a pointer to that string at "pDest" and stores the 580 * string's length at "pLength". The Escaped ASCII string's length does not 581 * include the final NUL character. The caller is responsible for freeing 582 * "pDest" using PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug 583 * encoding. 584 * 585 * PARAMETERS: 586 * "utf16String" 587 * Address of array of bytes representing data source. Must be non-NULL. 588 * "utf16Length" 589 * Length of data source. Must be even. 590 * "debug" 591 * Boolean value indicating whether debug mode is desired. 592 * "pDest" 593 * Address where data will be stored. Must be non-NULL. 594 * "pLength" 595 * Address where data length will be stored. Must be non-NULL. 596 * "plContext" 597 * Platform-specific context pointer. 598 * THREAD SAFETY: 599 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 600 * RETURNS: 601 * Returns NULL if the function succeeds. 602 * Returns a String Error if the function fails in a non-fatal way. 603 * Returns a Fatal Error if the function fails in an unrecoverable way. 604 */ 605 PKIX_Error * 606 pkix_UTF16_to_EscASCII( 607 const void *utf16String, 608 PKIX_UInt32 utf16Length, 609 PKIX_Boolean debug, 610 char **pDest, 611 PKIX_UInt32 *pLength, 612 void *plContext) 613 { 614 char *destPtr = NULL; 615 PKIX_UInt32 i, charLen; 616 PKIX_UInt32 x = 0, y = 0, z = 0; 617 unsigned char *utf16Char = (unsigned char *)utf16String; 618 619 PKIX_ENTER(STRING, "pkix_UTF16_to_EscASCII"); 620 PKIX_NULLCHECK_THREE(utf16String, pDest, pLength); 621 622 /* Assume every pair of bytes becomes &#xNNNN; */ 623 charLen = 4*utf16Length; 624 625 /* utf16Lenght must be even */ 626 if ((utf16Length % 2) != 0){ 627 PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR); 628 } 629 630 /* Count how many bytes we need */ 631 for (i = 0; i < utf16Length; i += 2) { 632 if ((utf16Char[i] == 0x00)&& 633 pkix_isPlaintext(utf16Char[i+1], debug)) { 634 if (utf16Char[i+1] == '&') { 635 /* Need to convert this to & */ 636 charLen -= 3; 637 } else { 638 /* We can fit this into one char */ 639 charLen -= 7; 640 } 641 } else if ((utf16Char[i] >= 0xD8) && (utf16Char[i] <= 0xDB)) { 642 if ((i+3) >= utf16Length) { 643 PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR); 644 } else if ((utf16Char[i+2] >= 0xDC)&& 645 (utf16Char[i+2] <= 0xDF)) { 646 /* Quartet of bytes will become &#xNNNNNNNN; */ 647 charLen -= 4; 648 /* Quartet of bytes will produce 12 chars */ 649 i += 2; 650 } else { 651 /* Second pair should be DC00-DFFF */ 652 PKIX_ERROR(PKIX_UTF16LOWZONEERROR); 653 } 654 } 655 } 656 657 *pLength = charLen; 658 659 /* Ensure this string is null terminated */ 660 charLen++; 661 662 /* Allocate space for character array */ 663 PKIX_CHECK(PKIX_PL_Malloc(charLen, (void **)pDest, plContext), 664 PKIX_MALLOCFAILED); 665 666 destPtr = *pDest; 667 for (i = 0; i < utf16Length; i += 2) { 668 if ((utf16Char[i] == 0x00)&& 669 pkix_isPlaintext(utf16Char[i+1], debug)) { 670 /* Write a single character */ 671 *destPtr++ = utf16Char[i+1]; 672 } else if ((utf16Char[i+1] == '&') && (utf16Char[i] == 0x00)){ 673 *destPtr++ = '&'; 674 *destPtr++ = 'a'; 675 *destPtr++ = 'm'; 676 *destPtr++ = 'p'; 677 *destPtr++ = ';'; 678 } else if ((utf16Char[i] >= 0xD8)&& 679 (utf16Char[i] <= 0xDB)&& 680 (utf16Char[i+2] >= 0xDC)&& 681 (utf16Char[i+2] <= 0xDF)) { 682 /* 683 * Special UTF pairs are of the form: 684 * x = D800..DBFF; y = DC00..DFFF; 685 * The result is of the form: 686 * ((x - D800) * 400 + (y - DC00)) + 0001 0000 687 */ 688 x = 0x0FFFF & ((utf16Char[i]<<8) | utf16Char[i+1]); 689 y = 0x0FFFF & ((utf16Char[i+2]<<8) | utf16Char[i+3]); 690 z = ((x - 0xD800) * 0x400 + (y - 0xDC00)) + 0x00010000; 691 692 /* Sprintf &#xNNNNNNNN; */ 693 PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n"); 694 if (PR_snprintf(destPtr, 13, "&#x%08X;", z) == 695 (PKIX_UInt32)(-1)) { 696 PKIX_ERROR(PKIX_PRSNPRINTFFAILED); 697 } 698 i += 2; 699 destPtr += 12; 700 } else { 701 /* Sprintf &#xNNNN; */ 702 PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n"); 703 if (PR_snprintf 704 (destPtr, 705 9, 706 "&#x%02X%02X;", 707 utf16Char[i], 708 utf16Char[i+1]) == 709 (PKIX_UInt32)(-1)) { 710 PKIX_ERROR(PKIX_PRSNPRINTFFAILED); 711 } 712 destPtr += 8; 713 } 714 } 715 *destPtr = '\0'; 716 717 cleanup: 718 719 if (PKIX_ERROR_RECEIVED){ 720 PKIX_FREE(*pDest); 721 } 722 723 PKIX_RETURN(STRING); 724 } 725 726 /* 727 * FUNCTION: pkix_EscASCII_to_UTF16 728 * DESCRIPTION: 729 * 730 * Converts array of bytes pointed to by "escAsciiString" with length of 731 * "escAsciiLength" into a freshly allocated UTF-16 string and stores a 732 * pointer to that string at "pDest" and stores the string's length at 733 * "pLength". The caller is responsible for freeing "pDest" using 734 * PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug encoding. 735 * 736 * PARAMETERS: 737 * "escAsciiString" 738 * Address of array of bytes representing data source. Must be non-NULL. 739 * "escAsciiLength" 740 * Length of data source. Must be even. 741 * "debug" 742 * Boolean value indicating whether debug mode is desired. 743 * "pDest" 744 * Address where data will be stored. Must be non-NULL. 745 * "pLength" 746 * Address where data length will be stored. Must be non-NULL. 747 * "plContext" 748 * Platform-specific context pointer. 749 * THREAD SAFETY: 750 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 751 * RETURNS: 752 * Returns NULL if the function succeeds. 753 * Returns a String Error if the function fails in a non-fatal way. 754 * Returns a Fatal Error if the function fails in an unrecoverable way. 755 */ 756 PKIX_Error * 757 pkix_EscASCII_to_UTF16( 758 const char *escAsciiString, 759 PKIX_UInt32 escAsciiLen, 760 PKIX_Boolean debug, 761 void **pDest, 762 PKIX_UInt32 *pLength, 763 void *plContext) 764 { 765 PKIX_UInt32 newLen, i, j, charSize; 766 PKIX_UInt32 x = 0, y = 0, z = 0; 767 unsigned char *destPtr = NULL; 768 unsigned char testChar, testChar2; 769 unsigned char *stringData = (unsigned char *)escAsciiString; 770 771 PKIX_ENTER(STRING, "pkix_EscASCII_to_UTF16"); 772 PKIX_NULLCHECK_THREE(escAsciiString, pDest, pLength); 773 774 if (escAsciiLen == 0) { 775 PKIX_CHECK(PKIX_PL_Malloc(escAsciiLen, pDest, plContext), 776 PKIX_MALLOCFAILED); 777 goto cleanup; 778 } 779 780 /* Assume each unicode character takes two bytes */ 781 newLen = escAsciiLen*2; 782 783 /* Count up number of unicode encoded characters */ 784 for (i = 0; i < escAsciiLen; i++) { 785 if (!pkix_isPlaintext(stringData[i], debug)&& 786 (stringData[i] != '&')) { 787 PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII); 788 } else if (PL_strstr(escAsciiString+i, "&") == 789 escAsciiString+i) { 790 /* Convert EscAscii "&" to two bytes */ 791 newLen -= 8; 792 i += 4; 793 } else if ((PL_strstr(escAsciiString+i, "&#x") == 794 escAsciiString+i)|| 795 (PL_strstr(escAsciiString+i, "&#X") == 796 escAsciiString+i)) { 797 if (((i+7) <= escAsciiLen)&& 798 (escAsciiString[i+7] == ';')) { 799 /* Convert &#xNNNN; to two bytes */ 800 newLen -= 14; 801 i += 7; 802 } else if (((i+11) <= escAsciiLen)&& 803 (escAsciiString[i+11] == ';')) { 804 /* Convert &#xNNNNNNNN; to four bytes */ 805 newLen -= 20; 806 i += 11; 807 } else { 808 PKIX_ERROR(PKIX_ILLEGALUSEOFAMP); 809 } 810 } 811 } 812 813 PKIX_CHECK(PKIX_PL_Malloc(newLen, pDest, plContext), 814 PKIX_MALLOCFAILED); 815 816 /* Copy into newly allocated space */ 817 destPtr = (unsigned char *)*pDest; 818 819 i = 0; 820 while (i < escAsciiLen) { 821 /* Copy each byte until you hit a & */ 822 if (pkix_isPlaintext(escAsciiString[i], debug)) { 823 *destPtr++ = 0x00; 824 *destPtr++ = escAsciiString[i++]; 825 } else if (PL_strstr(escAsciiString+i, "&") == 826 escAsciiString+i) { 827 /* Convert EscAscii "&" to two bytes */ 828 *destPtr++ = 0x00; 829 *destPtr++ = '&'; 830 i += 5; 831 } else if (((PL_strstr(escAsciiString+i, "&#x") == 832 escAsciiString+i)|| 833 (PL_strstr(escAsciiString+i, "&#X") == 834 escAsciiString+i))&& 835 ((i+7) <= escAsciiLen)) { 836 837 /* We're either looking at &#xNNNN; or &#xNNNNNNNN; */ 838 charSize = (escAsciiString[i+7] == ';')?4:8; 839 840 /* Skip past the &#x */ 841 i += 3; 842 843 /* Make sure there is a terminating semi-colon */ 844 if (((i+charSize) > escAsciiLen)|| 845 (escAsciiString[i+charSize] != ';')) { 846 PKIX_ERROR(PKIX_TRUNCATEDUNICODEINESCAPEDASCII); 847 } 848 849 for (j = 0; j < charSize; j++) { 850 if (!PKIX_ISXDIGIT 851 (escAsciiString[i+j])) { 852 PKIX_ERROR(PKIX_ILLEGALUNICODECHARACTER); 853 } else if (charSize == 8) { 854 x |= (pkix_hex2i 855 (escAsciiString[i+j])) 856 <<(4*(7-j)); 857 } 858 } 859 860 testChar = 861 (pkix_hex2i(escAsciiString[i])<<4)| 862 pkix_hex2i(escAsciiString[i+1]); 863 testChar2 = 864 (pkix_hex2i(escAsciiString[i+2])<<4)| 865 pkix_hex2i(escAsciiString[i+3]); 866 867 if (charSize == 4) { 868 if ((testChar >= 0xD8)&& 869 (testChar <= 0xDF)) { 870 PKIX_ERROR(PKIX_ILLEGALSURROGATEPAIR); 871 } else if ((testChar == 0x00)&& 872 pkix_isPlaintext(testChar2, debug)) { 873 PKIX_ERROR( 874 PKIX_ILLEGALCHARACTERINESCAPEDASCII); 875 } 876 *destPtr++ = testChar; 877 *destPtr++ = testChar2; 878 } else if (charSize == 8) { 879 /* First two chars must be 0001-0010 */ 880 if (!((testChar == 0x00)&& 881 ((testChar2 >= 0x01)&& 882 (testChar2 <= 0x10)))) { 883 PKIX_ERROR( 884 PKIX_ILLEGALCHARACTERINESCAPEDASCII); 885 } 886 /* 887 * Unicode Strings of the form: 888 * x = 0001 0000..0010 FFFF 889 * Encoded as pairs of UTF-16 where 890 * y = ((x - 0001 0000) / 400) + D800 891 * z = ((x - 0001 0000) % 400) + DC00 892 */ 893 x -= 0x00010000; 894 y = (x/0x400)+ 0xD800; 895 z = (x%0x400)+ 0xDC00; 896 897 /* Copy four bytes */ 898 *destPtr++ = (y&0xFF00)>>8; 899 *destPtr++ = (y&0x00FF); 900 *destPtr++ = (z&0xFF00)>>8; 901 *destPtr++ = (z&0x00FF); 902 } 903 /* Move past the Hex digits and the semi-colon */ 904 i += charSize+1; 905 } else { 906 /* Do not allow any other non-plaintext character */ 907 PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII); 908 } 909 } 910 911 *pLength = newLen; 912 913 cleanup: 914 915 if (PKIX_ERROR_RECEIVED){ 916 PKIX_FREE(*pDest); 917 } 918 919 PKIX_RETURN(STRING); 920 } 921 922 /* 923 * FUNCTION: pkix_UTF16_to_UTF8 924 * DESCRIPTION: 925 * 926 * Converts array of bytes pointed to by "utf16String" with length of 927 * "utf16Length" into a freshly allocated UTF-8 string and stores a pointer 928 * to that string at "pDest" and stores the string's length at "pLength" (not 929 * counting the null terminator, if requested. The caller is responsible for 930 * freeing "pDest" using PKIX_PL_Free. 931 * 932 * PARAMETERS: 933 * "utf16String" 934 * Address of array of bytes representing data source. Must be non-NULL. 935 * "utf16Length" 936 * Length of data source. Must be even. 937 * "null-term" 938 * Boolean value indicating whether output should be null-terminated. 939 * "pDest" 940 * Address where data will be stored. Must be non-NULL. 941 * "pLength" 942 * Address where data length will be stored. Must be non-NULL. 943 * "plContext" 944 * Platform-specific context pointer. 945 * THREAD SAFETY: 946 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 947 * RETURNS: 948 * Returns NULL if the function succeeds. 949 * Returns a String Error if the function fails in a non-fatal way. 950 * Returns a Fatal Error if the function fails in an unrecoverable way. 951 */ 952 PKIX_Error * 953 pkix_UTF16_to_UTF8( 954 const void *utf16String, 955 PKIX_UInt32 utf16Length, 956 PKIX_Boolean null_term, 957 void **pDest, 958 PKIX_UInt32 *pLength, 959 void *plContext) 960 { 961 PKIX_Boolean result; 962 PKIX_UInt32 reallocLen; 963 char *endPtr = NULL; 964 965 PKIX_ENTER(STRING, "pkix_UTF16_to_UTF8"); 966 PKIX_NULLCHECK_THREE(utf16String, pDest, pLength); 967 968 /* XXX How big can a UTF8 string be compared to a UTF16? */ 969 PKIX_CHECK(PKIX_PL_Calloc(1, utf16Length*2, pDest, plContext), 970 PKIX_CALLOCFAILED); 971 972 PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n"); 973 result = PORT_UCS2_UTF8Conversion 974 (PKIX_FALSE, /* False = From UCS2 */ 975 (unsigned char *)utf16String, 976 utf16Length, 977 (unsigned char *)*pDest, 978 utf16Length*2, /* Max Size */ 979 pLength); 980 if (result == PR_FALSE){ 981 PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED); 982 } 983 984 reallocLen = *pLength; 985 986 if (null_term){ 987 reallocLen++; 988 } 989 990 PKIX_CHECK(PKIX_PL_Realloc(*pDest, reallocLen, pDest, plContext), 991 PKIX_REALLOCFAILED); 992 993 if (null_term){ 994 endPtr = (char*)*pDest + reallocLen - 1; 995 *endPtr = '\0'; 996 } 997 998 cleanup: 999 1000 if (PKIX_ERROR_RECEIVED){ 1001 PKIX_FREE(*pDest); 1002 } 1003 1004 PKIX_RETURN(STRING); 1005 } 1006 1007 /* 1008 * FUNCTION: pkix_UTF8_to_UTF16 1009 * DESCRIPTION: 1010 * 1011 * Converts array of bytes pointed to by "utf8String" with length of 1012 * "utf8Length" into a freshly allocated UTF-16 string and stores a pointer 1013 * to that string at "pDest" and stores the string's length at "pLength". The 1014 * caller is responsible for freeing "pDest" using PKIX_PL_Free. 1015 * 1016 * PARAMETERS: 1017 * "utf8String" 1018 * Address of array of bytes representing data source. Must be non-NULL. 1019 * "utf8Length" 1020 * Length of data source. Must be even. 1021 * "pDest" 1022 * Address where data will be stored. Must be non-NULL. 1023 * "pLength" 1024 * Address where data length will be stored. Must be non-NULL. 1025 * "plContext" 1026 * Platform-specific context pointer. 1027 * THREAD SAFETY: 1028 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1029 * RETURNS: 1030 * Returns NULL if the function succeeds. 1031 * Returns a String Error if the function fails in a non-fatal way. 1032 * Returns a Fatal Error if the function fails in an unrecoverable way. 1033 */ 1034 PKIX_Error * 1035 pkix_UTF8_to_UTF16( 1036 const void *utf8String, 1037 PKIX_UInt32 utf8Length, 1038 void **pDest, 1039 PKIX_UInt32 *pLength, 1040 void *plContext) 1041 { 1042 PKIX_Boolean result; 1043 1044 PKIX_ENTER(STRING, "pkix_UTF8_to_UTF16"); 1045 PKIX_NULLCHECK_THREE(utf8String, pDest, pLength); 1046 1047 /* XXX How big can a UTF8 string be compared to a UTF16? */ 1048 PKIX_CHECK(PKIX_PL_Calloc(1, utf8Length*2, pDest, plContext), 1049 PKIX_MALLOCFAILED); 1050 1051 PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n"); 1052 result = PORT_UCS2_UTF8Conversion 1053 (PKIX_TRUE, /* True = From UTF8 */ 1054 (unsigned char *)utf8String, 1055 utf8Length, 1056 (unsigned char *)*pDest, 1057 utf8Length*2, /* Max Size */ 1058 pLength); 1059 if (result == PR_FALSE){ 1060 PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED); 1061 } 1062 1063 PKIX_CHECK(PKIX_PL_Realloc(*pDest, *pLength, pDest, plContext), 1064 PKIX_REALLOCFAILED); 1065 1066 cleanup: 1067 1068 if (PKIX_ERROR_RECEIVED){ 1069 PKIX_FREE(*pDest); 1070 } 1071 1072 PKIX_RETURN(STRING); 1073 }