1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/certdb/secname.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,709 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "cert.h" 1.9 +#include "secoid.h" 1.10 +#include "secder.h" /* XXX remove this when remove the DERTemplates */ 1.11 +#include "secasn1.h" 1.12 +#include "secitem.h" 1.13 +#include <stdarg.h> 1.14 +#include "secerr.h" 1.15 +#include "certi.h" 1.16 + 1.17 +static const SEC_ASN1Template cert_AVATemplate[] = { 1.18 + { SEC_ASN1_SEQUENCE, 1.19 + 0, NULL, sizeof(CERTAVA) }, 1.20 + { SEC_ASN1_OBJECT_ID, 1.21 + offsetof(CERTAVA,type), }, 1.22 + { SEC_ASN1_ANY, 1.23 + offsetof(CERTAVA,value), }, 1.24 + { 0, } 1.25 +}; 1.26 + 1.27 +const SEC_ASN1Template CERT_RDNTemplate[] = { 1.28 + { SEC_ASN1_SET_OF, 1.29 + offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } 1.30 +}; 1.31 + 1.32 + 1.33 +static int 1.34 +CountArray(void **array) 1.35 +{ 1.36 + int count = 0; 1.37 + if (array) { 1.38 + while (*array++) { 1.39 + count++; 1.40 + } 1.41 + } 1.42 + return count; 1.43 +} 1.44 + 1.45 +static void ** 1.46 +AddToArray(PLArenaPool *arena, void **array, void *element) 1.47 +{ 1.48 + unsigned count; 1.49 + void **ap; 1.50 + 1.51 + /* Count up number of slots already in use in the array */ 1.52 + count = 0; 1.53 + ap = array; 1.54 + if (ap) { 1.55 + while (*ap++) { 1.56 + count++; 1.57 + } 1.58 + } 1.59 + 1.60 + if (array) { 1.61 + array = (void**) PORT_ArenaGrow(arena, array, 1.62 + (count + 1) * sizeof(void *), 1.63 + (count + 2) * sizeof(void *)); 1.64 + } else { 1.65 + array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *)); 1.66 + } 1.67 + if (array) { 1.68 + array[count] = element; 1.69 + array[count+1] = 0; 1.70 + } 1.71 + return array; 1.72 +} 1.73 + 1.74 + 1.75 +SECOidTag 1.76 +CERT_GetAVATag(CERTAVA *ava) 1.77 +{ 1.78 + SECOidData *oid; 1.79 + if (!ava->type.data) return (SECOidTag)-1; 1.80 + 1.81 + oid = SECOID_FindOID(&ava->type); 1.82 + 1.83 + if ( oid ) { 1.84 + return(oid->offset); 1.85 + } 1.86 + return (SECOidTag)-1; 1.87 +} 1.88 + 1.89 +static SECStatus 1.90 +SetupAVAType(PLArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp) 1.91 +{ 1.92 + unsigned char *oid; 1.93 + unsigned oidLen; 1.94 + unsigned char *cp; 1.95 + int maxLen; 1.96 + SECOidData *oidrec; 1.97 + 1.98 + oidrec = SECOID_FindOIDByTag(type); 1.99 + if (oidrec == NULL) 1.100 + return SECFailure; 1.101 + 1.102 + oid = oidrec->oid.data; 1.103 + oidLen = oidrec->oid.len; 1.104 + 1.105 + maxLen = cert_AVAOidTagToMaxLen(type); 1.106 + if (maxLen < 0) { 1.107 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.108 + return SECFailure; 1.109 + } 1.110 + 1.111 + it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, oidLen); 1.112 + if (cp == NULL) { 1.113 + return SECFailure; 1.114 + } 1.115 + it->len = oidLen; 1.116 + PORT_Memcpy(cp, oid, oidLen); 1.117 + *maxLenp = (unsigned)maxLen; 1.118 + return SECSuccess; 1.119 +} 1.120 + 1.121 +static SECStatus 1.122 +SetupAVAValue(PLArenaPool *arena, int valueType, const SECItem *in, 1.123 + SECItem *out, unsigned maxLen) 1.124 +{ 1.125 + PRUint8 *value, *cp, *ucs4Val; 1.126 + unsigned valueLen, valueLenLen, total; 1.127 + unsigned ucs4Len = 0, ucs4MaxLen; 1.128 + 1.129 + value = in->data; 1.130 + valueLen = in->len; 1.131 + switch (valueType) { 1.132 + case SEC_ASN1_PRINTABLE_STRING: 1.133 + case SEC_ASN1_IA5_STRING: 1.134 + case SEC_ASN1_T61_STRING: 1.135 + case SEC_ASN1_UTF8_STRING: /* no conversion required */ 1.136 + break; 1.137 + case SEC_ASN1_UNIVERSAL_STRING: 1.138 + ucs4MaxLen = valueLen * 6; 1.139 + ucs4Val = (PRUint8 *)PORT_ArenaZAlloc(arena, ucs4MaxLen); 1.140 + if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, value, valueLen, 1.141 + ucs4Val, ucs4MaxLen, &ucs4Len)) { 1.142 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.143 + return SECFailure; 1.144 + } 1.145 + value = ucs4Val; 1.146 + valueLen = ucs4Len; 1.147 + maxLen *= 4; 1.148 + break; 1.149 + default: 1.150 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.151 + return SECFailure; 1.152 + } 1.153 + 1.154 + if (valueLen > maxLen) { 1.155 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.156 + return SECFailure; 1.157 + } 1.158 + 1.159 + valueLenLen = DER_LengthLength(valueLen); 1.160 + total = 1 + valueLenLen + valueLen; 1.161 + cp = (PRUint8*)PORT_ArenaAlloc(arena, total); 1.162 + if (!cp) { 1.163 + return SECFailure; 1.164 + } 1.165 + out->data = cp; 1.166 + out->len = total; 1.167 + cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen); 1.168 + PORT_Memcpy(cp, value, valueLen); 1.169 + return SECSuccess; 1.170 +} 1.171 + 1.172 +CERTAVA * 1.173 +CERT_CreateAVAFromRaw(PLArenaPool *pool, const SECItem * OID, 1.174 + const SECItem * value) 1.175 +{ 1.176 + CERTAVA *ava; 1.177 + int rv; 1.178 + 1.179 + ava = PORT_ArenaZNew(pool, CERTAVA); 1.180 + if (ava) { 1.181 + rv = SECITEM_CopyItem(pool, &ava->type, OID); 1.182 + if (rv) 1.183 + return NULL; 1.184 + 1.185 + rv = SECITEM_CopyItem(pool, &ava->value, value); 1.186 + if (rv) 1.187 + return NULL; 1.188 + } 1.189 + return ava; 1.190 +} 1.191 + 1.192 +CERTAVA * 1.193 +CERT_CreateAVAFromSECItem(PLArenaPool *arena, SECOidTag kind, int valueType, 1.194 + SECItem *value) 1.195 +{ 1.196 + CERTAVA *ava; 1.197 + int rv; 1.198 + unsigned maxLen; 1.199 + 1.200 + ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); 1.201 + if (ava) { 1.202 + rv = SetupAVAType(arena, kind, &ava->type, &maxLen); 1.203 + if (rv) { 1.204 + /* Illegal AVA type */ 1.205 + return NULL; 1.206 + } 1.207 + rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen); 1.208 + if (rv) { 1.209 + /* Illegal value type */ 1.210 + return NULL; 1.211 + } 1.212 + } 1.213 + return ava; 1.214 +} 1.215 + 1.216 +CERTAVA * 1.217 +CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, int valueType, char *value) 1.218 +{ 1.219 + SECItem item = { siBuffer, NULL, 0 }; 1.220 + 1.221 + item.data = (PRUint8 *)value; 1.222 + item.len = PORT_Strlen(value); 1.223 + 1.224 + return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item); 1.225 +} 1.226 + 1.227 +CERTAVA * 1.228 +CERT_CopyAVA(PLArenaPool *arena, CERTAVA *from) 1.229 +{ 1.230 + CERTAVA *ava; 1.231 + int rv; 1.232 + 1.233 + ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA)); 1.234 + if (ava) { 1.235 + rv = SECITEM_CopyItem(arena, &ava->type, &from->type); 1.236 + if (rv) goto loser; 1.237 + rv = SECITEM_CopyItem(arena, &ava->value, &from->value); 1.238 + if (rv) goto loser; 1.239 + } 1.240 + return ava; 1.241 + 1.242 + loser: 1.243 + return 0; 1.244 +} 1.245 + 1.246 +/************************************************************************/ 1.247 +/* XXX This template needs to go away in favor of the new SEC_ASN1 version. */ 1.248 +static const SEC_ASN1Template cert_RDNTemplate[] = { 1.249 + { SEC_ASN1_SET_OF, 1.250 + offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } 1.251 +}; 1.252 + 1.253 + 1.254 +CERTRDN * 1.255 +CERT_CreateRDN(PLArenaPool *arena, CERTAVA *ava0, ...) 1.256 +{ 1.257 + CERTAVA *ava; 1.258 + CERTRDN *rdn; 1.259 + va_list ap; 1.260 + unsigned count; 1.261 + CERTAVA **avap; 1.262 + 1.263 + rdn = (CERTRDN*) PORT_ArenaAlloc(arena, sizeof(CERTRDN)); 1.264 + if (rdn) { 1.265 + /* Count number of avas going into the rdn */ 1.266 + count = 0; 1.267 + if (ava0) { 1.268 + count++; 1.269 + va_start(ap, ava0); 1.270 + while ((ava = va_arg(ap, CERTAVA*)) != 0) { 1.271 + count++; 1.272 + } 1.273 + va_end(ap); 1.274 + } 1.275 + 1.276 + /* Now fill in the pointers */ 1.277 + rdn->avas = avap = 1.278 + (CERTAVA**) PORT_ArenaAlloc( arena, (count + 1)*sizeof(CERTAVA*)); 1.279 + if (!avap) { 1.280 + return 0; 1.281 + } 1.282 + if (ava0) { 1.283 + *avap++ = ava0; 1.284 + va_start(ap, ava0); 1.285 + while ((ava = va_arg(ap, CERTAVA*)) != 0) { 1.286 + *avap++ = ava; 1.287 + } 1.288 + va_end(ap); 1.289 + } 1.290 + *avap++ = 0; 1.291 + } 1.292 + return rdn; 1.293 +} 1.294 + 1.295 +SECStatus 1.296 +CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava) 1.297 +{ 1.298 + rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava); 1.299 + return rdn->avas ? SECSuccess : SECFailure; 1.300 +} 1.301 + 1.302 +SECStatus 1.303 +CERT_CopyRDN(PLArenaPool *arena, CERTRDN *to, CERTRDN *from) 1.304 +{ 1.305 + CERTAVA **avas, *fava, *tava; 1.306 + SECStatus rv = SECSuccess; 1.307 + 1.308 + /* Copy each ava from from */ 1.309 + avas = from->avas; 1.310 + if (avas) { 1.311 + if (avas[0] == NULL) { 1.312 + rv = CERT_AddAVA(arena, to, NULL); 1.313 + return rv; 1.314 + } 1.315 + while ((fava = *avas++) != 0) { 1.316 + tava = CERT_CopyAVA(arena, fava); 1.317 + if (!tava) { 1.318 + rv = SECFailure; 1.319 + break; 1.320 + } 1.321 + rv = CERT_AddAVA(arena, to, tava); 1.322 + if (rv != SECSuccess) 1.323 + break; 1.324 + } 1.325 + } 1.326 + return rv; 1.327 +} 1.328 + 1.329 +/************************************************************************/ 1.330 + 1.331 +const SEC_ASN1Template CERT_NameTemplate[] = { 1.332 + { SEC_ASN1_SEQUENCE_OF, 1.333 + offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) } 1.334 +}; 1.335 + 1.336 +SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate) 1.337 + 1.338 +CERTName * 1.339 +CERT_CreateName(CERTRDN *rdn0, ...) 1.340 +{ 1.341 + CERTRDN *rdn; 1.342 + CERTName *name; 1.343 + va_list ap; 1.344 + unsigned count; 1.345 + CERTRDN **rdnp; 1.346 + PLArenaPool *arena; 1.347 + 1.348 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.349 + if ( !arena ) { 1.350 + return(0); 1.351 + } 1.352 + 1.353 + name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName)); 1.354 + if (name) { 1.355 + name->arena = arena; 1.356 + 1.357 + /* Count number of RDNs going into the Name */ 1.358 + if (!rdn0) { 1.359 + count = 0; 1.360 + } else { 1.361 + count = 1; 1.362 + va_start(ap, rdn0); 1.363 + while ((rdn = va_arg(ap, CERTRDN*)) != 0) { 1.364 + count++; 1.365 + } 1.366 + va_end(ap); 1.367 + } 1.368 + 1.369 + /* Allocate space (including space for terminal null ptr) */ 1.370 + name->rdns = rdnp = 1.371 + (CERTRDN**) PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN*)); 1.372 + if (!name->rdns) { 1.373 + goto loser; 1.374 + } 1.375 + 1.376 + /* Now fill in the pointers */ 1.377 + if (count > 0) { 1.378 + *rdnp++ = rdn0; 1.379 + va_start(ap, rdn0); 1.380 + while ((rdn = va_arg(ap, CERTRDN*)) != 0) { 1.381 + *rdnp++ = rdn; 1.382 + } 1.383 + va_end(ap); 1.384 + } 1.385 + 1.386 + /* null terminate the list */ 1.387 + *rdnp++ = 0; 1.388 + } 1.389 + return name; 1.390 + 1.391 +loser: 1.392 + PORT_FreeArena(arena, PR_FALSE); 1.393 + return(0); 1.394 +} 1.395 + 1.396 +void 1.397 +CERT_DestroyName(CERTName *name) 1.398 +{ 1.399 + if (name) 1.400 + { 1.401 + PLArenaPool *arena = name->arena; 1.402 + name->rdns = NULL; 1.403 + name->arena = NULL; 1.404 + if (arena) PORT_FreeArena(arena, PR_FALSE); 1.405 + } 1.406 +} 1.407 + 1.408 +SECStatus 1.409 +CERT_AddRDN(CERTName *name, CERTRDN *rdn) 1.410 +{ 1.411 + name->rdns = (CERTRDN**) AddToArray(name->arena, (void**) name->rdns, rdn); 1.412 + return name->rdns ? SECSuccess : SECFailure; 1.413 +} 1.414 + 1.415 +SECStatus 1.416 +CERT_CopyName(PLArenaPool *arena, CERTName *to, const CERTName *from) 1.417 +{ 1.418 + CERTRDN **rdns, *frdn, *trdn; 1.419 + SECStatus rv = SECSuccess; 1.420 + 1.421 + if (!to || !from) { 1.422 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.423 + return SECFailure; 1.424 + } 1.425 + 1.426 + CERT_DestroyName(to); 1.427 + to->arena = arena; 1.428 + 1.429 + /* Copy each rdn from from */ 1.430 + rdns = from->rdns; 1.431 + if (rdns) { 1.432 + if (rdns[0] == NULL) { 1.433 + rv = CERT_AddRDN(to, NULL); 1.434 + return rv; 1.435 + } 1.436 + while ((frdn = *rdns++) != NULL) { 1.437 + trdn = CERT_CreateRDN(arena, NULL); 1.438 + if (!trdn) { 1.439 + rv = SECFailure; 1.440 + break; 1.441 + } 1.442 + rv = CERT_CopyRDN(arena, trdn, frdn); 1.443 + if (rv != SECSuccess) 1.444 + break; 1.445 + rv = CERT_AddRDN(to, trdn); 1.446 + if (rv != SECSuccess) 1.447 + break; 1.448 + } 1.449 + } 1.450 + return rv; 1.451 +} 1.452 + 1.453 +/************************************************************************/ 1.454 + 1.455 +static void 1.456 +canonicalize(SECItem * foo) 1.457 +{ 1.458 + int ch, lastch, len, src, dest; 1.459 + 1.460 + /* strip trailing whitespace. */ 1.461 + len = foo->len; 1.462 + while (len > 0 && ((ch = foo->data[len - 1]) == ' ' || 1.463 + ch == '\t' || ch == '\r' || ch == '\n')) { 1.464 + len--; 1.465 + } 1.466 + 1.467 + src = 0; 1.468 + /* strip leading whitespace. */ 1.469 + while (src < len && ((ch = foo->data[src]) == ' ' || 1.470 + ch == '\t' || ch == '\r' || ch == '\n')) { 1.471 + src++; 1.472 + } 1.473 + dest = 0; lastch = ' '; 1.474 + while (src < len) { 1.475 + ch = foo->data[src++]; 1.476 + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { 1.477 + ch = ' '; 1.478 + if (ch == lastch) 1.479 + continue; 1.480 + } else if (ch >= 'A' && ch <= 'Z') { 1.481 + ch |= 0x20; /* downshift */ 1.482 + } 1.483 + foo->data[dest++] = lastch = ch; 1.484 + } 1.485 + foo->len = dest; 1.486 +} 1.487 + 1.488 +/* SECItems a and b contain DER-encoded printable strings. */ 1.489 +SECComparison 1.490 +CERT_CompareDERPrintableStrings(const SECItem *a, const SECItem *b) 1.491 +{ 1.492 + SECComparison rv = SECLessThan; 1.493 + SECItem * aVal = CERT_DecodeAVAValue(a); 1.494 + SECItem * bVal = CERT_DecodeAVAValue(b); 1.495 + 1.496 + if (aVal && aVal->len && aVal->data && 1.497 + bVal && bVal->len && bVal->data) { 1.498 + canonicalize(aVal); 1.499 + canonicalize(bVal); 1.500 + rv = SECITEM_CompareItem(aVal, bVal); 1.501 + } 1.502 + SECITEM_FreeItem(aVal, PR_TRUE); 1.503 + SECITEM_FreeItem(bVal, PR_TRUE); 1.504 + return rv; 1.505 +} 1.506 + 1.507 +SECComparison 1.508 +CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) 1.509 +{ 1.510 + SECComparison rv; 1.511 + 1.512 + rv = SECITEM_CompareItem(&a->type, &b->type); 1.513 + if (SECEqual != rv) 1.514 + return rv; /* Attribute types don't match. */ 1.515 + /* Let's be optimistic. Maybe the values will just compare equal. */ 1.516 + rv = SECITEM_CompareItem(&a->value, &b->value); 1.517 + if (SECEqual == rv) 1.518 + return rv; /* values compared exactly. */ 1.519 + if (a->value.len && a->value.data && b->value.len && b->value.data) { 1.520 + /* Here, the values did not match. 1.521 + ** If the values had different encodings, convert them to the same 1.522 + ** encoding and compare that way. 1.523 + */ 1.524 + if (a->value.data[0] != b->value.data[0]) { 1.525 + /* encodings differ. Convert both to UTF-8 and compare. */ 1.526 + SECItem * aVal = CERT_DecodeAVAValue(&a->value); 1.527 + SECItem * bVal = CERT_DecodeAVAValue(&b->value); 1.528 + if (aVal && aVal->len && aVal->data && 1.529 + bVal && bVal->len && bVal->data) { 1.530 + rv = SECITEM_CompareItem(aVal, bVal); 1.531 + } 1.532 + SECITEM_FreeItem(aVal, PR_TRUE); 1.533 + SECITEM_FreeItem(bVal, PR_TRUE); 1.534 + } else if (a->value.data[0] == 0x13) { /* both are printable strings. */ 1.535 + /* printable strings */ 1.536 + rv = CERT_CompareDERPrintableStrings(&a->value, &b->value); 1.537 + } 1.538 + } 1.539 + return rv; 1.540 +} 1.541 + 1.542 +SECComparison 1.543 +CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b) 1.544 +{ 1.545 + CERTAVA **aavas, *aava; 1.546 + CERTAVA **bavas, *bava; 1.547 + int ac, bc; 1.548 + SECComparison rv = SECEqual; 1.549 + 1.550 + aavas = a->avas; 1.551 + bavas = b->avas; 1.552 + 1.553 + /* 1.554 + ** Make sure array of ava's are the same length. If not, then we are 1.555 + ** not equal 1.556 + */ 1.557 + ac = CountArray((void**) aavas); 1.558 + bc = CountArray((void**) bavas); 1.559 + if (ac < bc) return SECLessThan; 1.560 + if (ac > bc) return SECGreaterThan; 1.561 + 1.562 + while (NULL != (aava = *aavas++)) { 1.563 + for (bavas = b->avas; NULL != (bava = *bavas++); ) { 1.564 + rv = SECITEM_CompareItem(&aava->type, &bava->type); 1.565 + if (SECEqual == rv) { 1.566 + rv = CERT_CompareAVA(aava, bava); 1.567 + if (SECEqual != rv) 1.568 + return rv; 1.569 + break; 1.570 + } 1.571 + } 1.572 + if (!bava) /* didn't find a match */ 1.573 + return SECGreaterThan; 1.574 + } 1.575 + return rv; 1.576 +} 1.577 + 1.578 +SECComparison 1.579 +CERT_CompareName(const CERTName *a, const CERTName *b) 1.580 +{ 1.581 + CERTRDN **ardns, *ardn; 1.582 + CERTRDN **brdns, *brdn; 1.583 + int ac, bc; 1.584 + SECComparison rv = SECEqual; 1.585 + 1.586 + ardns = a->rdns; 1.587 + brdns = b->rdns; 1.588 + 1.589 + /* 1.590 + ** Make sure array of rdn's are the same length. If not, then we are 1.591 + ** not equal 1.592 + */ 1.593 + ac = CountArray((void**) ardns); 1.594 + bc = CountArray((void**) brdns); 1.595 + if (ac < bc) return SECLessThan; 1.596 + if (ac > bc) return SECGreaterThan; 1.597 + 1.598 + for (;;) { 1.599 + ardn = *ardns++; 1.600 + brdn = *brdns++; 1.601 + if (!ardn) { 1.602 + break; 1.603 + } 1.604 + rv = CERT_CompareRDN(ardn, brdn); 1.605 + if (rv) return rv; 1.606 + } 1.607 + return rv; 1.608 +} 1.609 + 1.610 +/* Moved from certhtml.c */ 1.611 +SECItem * 1.612 +CERT_DecodeAVAValue(const SECItem *derAVAValue) 1.613 +{ 1.614 + SECItem *retItem; 1.615 + const SEC_ASN1Template *theTemplate = NULL; 1.616 + enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none; 1.617 + SECItem avaValue = {siBuffer, 0}; 1.618 + PLArenaPool *newarena = NULL; 1.619 + 1.620 + if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) { 1.621 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.622 + return NULL; 1.623 + } 1.624 + 1.625 + switch(derAVAValue->data[0]) { 1.626 + case SEC_ASN1_UNIVERSAL_STRING: 1.627 + convert = conv_ucs4; 1.628 + theTemplate = SEC_ASN1_GET(SEC_UniversalStringTemplate); 1.629 + break; 1.630 + case SEC_ASN1_IA5_STRING: 1.631 + theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); 1.632 + break; 1.633 + case SEC_ASN1_PRINTABLE_STRING: 1.634 + theTemplate = SEC_ASN1_GET(SEC_PrintableStringTemplate); 1.635 + break; 1.636 + case SEC_ASN1_T61_STRING: 1.637 + /* 1.638 + * Per common practice, we're not decoding actual T.61, but instead 1.639 + * treating T61-labeled strings as containing ISO-8859-1. 1.640 + */ 1.641 + convert = conv_iso88591; 1.642 + theTemplate = SEC_ASN1_GET(SEC_T61StringTemplate); 1.643 + break; 1.644 + case SEC_ASN1_BMP_STRING: 1.645 + convert = conv_ucs2; 1.646 + theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate); 1.647 + break; 1.648 + case SEC_ASN1_UTF8_STRING: 1.649 + /* No conversion needed ! */ 1.650 + theTemplate = SEC_ASN1_GET(SEC_UTF8StringTemplate); 1.651 + break; 1.652 + default: 1.653 + PORT_SetError(SEC_ERROR_INVALID_AVA); 1.654 + return NULL; 1.655 + } 1.656 + 1.657 + PORT_Memset(&avaValue, 0, sizeof(SECItem)); 1.658 + newarena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.659 + if (!newarena) { 1.660 + return NULL; 1.661 + } 1.662 + if(SEC_QuickDERDecodeItem(newarena, &avaValue, theTemplate, derAVAValue) 1.663 + != SECSuccess) { 1.664 + PORT_FreeArena(newarena, PR_FALSE); 1.665 + return NULL; 1.666 + } 1.667 + 1.668 + if (convert != conv_none) { 1.669 + unsigned int utf8ValLen = avaValue.len * 3; 1.670 + unsigned char *utf8Val = (unsigned char*) 1.671 + PORT_ArenaZAlloc(newarena, utf8ValLen); 1.672 + 1.673 + switch (convert) { 1.674 + case conv_ucs4: 1.675 + if(avaValue.len % 4 != 0 || 1.676 + !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, 1.677 + utf8Val, utf8ValLen, &utf8ValLen)) { 1.678 + PORT_FreeArena(newarena, PR_FALSE); 1.679 + PORT_SetError(SEC_ERROR_INVALID_AVA); 1.680 + return NULL; 1.681 + } 1.682 + break; 1.683 + case conv_ucs2: 1.684 + if(avaValue.len % 2 != 0 || 1.685 + !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, 1.686 + utf8Val, utf8ValLen, &utf8ValLen)) { 1.687 + PORT_FreeArena(newarena, PR_FALSE); 1.688 + PORT_SetError(SEC_ERROR_INVALID_AVA); 1.689 + return NULL; 1.690 + } 1.691 + break; 1.692 + case conv_iso88591: 1.693 + if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len, 1.694 + utf8Val, utf8ValLen, &utf8ValLen)) { 1.695 + PORT_FreeArena(newarena, PR_FALSE); 1.696 + PORT_SetError(SEC_ERROR_INVALID_AVA); 1.697 + return NULL; 1.698 + } 1.699 + break; 1.700 + case conv_none: 1.701 + PORT_Assert(0); /* not reached */ 1.702 + break; 1.703 + } 1.704 + 1.705 + avaValue.data = utf8Val; 1.706 + avaValue.len = utf8ValLen; 1.707 + } 1.708 + 1.709 + retItem = SECITEM_DupItem(&avaValue); 1.710 + PORT_FreeArena(newarena, PR_FALSE); 1.711 + return retItem; 1.712 +}