Bug Summary

File:s/lib/certdb/secname.c
Warning:line 351, column 21
Although the value stored to 'rdn' is used in the enclosing expression, the value is never actually read from 'rdn'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name secname.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/certdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/certdb -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c secname.c
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
14static const SEC_ASN1Template cert_AVATemplate[] = {
15 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(CERTAVA) },
16 { SEC_ASN1_OBJECT_ID0x06, offsetof(CERTAVA, type)__builtin_offsetof(CERTAVA, type) },
17 { SEC_ASN1_ANY0x00400, offsetof(CERTAVA, value)__builtin_offsetof(CERTAVA, value) },
18 { 0 }
19};
20
21const SEC_ASN1Template CERT_RDNTemplate[] = {
22 { SEC_ASN1_SET_OF(0x02000 | 0x11), offsetof(CERTRDN, avas)__builtin_offsetof(CERTRDN, avas), cert_AVATemplate,
23 sizeof(CERTRDN) }
24};
25
26static int
27CountArray(void **array)
28{
29 int count = 0;
30 if (array) {
31 while (*array++) {
32 count++;
33 }
34 }
35 return count;
36}
37
38static void **
39AddToArray(PLArenaPool *arena, void **array, void *element)
40{
41 unsigned count;
42 void **ap;
43
44 /* Count up number of slots already in use in the array */
45 count = 0;
46 ap = array;
47 if (ap) {
48 while (*ap++) {
49 count++;
50 }
51 }
52
53 if (array) {
54 array =
55 (void **)PORT_ArenaGrowPORT_ArenaGrow_Util(arena, array, (count + 1) * sizeof(void *),
56 (count + 2) * sizeof(void *));
57 } else {
58 array = (void **)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, (count + 2) * sizeof(void *));
59 }
60 if (array) {
61 array[count] = element;
62 array[count + 1] = 0;
63 }
64 return array;
65}
66
67SECOidTag
68CERT_GetAVATag(CERTAVA *ava)
69{
70 SECOidData *oid;
71 if (!ava->type.data)
72 return (SECOidTag)-1;
73
74 oid = SECOID_FindOIDSECOID_FindOID_Util(&ava->type);
75
76 if (oid) {
77 return (oid->offset);
78 }
79 return (SECOidTag)-1;
80}
81
82static SECStatus
83SetupAVAType(PLArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp)
84{
85 unsigned char *oid;
86 unsigned oidLen;
87 unsigned char *cp;
88 int maxLen;
89 SECOidData *oidrec;
90
91 oidrec = SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(type);
92 if (oidrec == NULL((void*)0))
93 return SECFailure;
94
95 oid = oidrec->oid.data;
96 oidLen = oidrec->oid.len;
97
98 maxLen = cert_AVAOidTagToMaxLen(type);
99 if (maxLen < 0) {
100 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
101 return SECFailure;
102 }
103
104 it->data = cp = (unsigned char *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, oidLen);
105 if (cp == NULL((void*)0)) {
106 return SECFailure;
107 }
108 it->len = oidLen;
109 PORT_Memcpymemcpy(cp, oid, oidLen);
110 *maxLenp = (unsigned)maxLen;
111 return SECSuccess;
112}
113
114static SECStatus
115SetupAVAValue(PLArenaPool *arena, int valueType, const SECItem *in,
116 SECItem *out, unsigned maxLen)
117{
118 PRUint8 *value, *cp, *ucs4Val;
119 unsigned valueLen, valueLenLen, total;
120 unsigned ucs4Len = 0, ucs4MaxLen;
121
122 value = in->data;
123 valueLen = in->len;
124 switch (valueType) {
125 case SEC_ASN1_PRINTABLE_STRING0x13:
126 case SEC_ASN1_IA5_STRING0x16:
127 case SEC_ASN1_T61_STRING0x14:
128 case SEC_ASN1_UTF8_STRING0x0c: /* no conversion required */
129 break;
130 case SEC_ASN1_UNIVERSAL_STRING0x1c:
131 ucs4MaxLen = valueLen * 6;
132 ucs4Val = (PRUint8 *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, ucs4MaxLen);
133 if (!ucs4Val ||
134 !PORT_UCS4_UTF8Conversion(PR_TRUE1, value, valueLen, ucs4Val,
135 ucs4MaxLen, &ucs4Len)) {
136 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
137 return SECFailure;
138 }
139 value = ucs4Val;
140 valueLen = ucs4Len;
141 maxLen *= 4;
142 break;
143 default:
144 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
145 return SECFailure;
146 }
147
148 if (valueLen > maxLen) {
149 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
150 return SECFailure;
151 }
152
153 valueLenLen = DER_LengthLength(valueLen);
154 total = 1 + valueLenLen + valueLen;
155 cp = (PRUint8 *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, total);
156 if (!cp) {
157 return SECFailure;
158 }
159 out->data = cp;
160 out->len = total;
161 cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen);
162 PORT_Memcpymemcpy(cp, value, valueLen);
163 return SECSuccess;
164}
165
166CERTAVA *
167CERT_CreateAVAFromRaw(PLArenaPool *pool, const SECItem *OID,
168 const SECItem *value)
169{
170 CERTAVA *ava;
171 int rv;
172
173 ava = PORT_ArenaZNew(pool, CERTAVA)(CERTAVA *)PORT_ArenaZAlloc_Util(pool, sizeof(CERTAVA));
174 if (ava) {
175 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(pool, &ava->type, OID);
176 if (rv)
177 return NULL((void*)0);
178
179 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(pool, &ava->value, value);
180 if (rv)
181 return NULL((void*)0);
182 }
183 return ava;
184}
185
186CERTAVA *
187CERT_CreateAVAFromSECItem(PLArenaPool *arena, SECOidTag kind, int valueType,
188 SECItem *value)
189{
190 CERTAVA *ava;
191 int rv;
192 unsigned maxLen;
193
194 ava = (CERTAVA *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(CERTAVA));
195 if (ava) {
196 rv = SetupAVAType(arena, kind, &ava->type, &maxLen);
197 if (rv) {
198 /* Illegal AVA type */
199 return NULL((void*)0);
200 }
201 rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);
202 if (rv) {
203 /* Illegal value type */
204 return NULL((void*)0);
205 }
206 }
207 return ava;
208}
209
210CERTAVA *
211CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, int valueType, char *value)
212{
213 SECItem item = { siBuffer, NULL((void*)0), 0 };
214
215 item.data = (PRUint8 *)value;
216 item.len = PORT_Strlen(value)strlen(value);
217
218 return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item);
219}
220
221CERTAVA *
222CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from)
223{
224 CERTAVA *ava;
225 int rv;
226
227 ava = (CERTAVA *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(CERTAVA));
228 if (ava) {
229 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &ava->type, &from->type);
230 if (rv)
231 goto loser;
232 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &ava->value, &from->value);
233 if (rv)
234 goto loser;
235 }
236 return ava;
237
238loser:
239 return 0;
240}
241
242CERTRDN *
243CERT_CreateRDN(PLArenaPool *arena, CERTAVA *ava0, ...)
244{
245 CERTAVA *ava;
246 CERTRDN *rdn;
247 va_list ap;
248 unsigned count;
249 CERTAVA **avap;
250
251 rdn = (CERTRDN *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, sizeof(CERTRDN));
252 if (rdn) {
253 /* Count number of avas going into the rdn */
254 count = 0;
255 if (ava0) {
256 count++;
257 va_start(ap, ava0)__builtin_va_start(ap, ava0);
258 while ((ava = va_arg(ap, CERTAVA *)__builtin_va_arg(ap, CERTAVA *)) != 0) {
259 count++;
260 }
261 va_end(ap)__builtin_va_end(ap);
262 }
263
264 /* Now fill in the pointers */
265 rdn->avas = avap =
266 (CERTAVA **)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, (count + 1) * sizeof(CERTAVA *));
267 if (!avap) {
268 return 0;
269 }
270 if (ava0) {
271 *avap++ = ava0;
272 va_start(ap, ava0)__builtin_va_start(ap, ava0);
273 while ((ava = va_arg(ap, CERTAVA *)__builtin_va_arg(ap, CERTAVA *)) != 0) {
274 *avap++ = ava;
275 }
276 va_end(ap)__builtin_va_end(ap);
277 }
278 *avap++ = 0;
279 }
280 return rdn;
281}
282
283SECStatus
284CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava)
285{
286 rdn->avas = (CERTAVA **)AddToArray(arena, (void **)rdn->avas, ava);
287 return rdn->avas ? SECSuccess : SECFailure;
288}
289
290SECStatus
291CERT_CopyRDN(PLArenaPool *arena, CERTRDN *to, CERTRDN *from)
292{
293 CERTAVA **avas, *fava, *tava;
294 SECStatus rv = SECSuccess;
295
296 /* Copy each ava from from */
297 avas = from->avas;
298 if (avas) {
299 if (avas[0] == NULL((void*)0)) {
300 rv = CERT_AddAVA(arena, to, NULL((void*)0));
301 return rv;
302 }
303 while ((fava = *avas++) != 0) {
304 tava = CERT_CopyAVA(arena, fava);
305 if (!tava) {
306 rv = SECFailure;
307 break;
308 }
309 rv = CERT_AddAVA(arena, to, tava);
310 if (rv != SECSuccess)
311 break;
312 }
313 }
314 return rv;
315}
316
317/************************************************************************/
318
319const SEC_ASN1Template CERT_NameTemplate[] = {
320 { SEC_ASN1_SEQUENCE_OF(0x02000 | 0x10), offsetof(CERTName, rdns)__builtin_offsetof(CERTName, rdns), CERT_RDNTemplate,
321 sizeof(CERTName) }
322};
323
324SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate)const SEC_ASN1Template *NSS_Get_CERT_NameTemplate(void *arg, PRBool
enc) { return CERT_NameTemplate; }
325
326CERTName *
327CERT_CreateName(CERTRDN *rdn0, ...)
328{
329 CERTRDN *rdn;
330 CERTName *name;
331 va_list ap;
332 unsigned count;
333 CERTRDN **rdnp;
334 PLArenaPool *arena;
335
336 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
337 if (!arena) {
338 return (0);
339 }
340
341 name = (CERTName *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, sizeof(CERTName));
342 if (name) {
343 name->arena = arena;
344
345 /* Count number of RDNs going into the Name */
346 if (!rdn0) {
347 count = 0;
348 } else {
349 count = 1;
350 va_start(ap, rdn0)__builtin_va_start(ap, rdn0);
351 while ((rdn = va_arg(ap, CERTRDN *)__builtin_va_arg(ap, CERTRDN *)) != 0) {
Although the value stored to 'rdn' is used in the enclosing expression, the value is never actually read from 'rdn'
352 count++;
353 }
354 va_end(ap)__builtin_va_end(ap);
355 }
356
357 /* Allocate space (including space for terminal null ptr) */
358 name->rdns = rdnp =
359 (CERTRDN **)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, (count + 1) * sizeof(CERTRDN *));
360 if (!name->rdns) {
361 goto loser;
362 }
363
364 /* Now fill in the pointers */
365 if (count > 0) {
366 *rdnp++ = rdn0;
367 va_start(ap, rdn0)__builtin_va_start(ap, rdn0);
368 while ((rdn = va_arg(ap, CERTRDN *)__builtin_va_arg(ap, CERTRDN *)) != 0) {
369 *rdnp++ = rdn;
370 }
371 va_end(ap)__builtin_va_end(ap);
372 }
373
374 /* null terminate the list */
375 *rdnp++ = 0;
376 }
377 return name;
378
379loser:
380 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
381 return (0);
382}
383
384void
385CERT_DestroyName(CERTName *name)
386{
387 if (name) {
388 PLArenaPool *arena = name->arena;
389 name->rdns = NULL((void*)0);
390 name->arena = NULL((void*)0);
391 if (arena)
392 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
393 }
394}
395
396SECStatus
397CERT_AddRDN(CERTName *name, CERTRDN *rdn)
398{
399 name->rdns = (CERTRDN **)AddToArray(name->arena, (void **)name->rdns, rdn);
400 return name->rdns ? SECSuccess : SECFailure;
401}
402
403SECStatus
404CERT_CopyName(PLArenaPool *arena, CERTName *to, const CERTName *from)
405{
406 CERTRDN **rdns, *frdn, *trdn;
407 SECStatus rv = SECSuccess;
408
409 if (!to || !from) {
410 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
411 return SECFailure;
412 }
413
414 CERT_DestroyName(to);
415 to->arena = arena;
416
417 /* Copy each rdn from from */
418 rdns = from->rdns;
419 if (rdns) {
420 if (rdns[0] == NULL((void*)0)) {
421 rv = CERT_AddRDN(to, NULL((void*)0));
422 return rv;
423 }
424 while ((frdn = *rdns++) != NULL((void*)0)) {
425 trdn = CERT_CreateRDN(arena, NULL((void*)0));
426 if (!trdn) {
427 rv = SECFailure;
428 break;
429 }
430 rv = CERT_CopyRDN(arena, trdn, frdn);
431 if (rv != SECSuccess)
432 break;
433 rv = CERT_AddRDN(to, trdn);
434 if (rv != SECSuccess)
435 break;
436 }
437 }
438 return rv;
439}
440
441/************************************************************************/
442
443static void
444canonicalize(SECItem *foo)
445{
446 int ch, lastch, len, src, dest;
447
448 /* strip trailing whitespace. */
449 len = foo->len;
450 while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || ch == '\t' ||
451 ch == '\r' || ch == '\n')) {
452 len--;
453 }
454
455 src = 0;
456 /* strip leading whitespace. */
457 while (src < len && ((ch = foo->data[src]) == ' ' || ch == '\t' ||
458 ch == '\r' || ch == '\n')) {
459 src++;
460 }
461 dest = 0;
462 lastch = ' ';
463 while (src < len) {
464 ch = foo->data[src++];
465 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
466 ch = ' ';
467 if (ch == lastch)
468 continue;
469 } else if (ch >= 'A' && ch <= 'Z') {
470 ch |= 0x20; /* downshift */
471 }
472 foo->data[dest++] = lastch = ch;
473 }
474 foo->len = dest;
475}
476
477/* SECItems a and b contain DER-encoded printable strings. */
478SECComparison
479CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b)
480{
481 SECComparison rv = SECLessThan;
482 SECItem *aVal = CERT_DecodeAVAValue(a);
483 SECItem *bVal = CERT_DecodeAVAValue(b);
484
485 if (aVal && aVal->len && aVal->data && bVal && bVal->len && bVal->data) {
486 canonicalize(aVal);
487 canonicalize(bVal);
488 rv = SECITEM_CompareItemSECITEM_CompareItem_Util(aVal, bVal);
489 }
490 SECITEM_FreeItemSECITEM_FreeItem_Util(aVal, PR_TRUE1);
491 SECITEM_FreeItemSECITEM_FreeItem_Util(bVal, PR_TRUE1);
492 return rv;
493}
494
495SECComparison
496CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b)
497{
498 SECComparison rv;
499
500 rv = SECITEM_CompareItemSECITEM_CompareItem_Util(&a->type, &b->type);
501 if (SECEqual != rv)
502 return rv; /* Attribute types don't match. */
503 /* Let's be optimistic. Maybe the values will just compare equal. */
504 rv = SECITEM_CompareItemSECITEM_CompareItem_Util(&a->value, &b->value);
505 if (SECEqual == rv)
506 return rv; /* values compared exactly. */
507 if (a->value.len && a->value.data && b->value.len && b->value.data) {
508 /* Here, the values did not match.
509 ** If the values had different encodings, convert them to the same
510 ** encoding and compare that way.
511 */
512 if (a->value.data[0] != b->value.data[0]) {
513 /* encodings differ. Convert both to UTF-8 and compare. */
514 SECItem *aVal = CERT_DecodeAVAValue(&a->value);
515 SECItem *bVal = CERT_DecodeAVAValue(&b->value);
516 if (aVal && aVal->len && aVal->data && bVal && bVal->len &&
517 bVal->data) {
518 rv = SECITEM_CompareItemSECITEM_CompareItem_Util(aVal, bVal);
519 }
520 SECITEM_FreeItemSECITEM_FreeItem_Util(aVal, PR_TRUE1);
521 SECITEM_FreeItemSECITEM_FreeItem_Util(bVal, PR_TRUE1);
522 } else if (a->value.data[0] == 0x13) { /* both are printable strings. */
523 /* printable strings */
524 rv = CERT_CompareDERPrintableStrings(&a->value, &b->value);
525 }
526 }
527 return rv;
528}
529
530SECComparison
531CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b)
532{
533 CERTAVA **aavas, *aava;
534 CERTAVA **bavas, *bava;
535 int ac, bc;
536 SECComparison rv = SECEqual;
537
538 aavas = a->avas;
539 bavas = b->avas;
540
541 /*
542 ** Make sure array of ava's are the same length. If not, then we are
543 ** not equal
544 */
545 ac = CountArray((void **)aavas);
546 bc = CountArray((void **)bavas);
547 if (ac < bc)
548 return SECLessThan;
549 if (ac > bc)
550 return SECGreaterThan;
551
552 while (NULL((void*)0) != (aava = *aavas++)) {
553 for (bavas = b->avas; NULL((void*)0) != (bava = *bavas++);) {
554 rv = SECITEM_CompareItemSECITEM_CompareItem_Util(&aava->type, &bava->type);
555 if (SECEqual == rv) {
556 rv = CERT_CompareAVA(aava, bava);
557 if (SECEqual != rv)
558 return rv;
559 break;
560 }
561 }
562 if (!bava) /* didn't find a match */
563 return SECGreaterThan;
564 }
565 return rv;
566}
567
568SECComparison
569CERT_CompareName(const CERTName *a, const CERTName *b)
570{
571 CERTRDN **ardns;
572 CERTRDN **brdns;
573 int ac, bc;
574 SECComparison rv = SECEqual;
575
576 ardns = a->rdns;
577 brdns = b->rdns;
578
579 /*
580 ** Make sure array of rdn's are the same length. If not, then we are
581 ** not equal
582 */
583 ac = CountArray((void **)ardns);
584 bc = CountArray((void **)brdns);
585 if (ac < bc)
586 return SECLessThan;
587 if (ac > bc)
588 return SECGreaterThan;
589
590 while (rv == SECEqual && *ardns) {
591 rv = CERT_CompareRDN(*ardns++, *brdns++);
592 }
593 return rv;
594}
595
596/* Moved from certhtml.c */
597SECItem *
598CERT_DecodeAVAValue(const SECItem *derAVAValue)
599{
600 SECItem *retItem;
601 const SEC_ASN1Template *theTemplate = NULL((void*)0);
602 enum { conv_none,
603 conv_ucs4,
604 conv_ucs2,
605 conv_iso88591 } convert = conv_none;
606 SECItem avaValue = { siBuffer, 0 };
607 PORTCheapArenaPool tmpArena;
608
609 if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) {
610 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
611 return NULL((void*)0);
612 }
613
614 switch (derAVAValue->data[0]) {
615 case SEC_ASN1_UNIVERSAL_STRING0x1c:
616 convert = conv_ucs4;
617 theTemplate = SEC_ASN1_GET(SEC_UniversalStringTemplate)SEC_UniversalStringTemplate;
618 break;
619 case SEC_ASN1_IA5_STRING0x16:
620 theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate)SEC_IA5StringTemplate_Util;
621 break;
622 case SEC_ASN1_PRINTABLE_STRING0x13:
623 theTemplate = SEC_ASN1_GET(SEC_PrintableStringTemplate)SEC_PrintableStringTemplate;
624 break;
625 case SEC_ASN1_T61_STRING0x14:
626 /*
627 * Per common practice, we're not decoding actual T.61, but instead
628 * treating T61-labeled strings as containing ISO-8859-1.
629 */
630 convert = conv_iso88591;
631 theTemplate = SEC_ASN1_GET(SEC_T61StringTemplate)SEC_T61StringTemplate;
632 break;
633 case SEC_ASN1_BMP_STRING0x1e:
634 convert = conv_ucs2;
635 theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate)SEC_BMPStringTemplate_Util;
636 break;
637 case SEC_ASN1_UTF8_STRING0x0c:
638 /* No conversion needed ! */
639 theTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate)SEC_UTF8StringTemplate_Util;
640 break;
641 default:
642 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_AVA);
643 return NULL((void*)0);
644 }
645
646 PORT_Memsetmemset(&avaValue, 0, sizeof(SECItem));
647 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE(2048));
648 if (SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(&tmpArena.arena, &avaValue, theTemplate,
649 derAVAValue) != SECSuccess) {
650 PORT_DestroyCheapArena(&tmpArena);
651 return NULL((void*)0);
652 }
653
654 if (convert != conv_none) {
655 unsigned int utf8ValLen = avaValue.len * 3;
656 unsigned char *utf8Val =
657 (unsigned char *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(&tmpArena.arena, utf8ValLen);
658
659 switch (convert) {
660 case conv_ucs4:
661 if (avaValue.len % 4 != 0 ||
662 !PORT_UCS4_UTF8Conversion(PR_FALSE0, avaValue.data,
663 avaValue.len, utf8Val, utf8ValLen,
664 &utf8ValLen)) {
665 PORT_DestroyCheapArena(&tmpArena);
666 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_AVA);
667 return NULL((void*)0);
668 }
669 break;
670 case conv_ucs2:
671 if (avaValue.len % 2 != 0 ||
672 !PORT_UCS2_UTF8ConversionPORT_UCS2_UTF8Conversion_Util(PR_FALSE0, avaValue.data,
673 avaValue.len, utf8Val, utf8ValLen,
674 &utf8ValLen)) {
675 PORT_DestroyCheapArena(&tmpArena);
676 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_AVA);
677 return NULL((void*)0);
678 }
679 break;
680 case conv_iso88591:
681 if (!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len,
682 utf8Val, utf8ValLen,
683 &utf8ValLen)) {
684 PORT_DestroyCheapArena(&tmpArena);
685 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_AVA);
686 return NULL((void*)0);
687 }
688 break;
689 case conv_none:
690 PORT_Assert(0)((0)?((void)0):PR_Assert("0","secname.c",690)); /* not reached */
691 break;
692 }
693
694 avaValue.data = utf8Val;
695 avaValue.len = utf8ValLen;
696 }
697
698 retItem = SECITEM_DupItemSECITEM_DupItem_Util(&avaValue);
699 PORT_DestroyCheapArena(&tmpArena);
700 return retItem;
701}