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

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

mercurial