Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 &amp; */
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, "&amp;") ==
789 escAsciiString+i) {
790 /* Convert EscAscii "&amp;" 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 &amp; */
822 if (pkix_isPlaintext(escAsciiString[i], debug)) {
823 *destPtr++ = 0x00;
824 *destPtr++ = escAsciiString[i++];
825 } else if (PL_strstr(escAsciiString+i, "&amp;") ==
826 escAsciiString+i) {
827 /* Convert EscAscii "&amp;" 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 }
OLDNEW
« no previous file with comments | « nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h ('k') | nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698