secname.c 19 KB

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