comparison nss/lib/certdb/secname.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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(PLArenaPool *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 PLArenaPool *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 PLArenaPool *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(PLArenaPool *arena, CERTName *to, const 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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)