| OLD | NEW |
| (Empty) |
| 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 | |
| 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" | |
| 13 | |
| 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 }; | |
| 23 | |
| 24 const SEC_ASN1Template CERT_RDNTemplate[] = { | |
| 25 { SEC_ASN1_SET_OF, | |
| 26 offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) } | |
| 27 }; | |
| 28 | |
| 29 | |
| 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 } | |
| 41 | |
| 42 static void ** | |
| 43 AddToArray(PRArenaPool *arena, void **array, void *element) | |
| 44 { | |
| 45 unsigned count; | |
| 46 void **ap; | |
| 47 | |
| 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 } | |
| 56 | |
| 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 } | |
| 70 | |
| 71 | |
| 72 SECOidTag | |
| 73 CERT_GetAVATag(CERTAVA *ava) | |
| 74 { | |
| 75 SECOidData *oid; | |
| 76 if (!ava->type.data) return (SECOidTag)-1; | |
| 77 | |
| 78 oid = SECOID_FindOID(&ava->type); | |
| 79 | |
| 80 if ( oid ) { | |
| 81 return(oid->offset); | |
| 82 } | |
| 83 return (SECOidTag)-1; | |
| 84 } | |
| 85 | |
| 86 static SECStatus | |
| 87 SetupAVAType(PRArenaPool *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; | |
| 94 | |
| 95 oidrec = SECOID_FindOIDByTag(type); | |
| 96 if (oidrec == NULL) | |
| 97 return SECFailure; | |
| 98 | |
| 99 oid = oidrec->oid.data; | |
| 100 oidLen = oidrec->oid.len; | |
| 101 | |
| 102 maxLen = cert_AVAOidTagToMaxLen(type); | |
| 103 if (maxLen < 0) { | |
| 104 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 105 return SECFailure; | |
| 106 } | |
| 107 | |
| 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 } | |
| 117 | |
| 118 static SECStatus | |
| 119 SetupAVAValue(PRArenaPool *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; | |
| 125 | |
| 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 } | |
| 150 | |
| 151 if (valueLen > maxLen) { | |
| 152 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 153 return SECFailure; | |
| 154 } | |
| 155 | |
| 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 } | |
| 168 | |
| 169 CERTAVA * | |
| 170 CERT_CreateAVAFromRaw(PRArenaPool *pool, const SECItem * OID, | |
| 171 const SECItem * value) | |
| 172 { | |
| 173 CERTAVA *ava; | |
| 174 int rv; | |
| 175 | |
| 176 ava = PORT_ArenaZNew(pool, CERTAVA); | |
| 177 if (ava) { | |
| 178 rv = SECITEM_CopyItem(pool, &ava->type, OID); | |
| 179 if (rv) | |
| 180 return NULL; | |
| 181 | |
| 182 rv = SECITEM_CopyItem(pool, &ava->value, value); | |
| 183 if (rv) | |
| 184 return NULL; | |
| 185 } | |
| 186 return ava; | |
| 187 } | |
| 188 | |
| 189 CERTAVA * | |
| 190 CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, int valueType, | |
| 191 SECItem *value) | |
| 192 { | |
| 193 CERTAVA *ava; | |
| 194 int rv; | |
| 195 unsigned maxLen; | |
| 196 | |
| 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 } | |
| 212 | |
| 213 CERTAVA * | |
| 214 CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value) | |
| 215 { | |
| 216 SECItem item = { siBuffer, NULL, 0 }; | |
| 217 | |
| 218 item.data = (PRUint8 *)value; | |
| 219 item.len = PORT_Strlen(value); | |
| 220 | |
| 221 return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item); | |
| 222 } | |
| 223 | |
| 224 CERTAVA * | |
| 225 CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from) | |
| 226 { | |
| 227 CERTAVA *ava; | |
| 228 int rv; | |
| 229 | |
| 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; | |
| 238 | |
| 239 loser: | |
| 240 return 0; | |
| 241 } | |
| 242 | |
| 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 }; | |
| 249 | |
| 250 | |
| 251 CERTRDN * | |
| 252 CERT_CreateRDN(PRArenaPool *arena, CERTAVA *ava0, ...) | |
| 253 { | |
| 254 CERTAVA *ava; | |
| 255 CERTRDN *rdn; | |
| 256 va_list ap; | |
| 257 unsigned count; | |
| 258 CERTAVA **avap; | |
| 259 | |
| 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 } | |
| 272 | |
| 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 } | |
| 291 | |
| 292 SECStatus | |
| 293 CERT_AddAVA(PRArenaPool *arena, CERTRDN *rdn, CERTAVA *ava) | |
| 294 { | |
| 295 rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava); | |
| 296 return rdn->avas ? SECSuccess : SECFailure; | |
| 297 } | |
| 298 | |
| 299 SECStatus | |
| 300 CERT_CopyRDN(PRArenaPool *arena, CERTRDN *to, CERTRDN *from) | |
| 301 { | |
| 302 CERTAVA **avas, *fava, *tava; | |
| 303 SECStatus rv = SECSuccess; | |
| 304 | |
| 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 } | |
| 325 | |
| 326 /************************************************************************/ | |
| 327 | |
| 328 const SEC_ASN1Template CERT_NameTemplate[] = { | |
| 329 { SEC_ASN1_SEQUENCE_OF, | |
| 330 offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) } | |
| 331 }; | |
| 332 | |
| 333 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_NameTemplate) | |
| 334 | |
| 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 PRArenaPool *arena; | |
| 344 | |
| 345 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 346 if ( !arena ) { | |
| 347 return(0); | |
| 348 } | |
| 349 | |
| 350 name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName)); | |
| 351 if (name) { | |
| 352 name->arena = arena; | |
| 353 | |
| 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 } | |
| 365 | |
| 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 } | |
| 372 | |
| 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 } | |
| 382 | |
| 383 /* null terminate the list */ | |
| 384 *rdnp++ = 0; | |
| 385 } | |
| 386 return name; | |
| 387 | |
| 388 loser: | |
| 389 PORT_FreeArena(arena, PR_FALSE); | |
| 390 return(0); | |
| 391 } | |
| 392 | |
| 393 void | |
| 394 CERT_DestroyName(CERTName *name) | |
| 395 { | |
| 396 if (name) | |
| 397 { | |
| 398 PRArenaPool *arena = name->arena; | |
| 399 name->rdns = NULL; | |
| 400 name->arena = NULL; | |
| 401 if (arena) PORT_FreeArena(arena, PR_FALSE); | |
| 402 } | |
| 403 } | |
| 404 | |
| 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 } | |
| 411 | |
| 412 SECStatus | |
| 413 CERT_CopyName(PRArenaPool *arena, CERTName *to, CERTName *from) | |
| 414 { | |
| 415 CERTRDN **rdns, *frdn, *trdn; | |
| 416 SECStatus rv = SECSuccess; | |
| 417 | |
| 418 if (!to || !from) { | |
| 419 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 420 return SECFailure; | |
| 421 } | |
| 422 | |
| 423 CERT_DestroyName(to); | |
| 424 to->arena = arena; | |
| 425 | |
| 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 } | |
| 449 | |
| 450 /************************************************************************/ | |
| 451 | |
| 452 static void | |
| 453 canonicalize(SECItem * foo) | |
| 454 { | |
| 455 int ch, lastch, len, src, dest; | |
| 456 | |
| 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 } | |
| 463 | |
| 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 } | |
| 484 | |
| 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); | |
| 492 | |
| 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 } | |
| 503 | |
| 504 SECComparison | |
| 505 CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b) | |
| 506 { | |
| 507 SECComparison rv; | |
| 508 | |
| 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 } | |
| 538 | |
| 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; | |
| 546 | |
| 547 aavas = a->avas; | |
| 548 bavas = b->avas; | |
| 549 | |
| 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; | |
| 558 | |
| 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 } | |
| 574 | |
| 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; | |
| 582 | |
| 583 ardns = a->rdns; | |
| 584 brdns = b->rdns; | |
| 585 | |
| 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; | |
| 594 | |
| 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 } | |
| 606 | |
| 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; | |
| 616 | |
| 617 if (!derAVAValue || !derAVAValue->len || !derAVAValue->data) { | |
| 618 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 619 return NULL; | |
| 620 } | |
| 621 | |
| 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 } | |
| 653 | |
| 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 } | |
| 664 | |
| 665 if (convert != conv_none) { | |
| 666 unsigned int utf8ValLen = avaValue.len * 3; | |
| 667 unsigned char *utf8Val = (unsigned char*) | |
| 668 PORT_ArenaZAlloc(newarena, utf8ValLen); | |
| 669 | |
| 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 } | |
| 701 | |
| 702 avaValue.data = utf8Val; | |
| 703 avaValue.len = utf8ValLen; | |
| 704 } | |
| 705 | |
| 706 retItem = SECITEM_DupItem(&avaValue); | |
| 707 PORT_FreeArena(newarena, PR_FALSE); | |
| 708 return retItem; | |
| 709 } | |
| OLD | NEW |