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 *
pkix_LockObject(PKIX_PL_Object * object,void * plContext)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 *
pkix_UnlockObject(PKIX_PL_Object * object,void * plContext)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
pkix_pl_UInt32_Overflows(char * string)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 *
pkix_pl_getOIDToken(char * derBytes,PKIX_UInt32 index,PKIX_UInt32 * pToken,PKIX_UInt32 * pIndex,void * plContext)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 *
pkix_pl_helperBytes2Ascii(PKIX_UInt32 * tokens,PKIX_UInt32 numTokens,char ** pAscii,void * plContext)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 *
pkix_pl_ipAddrBytes2Ascii(SECItem * secItem,char ** pAscii,void * plContext)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 *
pkix_pl_oidBytes2Ascii(SECItem * secItem,char ** pAscii,void * plContext)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 *
pkix_UTF16_to_EscASCII(const void * utf16String,PKIX_UInt32 utf16Length,PKIX_Boolean debug,char ** pDest,PKIX_UInt32 * pLength,void * plContext)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 *
pkix_EscASCII_to_UTF16(const char * escAsciiString,PKIX_UInt32 escAsciiLen,PKIX_Boolean debug,void ** pDest,PKIX_UInt32 * pLength,void * plContext)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 *
pkix_UTF16_to_UTF8(const void * utf16String,PKIX_UInt32 utf16Length,PKIX_Boolean null_term,void ** pDest,PKIX_UInt32 * pLength,void * plContext)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 *
pkix_UTF8_to_UTF16(const void * utf8String,PKIX_UInt32 utf8Length,void ** pDest,PKIX_UInt32 * pLength,void * plContext)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 }
1074