Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 } |