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