Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1291)

Side by Side Diff: nss/lib/certdb/secname.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/certdb/polcyxtn.c ('k') | nss/lib/certdb/stanpcertdb.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « nss/lib/certdb/polcyxtn.c ('k') | nss/lib/certdb/stanpcertdb.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698