| OLD | NEW |
| (Empty) |
| 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 } | |
| OLD | NEW |