Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/certdb/secname.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 #include "cert.h" | |
6 #include "secoid.h" | |
7 #include "secder.h" /* XXX remove this when remove the DERTemplates */ | |
8 #include "secasn1.h" | |
9 #include "secitem.h" | |
10 #include <stdarg.h> | |
11 #include "secerr.h" | |
12 #include "certi.h" | |
13 | |
14 static const SEC_ASN1Template cert_AVATemplate[] = { | |
15 { SEC_ASN1_SEQUENCE, | |
16 0, NULL, sizeof(CERTAVA) }, | |
17 { SEC_ASN1_OBJECT_ID, | |
18 offsetof(CERTAVA,type), }, | |
19 { SEC_ASN1_ANY, | |
20 offsetof(CERTAVA,value), }, | |
21 { 0, } | |
22 }; | |
23 | |
24 const SEC_ASN1Template CERT_RDNTemplate[] = { | |
25 { SEC_ASN1_SET_OF, | |
26 offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } | |
27 }; | |
28 | |
29 | |
30 static int | |
31 CountArray(void **array) | |
32 { | |
33 int count = 0; | |
34 if (array) { | |
35 while (*array++) { | |
36 count++; | |
37 } | |
38 } | |
39 return count; | |
40 } | |
41 | |
42 static void ** | |
43 AddToArray(PLArenaPool *arena, void **array, void *element) | |
44 { | |
45 unsigned count; | |
46 void **ap; | |
47 | |
48 /* Count up number of slots already in use in the array */ | |
49 count = 0; | |
50 ap = array; | |
51 if (ap) { | |
52 while (*ap++) { | |
53 count++; | |
54 } | |
55 } | |
56 | |
57 if (array) { | |
58 array = (void**) PORT_ArenaGrow(arena, array, | |
59 (count + 1) * sizeof(void *), | |
60 (count + 2) * sizeof(void *)); | |
61 } else { | |
62 array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *)); | |
63 } | |
64 if (array) { | |
65 array[count] = element; | |
66 array[count+1] = 0; | |
67 } | |
68 return array; | |
69 } | |
70 | |
71 | |
72 SECOidTag | |
73 CERT_GetAVATag(CERTAVA *ava) | |
74 { | |
75 SECOidData *oid; | |
76 if (!ava->type.data) return (SECOidTag)-1; | |
77 | |
78 oid = SECOID_FindOID(&ava->type); | |
79 | |
80 if ( oid ) { | |
81 return(oid->offset); | |
82 } | |
83 return (SECOidTag)-1; | |
84 } | |
85 | |
86 static SECStatus | |
87 SetupAVAType(PLArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp) | |
88 { | |
89 unsigned char *oid; | |
90 unsigned oidLen; | |
91 unsigned char *cp; | |
92 int maxLen; | |
93 SECOidData *oidrec; | |
94 | |
95 oidrec = SECOID_FindOIDByTag(type); | |
96 if (oidrec == NULL) | |
97 return SECFailure; | |
98 | |
99 oid = oidrec->oid.data; | |
100 oidLen = oidrec->oid.len; | |
101 | |
102 maxLen = cert_AVAOidTagToMaxLen(type); | |
103 if (maxLen < 0) { | |
104 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
105 return SECFailure; | |
106 } | |
107 | |
108 it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, oidLen); | |
109 if (cp == NULL) { | |
110 return SECFailure; | |
111 } | |
112 it->len = oidLen; | |
113 PORT_Memcpy(cp, oid, oidLen); | |
114 *maxLenp = (unsigned)maxLen; | |
115 return SECSuccess; | |
116 } | |
117 | |
118 static SECStatus | |
119 SetupAVAValue(PLArenaPool *arena, int valueType, const SECItem *in, | |
120 SECItem *out, unsigned maxLen) | |
121 { | |
122 PRUint8 *value, *cp, *ucs4Val; | |
123 unsigned valueLen, valueLenLen, total; | |
124 unsigned ucs4Len = 0, ucs4MaxLen; | |
125 | |
126 value = in->data; | |
127 valueLen = in->len; | |
128 switch (valueType) { | |
129 case SEC_ASN1_PRINTABLE_STRING: | |
130 case SEC_ASN1_IA5_STRING: | |
131 case SEC_ASN1_T61_STRING: | |
132 case SEC_ASN1_UTF8_STRING: /* no conversion required */ | |
133 break; | |
134 case SEC_ASN1_UNIVERSAL_STRING: | |
135 ucs4MaxLen = valueLen * 6; | |
136 ucs4Val = (PRUint8 *)PORT_ArenaZAlloc(arena, ucs4MaxLen); | |
137 if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, value, valueLen, | |
138 ucs4Val, ucs4MaxLen, &ucs4Len)) { | |
139 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
140 return SECFailure; | |
141 } | |
142 value = ucs4Val; | |
143 valueLen = ucs4Len; | |
144 maxLen *= 4; | |
145 break; | |
146 default: | |
147 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
148 return SECFailure; | |
149 } | |
150 | |
151 if (valueLen > maxLen) { | |
152 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
153 return SECFailure; | |
154 } | |
155 | |
156 valueLenLen = DER_LengthLength(valueLen); | |
157 total = 1 + valueLenLen + valueLen; | |
158 cp = (PRUint8*)PORT_ArenaAlloc(arena, total); | |
159 if (!cp) { | |
160 return SECFailure; | |
161 } | |
162 out->data = cp; | |
163 out->len = total; | |
164 cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen); | |
165 PORT_Memcpy(cp, value, valueLen); | |
166 return SECSuccess; | |
167 } | |
168 | |
169 CERTAVA * | |
170 CERT_CreateAVAFromRaw(PLArenaPool *pool, const SECItem * OID, | |
171 const SECItem * value) | |
172 { | |
173 CERTAVA *ava; | |
174 int rv; | |
175 | |
176 ava = PORT_ArenaZNew(pool, CERTAVA); | |
177 if (ava) { | |
178 rv = SECITEM_CopyItem(pool, &ava->type, OID); | |
179 if (rv) | |
180 return NULL; | |
181 | |
182 rv = SECITEM_CopyItem(pool, &ava->value, value); | |
183 if (rv) | |
184 return NULL; | |
185 } | |
186 return ava; | |
187 } | |
188 | |
189 CERTAVA * | |
190 CERT_CreateAVAFromSECItem(PLArenaPool *arena, SECOidTag kind, int valueType, | |
191 SECItem *value) | |
192 { | |
193 CERTAVA *ava; | |
194 int rv; | |
195 unsigned maxLen; | |
196 | |
197 ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); | |
198 if (ava) { | |
199 rv = SetupAVAType(arena, kind, &ava->type, &maxLen); | |
200 if (rv) { | |
201 /* Illegal AVA type */ | |
202 return NULL; | |
203 } | |
204 rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen); | |
205 if (rv) { | |
206 /* Illegal value type */ | |
207 return NULL; | |
208 } | |
209 } | |
210 return ava; | |
211 } | |
212 | |
213 CERTAVA * | |
214 CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, int valueType, char *value) | |
215 { | |
216 SECItem item = { siBuffer, NULL, 0 }; | |
217 | |
218 item.data = (PRUint8 *)value; | |
219 item.len = PORT_Strlen(value); | |
220 | |
221 return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item); | |
222 } | |
223 | |
224 CERTAVA * | |
225 CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from) | |
226 { | |
227 CERTAVA *ava; | |
228 int rv; | |
229 | |
230 ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); | |
231 if (ava) { | |
232 rv = SECITEM_CopyItem(arena, &ava->type, &from->type); | |
233 if (rv) goto loser; | |
234 rv = SECITEM_CopyItem(arena, &ava->value, &from->value); | |
235 if (rv) goto loser; | |
236 } | |
237 return ava; | |
238 | |
239 loser: | |
240 return 0; | |
241 } | |
242 | |
243 /************************************************************************/ | |
244 /* XXX This template needs to go away in favor of the new SEC_ASN1 version. */ | |
245 static const SEC_ASN1Template cert_RDNTemplate[] = { | |
246 { SEC_ASN1_SET_OF, | |
247 offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } | |
248 }; | |
249 | |
250 | |
251 CERTRDN * | |
252 CERT_CreateRDN(PLArenaPool *arena, CERTAVA *ava0, ...) | |
253 { | |
254 CERTAVA *ava; | |
255 CERTRDN *rdn; | |
256 va_list ap; | |
257 unsigned count; | |
258 CERTAVA **avap; | |
259 | |
260 rdn = (CERTRDN*) PORT_ArenaAlloc(arena, sizeof(CERTRDN)); | |
261 if (rdn) { | |
262 /* Count number of avas going into the rdn */ | |
263 count = 0; | |
264 if (ava0) { | |
265 count++; | |
266 va_start(ap, ava0); | |
267 while ((ava = va_arg(ap, CERTAVA*)) != 0) { | |
268 count++; | |
269 } | |
270 va_end(ap); | |
271 } | |
272 | |
273 /* Now fill in the pointers */ | |
274 rdn->avas = avap = | |
275 (CERTAVA**) PORT_ArenaAlloc( arena, (count + 1)*sizeof(CERTAVA*)); | |
276 if (!avap) { | |
277 return 0; | |
278 } | |
279 if (ava0) { | |
280 *avap++ = ava0; | |
281 va_start(ap, ava0); | |
282 while ((ava = va_arg(ap, CERTAVA*)) != 0) { | |
283 *avap++ = ava; | |
284 } | |
285 va_end(ap); | |
286 } | |
287 *avap++ = 0; | |
288 } | |
289 return rdn; | |
290 } | |
291 | |
292 SECStatus | |
293 CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava) | |
294 { | |
295 rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava); | |
296 return rdn->avas ? SECSuccess : SECFailure; | |
297 } | |
298 | |
299 SECStatus | |
300 CERT_CopyRDN(PLArenaPool *arena, CERTRDN *to, CERTRDN *from) | |
301 { | |
302 CERTAVA **avas, *fava, *tava; | |
303 SECStatus rv = SECSuccess; | |
304 | |
305 /* Copy each ava from from */ | |
306 avas = from->avas; | |
307 if (avas) { | |
308 if (avas[0] == NULL) { | |
309 rv = CERT_AddAVA(arena, to, NULL); | |
310 return rv; | |
311 } | |
312 while ((fava = *avas++) != 0) { | |
313 tava = CERT_CopyAVA(arena, fava); | |
314 if (!tava) { | |
315 rv = SECFailure; | |
316 break; | |
317 } | |
318 rv = CERT_AddAVA(arena, to, tava); | |
319 if (rv != SECSuccess) | |
320 break; | |
321 } | |
322 } | |
323 return rv; | |
324 } | |
325 | |
326 /************************************************************************/ | |
327 | |
328 const SEC_ASN1Template CERT_NameTemplate[] = { | |
329 { SEC_ASN1_SEQUENCE_OF, | |
330 offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) } | |
331 }; | |
332 | |
333 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate) | |
334 | |
335 CERTName * | |
336 CERT_CreateName(CERTRDN *rdn0, ...) | |
337 { | |
338 CERTRDN *rdn; | |
339 CERTName *name; | |
340 va_list ap; | |
341 unsigned count; | |
342 CERTRDN **rdnp; | |
343 PLArenaPool *arena; | |
344 | |
345 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
346 if ( !arena ) { | |
347 return(0); | |
348 } | |
349 | |
350 name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName)); | |
351 if (name) { | |
352 name->arena = arena; | |
353 | |
354 /* Count number of RDNs going into the Name */ | |
355 if (!rdn0) { | |
356 count = 0; | |
357 } else { | |
358 count = 1; | |
359 va_start(ap, rdn0); | |
360 while ((rdn = va_arg(ap, CERTRDN*)) != 0) { | |
361 count++; | |
362 } | |
363 va_end(ap); | |
364 } | |
365 | |
366 /* Allocate space (including space for terminal null ptr) */ | |
367 name->rdns = rdnp = | |
368 (CERTRDN**) PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN*)); | |
369 if (!name->rdns) { | |
370 goto loser; | |
371 } | |
372 | |
373 /* Now fill in the pointers */ | |
374 if (count > 0) { | |
375 *rdnp++ = rdn0; | |
376 va_start(ap, rdn0); | |
377 while ((rdn = va_arg(ap, CERTRDN*)) != 0) { | |
378 *rdnp++ = rdn; | |
379 } | |
380 va_end(ap); | |
381 } | |
382 | |
383 /* null terminate the list */ | |
384 *rdnp++ = 0; | |
385 } | |
386 return name; | |
387 | |
388 loser: | |
389 PORT_FreeArena(arena, PR_FALSE); | |
390 return(0); | |
391 } | |
392 | |
393 void | |
394 CERT_DestroyName(CERTName *name) | |
395 { | |
396 if (name) | |
397 { | |
398 PLArenaPool *arena = name->arena; | |
399 name->rdns = NULL; | |
400 name->arena = NULL; | |
401 if (arena) PORT_FreeArena(arena, PR_FALSE); | |
402 } | |
403 } | |
404 | |
405 SECStatus | |
406 CERT_AddRDN(CERTName *name, CERTRDN *rdn) | |
407 { | |
408 name->rdns = (CERTRDN**) AddToArray(name->arena, (void**) name->rdns, rdn); | |
409 return name->rdns ? SECSuccess : SECFailure; | |
410 } | |
411 | |
412 SECStatus | |
413 CERT_CopyName(PLArenaPool *arena, CERTName *to, const CERTName *from) | |
414 { | |
415 CERTRDN **rdns, *frdn, *trdn; | |
416 SECStatus rv = SECSuccess; | |
417 | |
418 if (!to || !from) { | |
419 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
420 return SECFailure; | |
421 } | |
422 | |
423 CERT_DestroyName(to); | |
424 to->arena = arena; | |
425 | |
426 /* Copy each rdn from from */ | |
427 rdns = from->rdns; | |
428 if (rdns) { | |
429 if (rdns[0] == NULL) { | |
430 rv = CERT_AddRDN(to, NULL); | |
431 return rv; | |
432 } | |
433 while ((frdn = *rdns++) != NULL) { | |
434 trdn = CERT_CreateRDN(arena, NULL); | |
435 if (!trdn) { | |
436 rv = SECFailure; | |
437 break; | |
438 } | |
439 rv = CERT_CopyRDN(arena, trdn, frdn); | |
440 if (rv != SECSuccess) | |
441 break; | |
442 rv = CERT_AddRDN(to, trdn); | |
443 if (rv != SECSuccess) | |
444 break; | |
445 } | |
446 } | |
447 return rv; | |
448 } | |
449 | |
450 /************************************************************************/ | |
451 | |
452 static void | |
453 canonicalize(SECItem * foo) | |
454 { | |
455 int ch, lastch, len, src, dest; | |
456 | |
457 /* strip trailing whitespace. */ | |
458 len = foo->len; | |
459 while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || | |
460 ch == '\t' || ch == '\r' || ch == '\n')) { | |
461 len--; | |
462 } | |
463 | |
464 src = 0; | |
465 /* strip leading whitespace. */ | |
466 while (src < len && ((ch = foo->data[src]) == ' ' || | |
467 ch == '\t' || ch == '\r' || ch == '\n')) { | |
468 src++; | |
469 } | |
470 dest = 0; lastch = ' '; | |
471 while (src < len) { | |
472 ch = foo->data[src++]; | |
473 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { | |
474 ch = ' '; | |
475 if (ch == lastch) | |
476 continue; | |
477 } else if (ch >= 'A' && ch <= 'Z') { | |
478 ch |= 0x20; /* downshift */ | |
479 } | |
480 foo->data[dest++] = lastch = ch; | |
481 } | |
482 foo->len = dest; | |
483 } | |
484 | |
485 /* SECItems a and b contain DER-encoded printable strings. */ | |
486 SECComparison | |
487 CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b) | |
488 { | |
489 SECComparison rv = SECLessThan; | |
490 SECItem * aVal = CERT_DecodeAVAValue(a); | |
491 SECItem * bVal = CERT_DecodeAVAValue(b); | |
492 | |
493 if (aVal && aVal->len && aVal->data && | |
494 bVal && bVal->len && bVal->data) { | |
495 canonicalize(aVal); | |
496 canonicalize(bVal); | |
497 rv = SECITEM_CompareItem(aVal, bVal); | |
498 } | |
499 SECITEM_FreeItem(aVal, PR_TRUE); | |
500 SECITEM_FreeItem(bVal, PR_TRUE); | |
501 return rv; | |
502 } | |
503 | |
504 SECComparison | |
505 CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) | |
506 { | |
507 SECComparison rv; | |
508 | |
509 rv = SECITEM_CompareItem(&a->type, &b->type); | |
510 if (SECEqual != rv) | |
511 return rv; /* Attribute types don't match. */ | |
512 /* Let's be optimistic. Maybe the values will just compare equal. */ | |
513 rv = SECITEM_CompareItem(&a->value, &b->value); | |
514 if (SECEqual == rv) | |
515 return rv; /* values compared exactly. */ | |
516 if (a->value.len && a->value.data && b->value.len && b->value.data) { | |
517 /* Here, the values did not match. | |
518 ** If the values had different encodings, convert them to the same | |
519 ** encoding and compare that way. | |
520 */ | |
521 if (a->value.data[0] != b->value.data[0]) { | |
522 /* encodings differ. Convert both to UTF-8 and compare. */ | |
523 SECItem * aVal = CERT_DecodeAVAValue(&a->value); | |
524 SECItem * bVal = CERT_DecodeAVAValue(&b->value); | |
525 if (aVal && aVal->len && aVal->data && | |
526 bVal && bVal->len && bVal->data) { | |
527 rv = SECITEM_CompareItem(aVal, bVal); | |
528 } | |
529 SECITEM_FreeItem(aVal, PR_TRUE); | |
530 SECITEM_FreeItem(bVal, PR_TRUE); | |
531 } else if (a->value.data[0] == 0x13) { /* both are printable strings. */ | |
532 /* printable strings */ | |
533 rv = CERT_CompareDERPrintableStrings(&a->value, &b->value); | |
534 } | |
535 } | |
536 return rv; | |
537 } | |
538 | |
539 SECComparison | |
540 CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b) | |
541 { | |
542 CERTAVA **aavas, *aava; | |
543 CERTAVA **bavas, *bava; | |
544 int ac, bc; | |
545 SECComparison rv = SECEqual; | |
546 | |
547 aavas = a->avas; | |
548 bavas = b->avas; | |
549 | |
550 /* | |
551 ** Make sure array of ava's are the same length. If not, then we are | |
552 ** not equal | |
553 */ | |
554 ac = CountArray((void**) aavas); | |
555 bc = CountArray((void**) bavas); | |
556 if (ac < bc) return SECLessThan; | |
557 if (ac > bc) return SECGreaterThan; | |
558 | |
559 while (NULL != (aava = *aavas++)) { | |
560 for (bavas = b->avas; NULL != (bava = *bavas++); ) { | |
561 rv = SECITEM_CompareItem(&aava->type, &bava->type); | |
562 if (SECEqual == rv) { | |
563 rv = CERT_CompareAVA(aava, bava); | |
564 if (SECEqual != rv) | |
565 return rv; | |
566 break; | |
567 } | |
568 } | |
569 if (!bava) /* didn't find a match */ | |
570 return SECGreaterThan; | |
571 } | |
572 return rv; | |
573 } | |
574 | |
575 SECComparison | |
576 CERT_CompareName(const CERTName *a, const CERTName *b) | |
577 { | |
578 CERTRDN **ardns, *ardn; | |
579 CERTRDN **brdns, *brdn; | |
580 int ac, bc; | |
581 SECComparison rv = SECEqual; | |
582 | |
583 ardns = a->rdns; | |
584 brdns = b->rdns; | |
585 | |
586 /* | |
587 ** Make sure array of rdn's are the same length. If not, then we are | |
588 ** not equal | |
589 */ | |
590 ac = CountArray((void**) ardns); | |
591 bc = CountArray((void**) brdns); | |
592 if (ac < bc) return SECLessThan; | |
593 if (ac > bc) return SECGreaterThan; | |
594 | |
595 for (;;) { | |
596 ardn = *ardns++; | |
597 brdn = *brdns++; | |
598 if (!ardn) { | |
599 break; | |
600 } | |
601 rv = CERT_CompareRDN(ardn, brdn); | |
602 if (rv) return rv; | |
603 } | |
604 return rv; | |
605 } | |
606 | |
607 /* Moved from certhtml.c */ | |
608 SECItem * | |
609 CERT_DecodeAVAValue(const SECItem *derAVAValue) | |
610 { | |
611 SECItem *retItem; | |
612 const SEC_ASN1Template *theTemplate = NULL; | |
613 enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none; | |
614 SECItem avaValue = {siBuffer, 0}; | |
615 PLArenaPool *newarena = NULL; | |
616 | |
617 if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) { | |
618 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
619 return NULL; | |
620 } | |
621 | |
622 switch(derAVAValue->data[0]) { | |
623 case SEC_ASN1_UNIVERSAL_STRING: | |
624 convert = conv_ucs4; | |
625 theTemplate = SEC_ASN1_GET(SEC_UniversalStringTemplate); | |
626 break; | |
627 case SEC_ASN1_IA5_STRING: | |
628 theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); | |
629 break; | |
630 case SEC_ASN1_PRINTABLE_STRING: | |
631 theTemplate = SEC_ASN1_GET(SEC_PrintableStringTemplate); | |
632 break; | |
633 case SEC_ASN1_T61_STRING: | |
634 /* | |
635 * Per common practice, we're not decoding actual T.61, but instead | |
636 * treating T61-labeled strings as containing ISO-8859-1. | |
637 */ | |
638 convert = conv_iso88591; | |
639 theTemplate = SEC_ASN1_GET(SEC_T61StringTemplate); | |
640 break; | |
641 case SEC_ASN1_BMP_STRING: | |
642 convert = conv_ucs2; | |
643 theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate); | |
644 break; | |
645 case SEC_ASN1_UTF8_STRING: | |
646 /* No conversion needed ! */ | |
647 theTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate); | |
648 break; | |
649 default: | |
650 PORT_SetError(SEC_ERROR_INVALID_AVA); | |
651 return NULL; | |
652 } | |
653 | |
654 PORT_Memset(&avaValue, 0, sizeof(SECItem)); | |
655 newarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
656 if (!newarena) { | |
657 return NULL; | |
658 } | |
659 if(SEC_QuickDERDecodeItem(newarena, &avaValue, theTemplate, derAVAValue) | |
660 != SECSuccess) { | |
661 PORT_FreeArena(newarena, PR_FALSE); | |
662 return NULL; | |
663 } | |
664 | |
665 if (convert != conv_none) { | |
666 unsigned int utf8ValLen = avaValue.len * 3; | |
667 unsigned char *utf8Val = (unsigned char*) | |
668 PORT_ArenaZAlloc(newarena, utf8ValLen); | |
669 | |
670 switch (convert) { | |
671 case conv_ucs4: | |
672 if(avaValue.len % 4 != 0 || | |
673 !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, | |
674 utf8Val, utf8ValLen, &utf8ValLen)) { | |
675 PORT_FreeArena(newarena, PR_FALSE); | |
676 PORT_SetError(SEC_ERROR_INVALID_AVA); | |
677 return NULL; | |
678 } | |
679 break; | |
680 case conv_ucs2: | |
681 if(avaValue.len % 2 != 0 || | |
682 !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, | |
683 utf8Val, utf8ValLen, &utf8ValLen)) { | |
684 PORT_FreeArena(newarena, PR_FALSE); | |
685 PORT_SetError(SEC_ERROR_INVALID_AVA); | |
686 return NULL; | |
687 } | |
688 break; | |
689 case conv_iso88591: | |
690 if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len, | |
691 utf8Val, utf8ValLen, &utf8ValLen)) { | |
692 PORT_FreeArena(newarena, PR_FALSE); | |
693 PORT_SetError(SEC_ERROR_INVALID_AVA); | |
694 return NULL; | |
695 } | |
696 break; | |
697 case conv_none: | |
698 PORT_Assert(0); /* not reached */ | |
699 break; | |
700 } | |
701 | |
702 avaValue.data = utf8Val; | |
703 avaValue.len = utf8ValLen; | |
704 } | |
705 | |
706 retItem = SECITEM_DupItem(&avaValue); | |
707 PORT_FreeArena(newarena, PR_FALSE); | |
708 return retItem; | |
709 } |