Back to index

lightning-sunbird  0.9+nobinonly
secname.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   John Gardiner Myers <jgmyers@speakeasy.net>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "cert.h"
00039 #include "secoid.h"
00040 #include "secder.h"  /* XXX remove this when remove the DERTemplates */
00041 #include "secasn1.h"
00042 #include "secitem.h"
00043 #include <stdarg.h>
00044 #include "secerr.h"
00045 #include "certi.h"
00046 
00047 static const SEC_ASN1Template cert_AVATemplate[] = {
00048     { SEC_ASN1_SEQUENCE,
00049          0, NULL, sizeof(CERTAVA) },
00050     { SEC_ASN1_OBJECT_ID,
00051          offsetof(CERTAVA,type), },
00052     { SEC_ASN1_ANY,
00053          offsetof(CERTAVA,value), },
00054     { 0, }
00055 };
00056 
00057 const SEC_ASN1Template CERT_RDNTemplate[] = {
00058     { SEC_ASN1_SET_OF,
00059          offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) }
00060 };
00061 
00062 
00063 static int
00064 CountArray(void **array)
00065 {
00066     int count = 0;
00067     if (array) {
00068        while (*array++) {
00069            count++;
00070        }
00071     }
00072     return count;
00073 }
00074 
00075 static void **
00076 AddToArray(PRArenaPool *arena, void **array, void *element)
00077 {
00078     unsigned count;
00079     void **ap;
00080 
00081     /* Count up number of slots already in use in the array */
00082     count = 0;
00083     ap = array;
00084     if (ap) {
00085        while (*ap++) {
00086            count++;
00087        }
00088     }
00089 
00090     if (array) {
00091        array = (void**) PORT_ArenaGrow(arena, array,
00092                                    (count + 1) * sizeof(void *),
00093                                    (count + 2) * sizeof(void *));
00094     } else {
00095        array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *));
00096     }
00097     if (array) {
00098        array[count] = element;
00099        array[count+1] = 0;
00100     }
00101     return array;
00102 }
00103 
00104 
00105 SECOidTag
00106 CERT_GetAVATag(CERTAVA *ava)
00107 {
00108     SECOidData *oid;
00109     if (!ava->type.data) return (SECOidTag)-1;
00110 
00111     oid = SECOID_FindOID(&ava->type);
00112     
00113     if ( oid ) {
00114        return(oid->offset);
00115     }
00116     return (SECOidTag)-1;
00117 }
00118 
00119 static SECStatus
00120 SetupAVAType(PRArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp)
00121 {
00122     unsigned char *oid;
00123     unsigned oidLen;
00124     unsigned char *cp;
00125     int      maxLen;
00126     SECOidData *oidrec;
00127 
00128     oidrec = SECOID_FindOIDByTag(type);
00129     if (oidrec == NULL)
00130        return SECFailure;
00131 
00132     oid = oidrec->oid.data;
00133     oidLen = oidrec->oid.len;
00134 
00135     maxLen = cert_AVAOidTagToMaxLen(type);
00136     if (maxLen < 0) {
00137        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00138        return SECFailure;
00139     }
00140 
00141     it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, oidLen);
00142     if (cp == NULL) {
00143        return SECFailure;
00144     }
00145     it->len = oidLen;
00146     PORT_Memcpy(cp, oid, oidLen);
00147     *maxLenp = (unsigned)maxLen;
00148     return SECSuccess;
00149 }
00150 
00151 static SECStatus
00152 SetupAVAValue(PRArenaPool *arena, int valueType, char *value, SECItem *it,
00153              unsigned maxLen)
00154 {
00155     unsigned valueLen, valueLenLen, total;
00156     unsigned ucs4Len = 0, ucs4MaxLen;
00157     unsigned char *cp, *ucs4Val;
00158 
00159     switch (valueType) {
00160       case SEC_ASN1_PRINTABLE_STRING:
00161       case SEC_ASN1_IA5_STRING:
00162       case SEC_ASN1_T61_STRING:
00163       case SEC_ASN1_UTF8_STRING: /* no conversion required */
00164        valueLen = PORT_Strlen(value);
00165        break;
00166       case SEC_ASN1_UNIVERSAL_STRING:
00167        valueLen = PORT_Strlen(value);
00168        ucs4MaxLen = valueLen * 6;
00169        ucs4Val = (unsigned char *)PORT_ArenaZAlloc(arena, ucs4MaxLen);
00170        if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, 
00171                                        (unsigned char *)value, valueLen,
00172                                    ucs4Val, ucs4MaxLen, &ucs4Len)) {
00173            PORT_SetError(SEC_ERROR_INVALID_ARGS);
00174            return SECFailure;
00175        }
00176        value = (char *)ucs4Val;
00177        valueLen = ucs4Len;
00178        maxLen *= 4;
00179        break;
00180       default:
00181        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00182        return SECFailure;
00183     }
00184 
00185     if (valueLen > maxLen) {
00186        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00187        return SECFailure;
00188     } 
00189 
00190     valueLenLen = DER_LengthLength(valueLen);
00191     total = 1 + valueLenLen + valueLen;
00192     it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, total);
00193     if (!cp) {
00194        return SECFailure;
00195     }
00196     it->len = total;
00197     cp = (unsigned char*) DER_StoreHeader(cp, valueType, valueLen);
00198     PORT_Memcpy(cp, value, valueLen);
00199     return SECSuccess;
00200 }
00201 
00202 CERTAVA *
00203 CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value)
00204 {
00205     CERTAVA *ava;
00206     int rv;
00207     unsigned maxLen;
00208 
00209     ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
00210     if (ava) {
00211        rv = SetupAVAType(arena, kind, &ava->type, &maxLen);
00212        if (rv) {
00213            /* Illegal AVA type */
00214            return 0;
00215        }
00216        rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);
00217        if (rv) {
00218            /* Illegal value type */
00219            return 0;
00220        }
00221     }
00222     return ava;
00223 }
00224 
00225 CERTAVA *
00226 CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from)
00227 {
00228     CERTAVA *ava;
00229     int rv;
00230 
00231     ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));
00232     if (ava) {
00233        rv = SECITEM_CopyItem(arena, &ava->type, &from->type);
00234        if (rv) goto loser;
00235        rv = SECITEM_CopyItem(arena, &ava->value, &from->value);
00236        if (rv) goto loser;
00237     }
00238     return ava;
00239 
00240   loser:
00241     return 0;
00242 }
00243 
00244 /************************************************************************/
00245 /* XXX This template needs to go away in favor of the new SEC_ASN1 version. */
00246 static const SEC_ASN1Template cert_RDNTemplate[] = {
00247     { SEC_ASN1_SET_OF,
00248          offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) }
00249 };
00250 
00251 
00252 CERTRDN *
00253 CERT_CreateRDN(PRArenaPool *arena, CERTAVA *ava0, ...)
00254 {
00255     CERTAVA *ava;
00256     CERTRDN *rdn;
00257     va_list ap;
00258     unsigned count;
00259     CERTAVA **avap;
00260 
00261     rdn = (CERTRDN*) PORT_ArenaAlloc(arena, sizeof(CERTRDN));
00262     if (rdn) {
00263        /* Count number of avas going into the rdn */
00264        count = 0;
00265        if (ava0) {
00266            count++;
00267            va_start(ap, ava0);
00268            while ((ava = va_arg(ap, CERTAVA*)) != 0) {
00269               count++;
00270            }
00271            va_end(ap);
00272        }
00273 
00274        /* Now fill in the pointers */
00275        rdn->avas = avap =
00276            (CERTAVA**) PORT_ArenaAlloc( arena, (count + 1)*sizeof(CERTAVA*));
00277        if (!avap) {
00278            return 0;
00279        }
00280        if (ava0) {
00281            *avap++ = ava0;
00282            va_start(ap, ava0);
00283            while ((ava = va_arg(ap, CERTAVA*)) != 0) {
00284               *avap++ = ava;
00285            }
00286            va_end(ap);
00287        }
00288        *avap++ = 0;
00289     }
00290     return rdn;
00291 }
00292 
00293 SECStatus
00294 CERT_AddAVA(PRArenaPool *arena, CERTRDN *rdn, CERTAVA *ava)
00295 {
00296     rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava);
00297     return rdn->avas ? SECSuccess : SECFailure;
00298 }
00299 
00300 SECStatus
00301 CERT_CopyRDN(PRArenaPool *arena, CERTRDN *to, CERTRDN *from)
00302 {
00303     CERTAVA **avas, *fava, *tava;
00304     SECStatus rv = SECSuccess;
00305 
00306     /* Copy each ava from from */
00307     avas = from->avas;
00308     if (avas) {
00309        if (avas[0] == NULL) {
00310            rv = CERT_AddAVA(arena, to, NULL);
00311            return rv;
00312        }
00313        while ((fava = *avas++) != 0) {
00314            tava = CERT_CopyAVA(arena, fava);
00315            if (!tava) {
00316               rv = SECFailure;
00317               break;
00318            }
00319            rv = CERT_AddAVA(arena, to, tava);
00320            if (rv != SECSuccess) 
00321               break;
00322        }
00323     }
00324     return rv;
00325 }
00326 
00327 /************************************************************************/
00328 
00329 const SEC_ASN1Template CERT_NameTemplate[] = {
00330     { SEC_ASN1_SEQUENCE_OF,
00331          offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) }
00332 };
00333 
00334 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate)
00335 
00336 CERTName *
00337 CERT_CreateName(CERTRDN *rdn0, ...)
00338 {
00339     CERTRDN *rdn;
00340     CERTName *name;
00341     va_list ap;
00342     unsigned count;
00343     CERTRDN **rdnp;
00344     PRArenaPool *arena;
00345     
00346     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00347     if ( !arena ) {
00348        return(0);
00349     }
00350     
00351     name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName));
00352     if (name) {
00353        name->arena = arena;
00354        
00355        /* Count number of RDNs going into the Name */
00356        if (!rdn0) {
00357            count = 0;
00358        } else {
00359            count = 1;
00360            va_start(ap, rdn0);
00361            while ((rdn = va_arg(ap, CERTRDN*)) != 0) {
00362               count++;
00363            }
00364            va_end(ap);
00365        }
00366 
00367        /* Allocate space (including space for terminal null ptr) */
00368        name->rdns = rdnp =
00369            (CERTRDN**) PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN*));
00370        if (!name->rdns) {
00371            goto loser;
00372        }
00373 
00374        /* Now fill in the pointers */
00375        if (count > 0) {
00376            *rdnp++ = rdn0;
00377            va_start(ap, rdn0);
00378            while ((rdn = va_arg(ap, CERTRDN*)) != 0) {
00379               *rdnp++ = rdn;
00380            }
00381            va_end(ap);
00382        }
00383 
00384        /* null terminate the list */
00385        *rdnp++ = 0;
00386     }
00387     return name;
00388 
00389 loser:
00390     PORT_FreeArena(arena, PR_FALSE);
00391     return(0);
00392 }
00393 
00394 void
00395 CERT_DestroyName(CERTName *name)
00396 {
00397     if (name)
00398     {
00399         PRArenaPool *arena = name->arena;
00400         name->rdns = NULL;
00401        name->arena = NULL;
00402        if (arena) PORT_FreeArena(arena, PR_FALSE);
00403     }
00404 }
00405 
00406 SECStatus
00407 CERT_AddRDN(CERTName *name, CERTRDN *rdn)
00408 {
00409     name->rdns = (CERTRDN**) AddToArray(name->arena, (void**) name->rdns, rdn);
00410     return name->rdns ? SECSuccess : SECFailure;
00411 }
00412 
00413 SECStatus
00414 CERT_CopyName(PRArenaPool *arena, CERTName *to, CERTName *from)
00415 {
00416     CERTRDN **rdns, *frdn, *trdn;
00417     SECStatus rv = SECSuccess;
00418 
00419     if (!to || !from) {
00420        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00421        return SECFailure;
00422     }
00423 
00424     CERT_DestroyName(to);
00425     to->arena = arena;
00426 
00427     /* Copy each rdn from from */
00428     rdns = from->rdns;
00429     if (rdns) {
00430        if (rdns[0] == NULL) {
00431            rv = CERT_AddRDN(to, NULL);
00432            return rv;
00433        }
00434        while ((frdn = *rdns++) != NULL) {
00435            trdn = CERT_CreateRDN(arena, 0);
00436            if (!trdn) {
00437               rv = SECFailure;
00438               break;
00439            }
00440            rv = CERT_CopyRDN(arena, trdn, frdn);
00441            if (rv != SECSuccess) 
00442                break;
00443            rv = CERT_AddRDN(to, trdn);
00444            if (rv != SECSuccess) 
00445                break;
00446        }
00447     }
00448     return rv;
00449 }
00450 
00451 /************************************************************************/
00452 
00453 static void
00454 canonicalize(SECItem * foo)
00455 {
00456     int ch, lastch, len, src, dest;
00457 
00458     /* strip trailing whitespace. */
00459     len = foo->len;
00460     while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || 
00461            ch == '\t' || ch == '\r' || ch == '\n')) {
00462        len--;
00463     }
00464 
00465     src = 0;
00466     /* strip leading whitespace. */
00467     while (src < len && ((ch = foo->data[src]) == ' ' || 
00468            ch == '\t' || ch == '\r' || ch == '\n')) {
00469        src++;
00470     }
00471     dest = 0; lastch = ' ';
00472     while (src < len) {
00473         ch = foo->data[src++];
00474        if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
00475            ch = ' ';
00476            if (ch == lastch)
00477                continue;
00478        } else if (ch >= 'A' && ch <= 'Z') {
00479            ch |= 0x20;  /* downshift */
00480        }
00481        foo->data[dest++] = lastch = ch;
00482     }
00483     foo->len = dest;
00484 }
00485 
00486 /* SECItems a and b contain DER-encoded printable strings. */
00487 SECComparison
00488 CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b)
00489 {
00490     SECComparison rv = SECLessThan;
00491     SECItem * aVal = CERT_DecodeAVAValue(a);
00492     SECItem * bVal = CERT_DecodeAVAValue(b);
00493 
00494     if (aVal && aVal->len && aVal->data &&
00495        bVal && bVal->len && bVal->data) {
00496        canonicalize(aVal);
00497        canonicalize(bVal);
00498        rv = SECITEM_CompareItem(aVal, bVal);
00499     }
00500     SECITEM_FreeItem(aVal, PR_TRUE);
00501     SECITEM_FreeItem(bVal, PR_TRUE);
00502     return rv;
00503 }
00504 
00505 SECComparison
00506 CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b)
00507 {
00508     SECComparison rv;
00509 
00510     rv = SECITEM_CompareItem(&a->type, &b->type);
00511     if (SECEqual != rv)
00512        return rv;  /* Attribute types don't match. */
00513     /* Let's be optimistic.  Maybe the values will just compare equal. */
00514     rv = SECITEM_CompareItem(&a->value, &b->value);
00515     if (SECEqual == rv)
00516         return rv;  /* values compared exactly. */
00517     if (a->value.len && a->value.data && b->value.len && b->value.data) {
00518        /* Here, the values did not match.  
00519        ** If the values had different encodings, convert them to the same
00520        ** encoding and compare that way.
00521        */
00522        if (a->value.data[0] != b->value.data[0]) {
00523            /* encodings differ.  Convert both to UTF-8 and compare. */
00524            SECItem * aVal = CERT_DecodeAVAValue(&a->value);
00525            SECItem * bVal = CERT_DecodeAVAValue(&b->value);
00526            if (aVal && aVal->len && aVal->data &&
00527                bVal && bVal->len && bVal->data) {
00528               rv = SECITEM_CompareItem(aVal, bVal);
00529            }
00530            SECITEM_FreeItem(aVal, PR_TRUE);
00531            SECITEM_FreeItem(bVal, PR_TRUE);
00532        } else if (a->value.data[0] == 0x13) { /* both are printable strings. */
00533            /* printable strings */
00534            rv = CERT_CompareDERPrintableStrings(&a->value, &b->value);
00535        }
00536     }
00537     return rv;
00538 }
00539 
00540 SECComparison
00541 CERT_CompareRDN(CERTRDN *a, CERTRDN *b)
00542 {
00543     CERTAVA **aavas, *aava;
00544     CERTAVA **bavas, *bava;
00545     int ac, bc;
00546     SECComparison rv = SECEqual;
00547 
00548     aavas = a->avas;
00549     bavas = b->avas;
00550 
00551     /*
00552     ** Make sure array of ava's are the same length. If not, then we are
00553     ** not equal
00554     */
00555     ac = CountArray((void**) aavas);
00556     bc = CountArray((void**) bavas);
00557     if (ac < bc) return SECLessThan;
00558     if (ac > bc) return SECGreaterThan;
00559 
00560     for (;;) {
00561        aava = *aavas++;
00562        bava = *bavas++;
00563        if (!aava) {
00564            break;
00565        }
00566        rv = CERT_CompareAVA(aava, bava);
00567        if (rv) return rv;
00568     }
00569     return rv;
00570 }
00571 
00572 SECComparison
00573 CERT_CompareName(CERTName *a, CERTName *b)
00574 {
00575     CERTRDN **ardns, *ardn;
00576     CERTRDN **brdns, *brdn;
00577     int ac, bc;
00578     SECComparison rv = SECEqual;
00579 
00580     ardns = a->rdns;
00581     brdns = b->rdns;
00582 
00583     /*
00584     ** Make sure array of rdn's are the same length. If not, then we are
00585     ** not equal
00586     */
00587     ac = CountArray((void**) ardns);
00588     bc = CountArray((void**) brdns);
00589     if (ac < bc) return SECLessThan;
00590     if (ac > bc) return SECGreaterThan;
00591 
00592     for (;;) {
00593        ardn = *ardns++;
00594        brdn = *brdns++;
00595        if (!ardn) {
00596            break;
00597        }
00598        rv = CERT_CompareRDN(ardn, brdn);
00599        if (rv) return rv;
00600     }
00601     return rv;
00602 }
00603 
00604 /* Moved from certhtml.c */
00605 SECItem *
00606 CERT_DecodeAVAValue(const SECItem *derAVAValue)
00607 {
00608           SECItem          *retItem; 
00609     const SEC_ASN1Template *theTemplate       = NULL;
00610           enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none;
00611           SECItem           avaValue          = {siBuffer, 0}; 
00612           PLArenaPool      *newarena          = NULL;
00613 
00614     if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) {
00615        return NULL;
00616     }
00617 
00618     switch(derAVAValue->data[0]) {
00619        case SEC_ASN1_UNIVERSAL_STRING:
00620            convert = conv_ucs4;
00621            theTemplate = SEC_UniversalStringTemplate;
00622            break;
00623        case SEC_ASN1_IA5_STRING:
00624            theTemplate = SEC_IA5StringTemplate;
00625            break;
00626        case SEC_ASN1_PRINTABLE_STRING:
00627            theTemplate = SEC_PrintableStringTemplate;
00628            break;
00629        case SEC_ASN1_T61_STRING:
00630            /*
00631             * Per common practice, we're not decoding actual T.61, but instead
00632             * treating T61-labeled strings as containing ISO-8859-1.
00633             */
00634            convert = conv_iso88591;
00635            theTemplate = SEC_T61StringTemplate;
00636            break;
00637        case SEC_ASN1_BMP_STRING:
00638            convert = conv_ucs2;
00639            theTemplate = SEC_BMPStringTemplate;
00640            break;
00641        case SEC_ASN1_UTF8_STRING:
00642            /* No conversion needed ! */
00643            theTemplate = SEC_UTF8StringTemplate;
00644            break;
00645        default:
00646            return NULL;
00647     }
00648 
00649     PORT_Memset(&avaValue, 0, sizeof(SECItem));
00650     newarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00651     if (!newarena) {
00652         return NULL;
00653     }
00654     if(SEC_QuickDERDecodeItem(newarena, &avaValue, theTemplate, derAVAValue) 
00655                             != SECSuccess) {
00656        PORT_FreeArena(newarena, PR_FALSE);
00657        return NULL;
00658     }
00659 
00660     if (convert != conv_none) {
00661        unsigned int   utf8ValLen = avaValue.len * 3;
00662        unsigned char *utf8Val    = (unsigned char*)
00663                                 PORT_ArenaZAlloc(newarena, utf8ValLen);
00664 
00665         switch (convert) {
00666         case conv_ucs4:
00667            if(avaValue.len % 4 != 0 ||
00668               !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
00669                                    utf8Val, utf8ValLen, &utf8ValLen)) {
00670                 PORT_FreeArena(newarena, PR_FALSE);
00671                 PORT_SetError(SEC_ERROR_INVALID_AVA);
00672               return NULL;
00673           }
00674           break;
00675        case conv_ucs2:
00676            if(avaValue.len % 2 != 0 ||
00677               !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,
00678                                    utf8Val, utf8ValLen, &utf8ValLen)) {
00679                 PORT_FreeArena(newarena, PR_FALSE);
00680                 PORT_SetError(SEC_ERROR_INVALID_AVA);
00681               return NULL;
00682           }
00683           break;
00684        case conv_iso88591:
00685            if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len,
00686                                    utf8Val, utf8ValLen, &utf8ValLen)) {
00687                 PORT_FreeArena(newarena, PR_FALSE);
00688                 PORT_SetError(SEC_ERROR_INVALID_AVA);
00689               return NULL;
00690           }
00691           break;
00692        case conv_none:
00693           PORT_Assert(0); /* not reached */
00694           break;
00695        }
00696          
00697        avaValue.data = utf8Val;
00698        avaValue.len = utf8ValLen;
00699     }
00700 
00701     retItem = SECITEM_DupItem(&avaValue);
00702     PORT_FreeArena(newarena, PR_FALSE);
00703     return retItem;
00704 }