security/nss/lib/certdb/secname.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     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"
    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 };
    24 const SEC_ASN1Template CERT_RDNTemplate[] = {
    25     { SEC_ASN1_SET_OF,
    26 	  offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) }
    27 };
    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 }
    42 static void **
    43 AddToArray(PLArenaPool *arena, void **array, void *element)
    44 {
    45     unsigned count;
    46     void **ap;
    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     }
    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 }
    72 SECOidTag
    73 CERT_GetAVATag(CERTAVA *ava)
    74 {
    75     SECOidData *oid;
    76     if (!ava->type.data) return (SECOidTag)-1;
    78     oid = SECOID_FindOID(&ava->type);
    80     if ( oid ) {
    81 	return(oid->offset);
    82     }
    83     return (SECOidTag)-1;
    84 }
    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;
    95     oidrec = SECOID_FindOIDByTag(type);
    96     if (oidrec == NULL)
    97 	return SECFailure;
    99     oid = oidrec->oid.data;
   100     oidLen = oidrec->oid.len;
   102     maxLen = cert_AVAOidTagToMaxLen(type);
   103     if (maxLen < 0) {
   104 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   105 	return SECFailure;
   106     }
   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 }
   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;
   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     }
   151     if (valueLen > maxLen) {
   152 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   153 	return SECFailure;
   154     } 
   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 }
   169 CERTAVA *
   170 CERT_CreateAVAFromRaw(PLArenaPool *pool, const SECItem * OID,
   171                       const SECItem * value)
   172 {
   173     CERTAVA *ava;
   174     int rv;
   176     ava = PORT_ArenaZNew(pool, CERTAVA);
   177     if (ava) {
   178 	rv = SECITEM_CopyItem(pool, &ava->type, OID);
   179 	if (rv) 
   180 	    return NULL;
   182 	rv = SECITEM_CopyItem(pool, &ava->value, value);
   183 	if (rv) 
   184 	    return NULL;
   185     }
   186     return ava;
   187 }
   189 CERTAVA *
   190 CERT_CreateAVAFromSECItem(PLArenaPool *arena, SECOidTag kind, int valueType,
   191                           SECItem *value)
   192 {
   193     CERTAVA *ava;
   194     int rv;
   195     unsigned maxLen;
   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 }
   213 CERTAVA *
   214 CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, int valueType, char *value)
   215 {
   216     SECItem item = { siBuffer, NULL, 0 };
   218     item.data = (PRUint8 *)value;
   219     item.len  = PORT_Strlen(value);
   221     return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item);
   222 }
   224 CERTAVA *
   225 CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from)
   226 {
   227     CERTAVA *ava;
   228     int rv;
   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;
   239   loser:
   240     return 0;
   241 }
   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 };
   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;
   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 	}
   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 }
   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 }
   299 SECStatus
   300 CERT_CopyRDN(PLArenaPool *arena, CERTRDN *to, CERTRDN *from)
   301 {
   302     CERTAVA **avas, *fava, *tava;
   303     SECStatus rv = SECSuccess;
   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 }
   326 /************************************************************************/
   328 const SEC_ASN1Template CERT_NameTemplate[] = {
   329     { SEC_ASN1_SEQUENCE_OF,
   330 	  offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) }
   331 };
   333 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate)
   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;
   345     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   346     if ( !arena ) {
   347 	return(0);
   348     }
   350     name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName));
   351     if (name) {
   352 	name->arena = arena;
   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 	}
   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 	}
   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 	}
   383 	/* null terminate the list */
   384 	*rdnp++ = 0;
   385     }
   386     return name;
   388 loser:
   389     PORT_FreeArena(arena, PR_FALSE);
   390     return(0);
   391 }
   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 }
   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 }
   412 SECStatus
   413 CERT_CopyName(PLArenaPool *arena, CERTName *to, const CERTName *from)
   414 {
   415     CERTRDN **rdns, *frdn, *trdn;
   416     SECStatus rv = SECSuccess;
   418     if (!to || !from) {
   419 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   420 	return SECFailure;
   421     }
   423     CERT_DestroyName(to);
   424     to->arena = arena;
   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 }
   450 /************************************************************************/
   452 static void
   453 canonicalize(SECItem * foo)
   454 {
   455     int ch, lastch, len, src, dest;
   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     }
   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 }
   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);
   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 }
   504 SECComparison
   505 CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b)
   506 {
   507     SECComparison rv;
   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 }
   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;
   547     aavas = a->avas;
   548     bavas = b->avas;
   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;
   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 }
   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;
   583     ardns = a->rdns;
   584     brdns = b->rdns;
   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;
   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 }
   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;
   617     if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) {
   618 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   619 	return NULL;
   620     }
   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     }
   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     }
   665     if (convert != conv_none) {
   666 	unsigned int   utf8ValLen = avaValue.len * 3;
   667 	unsigned char *utf8Val    = (unsigned char*)
   668 				    PORT_ArenaZAlloc(newarena, utf8ValLen);
   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 	}
   702 	avaValue.data = utf8Val;
   703 	avaValue.len = utf8ValLen;
   704     }
   706     retItem = SECITEM_DupItem(&avaValue);
   707     PORT_FreeArena(newarena, PR_FALSE);
   708     return retItem;
   709 }

mercurial