2 * extenTest - verify encoding and decoding of extensions.
5 #include <security_cdsa_utils/cuFileIo.h>
6 #include <clAppUtils/CertBuilderApp.h>
7 #include <utilLib/common.h>
8 #include <utilLib/cspwrap.h>
9 #include <clAppUtils/clutils.h>
10 #include <security_cdsa_utils/cuPrintCert.h>
11 #include <security_cdsa_utils/cuOidParser.h>
16 #include <Security/cssm.h>
17 #include <Security/x509defs.h>
18 #include <Security/oidsattr.h>
19 #include <Security/oidscert.h>
20 #include <Security/certextensions.h>
22 #define KEY_ALG CSSM_ALGID_RSA
23 #define SIG_ALG CSSM_ALGID_SHA1WithRSA
24 #define KEY_SIZE_BITS CSP_RSA_KEY_SIZE_DEFAULT
25 #define SUBJ_KEY_LABEL "subjectKey"
29 static void usage(char **argv
)
31 printf("Usage: %s [options]\n", argv
[0]);
33 printf(" e=extenSpec (default = all)\n");
34 printf(" k keyUsage\n");
35 printf(" b basicConstraints\n");
36 printf(" x extendedKeyUsage\n");
37 printf(" s subjectKeyId\n");
38 printf(" a authorityKeyId\n");
39 printf(" t SubjectAltName\n");
40 printf(" i IssuerAltName\n");
41 printf(" c certPolicies\n");
42 printf(" n netscapeCertType\n");
43 printf(" p CRLDistributionPoints\n");
44 printf(" A AuthorityInfoAccess\n");
45 printf(" S SubjectInfoAccess\n");
46 printf(" q QualifiedCertStatements\n");
47 printf(" w(rite blobs)\n");
48 printf(" f=fileName (default is extension-specific file name)\n");
49 printf(" d(isplay certs)\n");
50 printf(" l=loops (default = %d)\n", LOOPS_DEF
);
51 printf(" p(ause on each loop)\n");
52 printf(" P(ause on each cert)\n");
56 /* dummy RDN - subject and issuer - we aren't testing this */
57 CB_NameOid dummyRdn
[] =
59 { "Apple Computer", &CSSMOID_OrganizationName
},
60 { "Doug Mitchell", &CSSMOID_CommonName
}
62 #define NUM_DUMMY_NAMES (sizeof(dummyRdn) / sizeof(CB_NameOid))
65 * Static components we reuse for each encode/decode.
67 static CSSM_X509_NAME
*dummyName
;
68 static CSSM_X509_TIME
*notBefore
; // UTC-style "not before" time
69 static CSSM_X509_TIME
*notAfter
; // UTC-style "not after" time
70 static CSSM_KEY subjPrivKey
;
71 static CSSM_KEY subjPubKey
;
73 static CSSM_BOOL
randBool()
75 unsigned r
= genRand(1, 0x10000000);
76 return (r
& 0x1) ? CSSM_TRUE
: CSSM_FALSE
;
79 /* Fill a CSSM_DATA with random data. Its referent is allocd with malloc. */
84 data
->Data
= (uint8
*)malloc(maxLen
);
85 simpleGenData(data
, 1, maxLen
);
89 * Various compare tests
99 printf("***Boolean miscompare on %s\n", desc
);
100 /* in case a CSSM_TRUE isn't exactly right... */
106 printf("*** post value is %d expected %d\n",
107 (int)post
, (int)pre
);
113 static int compCssmData(
118 if(appCompareCssmData(&d1
, &d2
)) {
121 printf("CSSM_DATA miscompare on %s\n", desc
);
125 #pragma mark ----- individual extension tests -----
127 #pragma mark --- CE_KeyUsage ---
128 static void kuCreate(void *arg
)
130 CE_KeyUsage
*ku
= (CE_KeyUsage
*)arg
;
132 /* set two random valid bits */
134 *ku
|= 1 << genRand(7, 15);
135 *ku
|= 1 << genRand(7, 15);
138 static unsigned kuCompare(const void *pre
, const void *post
)
140 const CE_KeyUsage
*kuPre
= (CE_KeyUsage
*)pre
;
141 const CE_KeyUsage
*kuPost
= (CE_KeyUsage
*)post
;
142 if(*kuPre
!= *kuPost
) {
143 printf("***Miscompare in CE_KeyUsage\n");
149 #pragma mark --- CE_BasicConstraints ---
150 static void bcCreate(void *arg
)
152 CE_BasicConstraints
*bc
= (CE_BasicConstraints
*)arg
;
154 bc
->pathLenConstraintPresent
= randBool();
155 if(bc
->pathLenConstraintPresent
) {
156 bc
->pathLenConstraint
= genRand(1,10);
160 static unsigned bcCompare(const void *pre
, const void *post
)
162 const CE_BasicConstraints
*bcpre
= (CE_BasicConstraints
*)pre
;
163 const CE_BasicConstraints
*bcpost
= (CE_BasicConstraints
*)post
;
166 rtn
+= compBool(bcpre
->cA
, bcpost
->cA
, "BasicConstraints.cA");
167 rtn
+= compBool(bcpre
->pathLenConstraintPresent
,
168 bcpost
->pathLenConstraintPresent
,
169 "BasicConstraints.pathLenConstraintPresent");
170 if(bcpre
->pathLenConstraint
!= bcpost
->pathLenConstraint
) {
171 printf("BasicConstraints.pathLenConstraint mismatch\n");
177 #pragma mark --- CE_SubjectKeyID ---
178 static void skidCreate(void *arg
)
180 CSSM_DATA_PTR skid
= (CSSM_DATA_PTR
)arg
;
184 static unsigned skidCompare(const void *pre
, const void *post
)
186 CSSM_DATA_PTR spre
= (CSSM_DATA_PTR
)pre
;
187 CSSM_DATA_PTR spost
= (CSSM_DATA_PTR
)post
;
188 return compCssmData(*spre
, *spost
, "SubjectKeyID");
191 static void skidFree(void *arg
)
193 CSSM_DATA_PTR skid
= (CSSM_DATA_PTR
)arg
;
197 #pragma mark --- CE_NetscapeCertType ---
198 static void nctCreate(void *arg
)
200 CE_NetscapeCertType
*nct
= (CE_NetscapeCertType
*)arg
;
202 /* set two random valid bits */
204 *nct
|= 1 << genRand(8, 15);
205 *nct
|= 1 << genRand(8, 15);
208 static unsigned nctCompare(const void *pre
, const void *post
)
210 const CE_NetscapeCertType
*nPre
= (CE_NetscapeCertType
*)pre
;
211 const CE_NetscapeCertType
*nPost
= (CE_NetscapeCertType
*)post
;
212 if(*nPre
!= *nPost
) {
213 printf("***Miscompare in CE_NetscapeCertType\n");
219 #pragma mark --- CE_ExtendedKeyUsage ---
221 /* a static array of meaningless OIDs, use 1.. NUM_SKU_OIDS */
222 CSSM_OID ekuOids
[] = {
225 CSSMOID_HoldInstructionCode
,
226 CSSMOID_InvalidityDate
228 #define NUM_SKU_OIDS 4
230 static void ekuCreate(void *arg
)
232 CE_ExtendedKeyUsage
*eku
= (CE_ExtendedKeyUsage
*)arg
;
233 eku
->numPurposes
= genRand(1, NUM_SKU_OIDS
);
234 eku
->purposes
= ekuOids
;
237 static unsigned ekuCompare(const void *pre
, const void *post
)
239 CE_ExtendedKeyUsage
*ekupre
= (CE_ExtendedKeyUsage
*)pre
;
240 CE_ExtendedKeyUsage
*ekupost
= (CE_ExtendedKeyUsage
*)post
;
242 if(ekupre
->numPurposes
!= ekupost
->numPurposes
) {
243 printf("CE_ExtendedKeyUsage.numPurposes miscompare\n");
247 for(unsigned dex
=0; dex
<ekupre
->numPurposes
; dex
++) {
248 rtn
+= compCssmData(ekupre
->purposes
[dex
],
249 ekupost
->purposes
[dex
], "CE_ExtendedKeyUsage.purposes");
255 #pragma mark --- general purpose X509 name generator ---
257 /* Attr/Value pairs, pick one of NUM_ATTR_STRINGS */
258 static char *attrStrings
[] = {
260 (char *)"anotherName",
261 (char *)"someOtherName"
263 #define NUM_ATTR_STRINGS 3
265 /* A/V type, pick one of NUM_ATTR_TYPES */
266 static CSSM_OID attrTypes
[] = {
269 CSSMOID_OrganizationName
,
272 #define NUM_ATTR_TYPES 4
274 /* A/V tag, pick one of NUM_ATTR_TAGS */
275 static char attrTags
[] = {
276 BER_TAG_PRINTABLE_STRING
,
280 #define NUM_ATTR_TAGS 3
282 static void rdnCreate(
283 CSSM_X509_RDN_PTR rdn
)
285 unsigned numPairs
= genRand(1,4);
286 rdn
->numberOfPairs
= numPairs
;
287 unsigned len
= numPairs
* sizeof(CSSM_X509_TYPE_VALUE_PAIR
);
288 rdn
->AttributeTypeAndValue
=
289 (CSSM_X509_TYPE_VALUE_PAIR_PTR
)malloc(len
);
290 memset(rdn
->AttributeTypeAndValue
, 0, len
);
292 for(unsigned atvDex
=0; atvDex
<numPairs
; atvDex
++) {
293 CSSM_X509_TYPE_VALUE_PAIR
&pair
=
294 rdn
->AttributeTypeAndValue
[atvDex
];
295 unsigned die
= genRand(1, NUM_ATTR_TYPES
);
296 pair
.type
= attrTypes
[die
- 1];
297 die
= genRand(1, NUM_ATTR_STRINGS
);
298 char *str
= attrStrings
[die
- 1];
299 pair
.value
.Data
= (uint8
*)str
;
300 pair
.value
.Length
= strlen(str
);
301 die
= genRand(1, NUM_ATTR_TAGS
);
302 pair
.valueType
= attrTags
[die
- 1];
306 static unsigned rdnCompare(
307 CSSM_X509_RDN_PTR rdn1
,
308 CSSM_X509_RDN_PTR rdn2
)
310 if(rdn1
->numberOfPairs
!= rdn2
->numberOfPairs
) {
311 printf("***Mismatch in numberOfPairs\n");
315 for(unsigned atvDex
=0; atvDex
<rdn1
->numberOfPairs
; atvDex
++) {
316 CSSM_X509_TYPE_VALUE_PAIR
&p1
=
317 rdn1
->AttributeTypeAndValue
[atvDex
];
318 CSSM_X509_TYPE_VALUE_PAIR
&p2
=
319 rdn2
->AttributeTypeAndValue
[atvDex
];
320 if(p1
.valueType
!= p2
.valueType
) {
321 printf("***valueType miscompare\n");
324 if(compCssmData(p1
.type
, p2
.type
, "ATV.type")) {
327 if(compCssmData(p1
.value
, p2
.value
, "ATV.value")) {
335 CSSM_X509_RDN_PTR rdn
)
337 free(rdn
->AttributeTypeAndValue
);
340 static void x509NameCreate(
341 CSSM_X509_NAME_PTR x509Name
)
343 memset(x509Name
, 0, sizeof(*x509Name
));
344 unsigned numRdns
= genRand(1,4);
345 x509Name
->numberOfRDNs
= numRdns
;
346 unsigned len
= numRdns
* sizeof(CSSM_X509_RDN
);
347 x509Name
->RelativeDistinguishedName
= (CSSM_X509_RDN_PTR
)malloc(len
);
348 memset(x509Name
->RelativeDistinguishedName
, 0, len
);
350 for(unsigned rdnDex
=0; rdnDex
<numRdns
; rdnDex
++) {
351 CSSM_X509_RDN
&rdn
= x509Name
->RelativeDistinguishedName
[rdnDex
];
356 static unsigned x509NameCompare(
357 const CSSM_X509_NAME_PTR n1
,
358 const CSSM_X509_NAME_PTR n2
)
360 if(n1
->numberOfRDNs
!= n2
->numberOfRDNs
) {
361 printf("***Mismatch in numberOfRDNs\n");
365 for(unsigned rdnDex
=0; rdnDex
<n1
->numberOfRDNs
; rdnDex
++) {
366 CSSM_X509_RDN
&rdn1
= n1
->RelativeDistinguishedName
[rdnDex
];
367 CSSM_X509_RDN
&rdn2
= n2
->RelativeDistinguishedName
[rdnDex
];
368 rtn
+= rdnCompare(&rdn1
, &rdn2
);
373 static void x509NameFree(
374 CSSM_X509_NAME_PTR n
)
376 for(unsigned rdnDex
=0; rdnDex
<n
->numberOfRDNs
; rdnDex
++) {
377 CSSM_X509_RDN
&rdn
= n
->RelativeDistinguishedName
[rdnDex
];
380 free(n
->RelativeDistinguishedName
);
383 #pragma mark --- general purpose GeneralNames generator ---
385 #define SOME_URL_1 "http://foo.bar.com"
386 #define SOME_URL_2 "http://bar.foo.com"
387 #define SOME_DNS_1 "Some DNS"
388 #define SOME_DNS_2 "Another DNS"
389 unsigned char someIpAdr_1
[] = {208, 161, 124, 209 };
390 unsigned char someIpAdr_2
[] = {10, 0, 61, 5};
392 static void genNameCreate(CE_GeneralName
*name
)
394 unsigned type
= genRand(1, 5);
399 name
->nameType
= GNT_URI
;
400 name
->berEncoded
= CSSM_FALSE
;
401 src
= randBool() ? SOME_URL_1
: SOME_URL_2
;
402 appCopyData(src
, strlen(src
), &name
->name
);
406 name
->nameType
= GNT_RegisteredID
;
407 name
->berEncoded
= CSSM_FALSE
;
408 appCopyData(CSSMOID_SubjectDirectoryAttributes
.Data
,
409 CSSMOID_SubjectDirectoryAttributes
.Length
,
414 name
->nameType
= GNT_DNSName
;
415 name
->berEncoded
= CSSM_FALSE
;
416 src
= randBool() ? SOME_DNS_1
: SOME_DNS_2
;
417 appCopyData(src
, strlen(src
), &name
->name
);
421 name
->nameType
= GNT_IPAddress
;
422 name
->berEncoded
= CSSM_FALSE
;
423 usrc
= randBool() ? someIpAdr_1
: someIpAdr_2
;
424 appCopyData(usrc
, 4, &name
->name
);
429 /* X509_NAME, the hard one */
430 name
->nameType
= GNT_DirectoryName
;
431 name
->berEncoded
= CSSM_FALSE
;
432 appSetupCssmData(&name
->name
, sizeof(CSSM_X509_NAME
));
433 x509NameCreate((CSSM_X509_NAME_PTR
)name
->name
.Data
);
438 static void genNamesCreate(void *arg
)
440 CE_GeneralNames
*names
= (CE_GeneralNames
*)arg
;
441 names
->numNames
= genRand(1, 3);
443 //names->numNames = 1;
444 names
->generalName
= (CE_GeneralName
*)malloc(names
->numNames
*
445 sizeof(CE_GeneralName
));
446 memset(names
->generalName
, 0, names
->numNames
* sizeof(CE_GeneralName
));
448 for(unsigned i
=0; i
<names
->numNames
; i
++) {
449 CE_GeneralName
*name
= &names
->generalName
[i
];
454 static unsigned genNameCompare(
455 CE_GeneralName
*npre
,
456 CE_GeneralName
*npost
)
459 if(npre
->nameType
!= npost
->nameType
) {
460 printf("***CE_GeneralName.nameType miscompare\n");
463 if(compBool(npre
->berEncoded
, npost
->berEncoded
,
464 "CE_GeneralName.berEncoded")) {
468 /* nameType-specific compare */
469 switch(npre
->nameType
) {
471 rtn
+= compCssmData(npre
->name
, npost
->name
,
472 "CE_GeneralName.RFC822Name");
475 rtn
+= compCssmData(npre
->name
, npost
->name
,
476 "CE_GeneralName.DNSName");
479 rtn
+= compCssmData(npre
->name
, npost
->name
,
480 "CE_GeneralName.URI");
483 rtn
+= compCssmData(npre
->name
, npost
->name
,
484 "CE_GeneralName.RFIPAddressC822Name");
486 case GNT_RegisteredID
:
487 rtn
+= compCssmData(npre
->name
, npost
->name
,
488 "CE_GeneralName.RegisteredID");
490 case GNT_DirectoryName
:
491 rtn
+= x509NameCompare((CSSM_X509_NAME_PTR
)npre
->name
.Data
,
492 (CSSM_X509_NAME_PTR
)npost
->name
.Data
);
495 printf("****BRRZAP! genNamesCompare needs work\n");
501 static unsigned genNamesCompare(const void *pre
, const void *post
)
503 const CE_GeneralNames
*gnPre
= (CE_GeneralNames
*)pre
;
504 const CE_GeneralNames
*gnPost
= (CE_GeneralNames
*)post
;
507 if((gnPre
== NULL
) || (gnPost
== NULL
)) {
508 printf("***Bad GenNames pointer\n");
511 if(gnPre
->numNames
!= gnPost
->numNames
) {
512 printf("***CE_GeneralNames.numNames miscompare\n");
515 for(unsigned dex
=0; dex
<gnPre
->numNames
; dex
++) {
516 CE_GeneralName
*npre
= &gnPre
->generalName
[dex
];
517 CE_GeneralName
*npost
= &gnPost
->generalName
[dex
];
518 rtn
+= genNameCompare(npre
, npost
);
524 static void genNameFree(CE_GeneralName
*n
)
526 switch(n
->nameType
) {
527 case GNT_DirectoryName
:
528 x509NameFree((CSSM_X509_NAME_PTR
)n
->name
.Data
);
529 CSSM_FREE(n
->name
.Data
);
532 CSSM_FREE(n
->name
.Data
);
538 static void genNamesFree(void *arg
)
540 const CE_GeneralNames
*gn
= (CE_GeneralNames
*)arg
;
541 for(unsigned dex
=0; dex
<gn
->numNames
; dex
++) {
542 CE_GeneralName
*n
= (CE_GeneralName
*)&gn
->generalName
[dex
];
545 free(gn
->generalName
);
548 #pragma mark --- CE_CRLDistPointsSyntax ---
549 static void cdpCreate(void *arg
)
551 CE_CRLDistPointsSyntax
*cdp
= (CE_CRLDistPointsSyntax
*)arg
;
552 //cdp->numDistPoints = genRand(1,3);
554 cdp
->numDistPoints
= 1;
555 unsigned len
= sizeof(CE_CRLDistributionPoint
) * cdp
->numDistPoints
;
556 cdp
->distPoints
= (CE_CRLDistributionPoint
*)malloc(len
);
557 memset(cdp
->distPoints
, 0, len
);
559 for(unsigned dex
=0; dex
<cdp
->numDistPoints
; dex
++) {
560 CE_CRLDistributionPoint
*pt
= &cdp
->distPoints
[dex
];
562 /* all fields optional */
564 CE_DistributionPointName
*dpn
= pt
->distPointName
=
565 (CE_DistributionPointName
*)malloc(
566 sizeof(CE_DistributionPointName
));
567 memset(dpn
, 0, sizeof(CE_DistributionPointName
));
569 /* CE_DistributionPointName has two flavors */
571 dpn
->nameType
= CE_CDNT_FullName
;
572 dpn
->dpn
.fullName
= (CE_GeneralNames
*)malloc(
573 sizeof(CE_GeneralNames
));
574 memset(dpn
->dpn
.fullName
, 0, sizeof(CE_GeneralNames
));
575 genNamesCreate(dpn
->dpn
.fullName
);
578 dpn
->nameType
= CE_CDNT_NameRelativeToCrlIssuer
;
579 dpn
->dpn
.rdn
= (CSSM_X509_RDN_PTR
)malloc(
580 sizeof(CSSM_X509_RDN
));
581 memset(dpn
->dpn
.rdn
, 0, sizeof(CSSM_X509_RDN
));
582 rdnCreate(dpn
->dpn
.rdn
);
584 } /* creating CE_DistributionPointName */
586 pt
->reasonsPresent
= randBool();
587 if(pt
->reasonsPresent
) {
588 CE_CrlDistReasonFlags
*cdr
= &pt
->reasons
;
589 /* set two random valid bits */
591 *cdr
|= 1 << genRand(0,7);
592 *cdr
|= 1 << genRand(0,7);
595 /* make sure at least one present */
596 if((!pt
->distPointName
&& !pt
->reasonsPresent
) || randBool()) {
597 pt
->crlIssuer
= (CE_GeneralNames
*)malloc(sizeof(CE_GeneralNames
));
598 memset(pt
->crlIssuer
, 0, sizeof(CE_GeneralNames
));
599 genNamesCreate(pt
->crlIssuer
);
604 static unsigned cdpCompare(const void *pre
, const void *post
)
606 CE_CRLDistPointsSyntax
*cpre
= (CE_CRLDistPointsSyntax
*)pre
;
607 CE_CRLDistPointsSyntax
*cpost
= (CE_CRLDistPointsSyntax
*)post
;
609 if(cpre
->numDistPoints
!= cpost
->numDistPoints
) {
610 printf("***CE_CRLDistPointsSyntax.numDistPoints miscompare\n");
614 for(unsigned dex
=0; dex
<cpre
->numDistPoints
; dex
++) {
615 CE_CRLDistributionPoint
*ptpre
= &cpre
->distPoints
[dex
];
616 CE_CRLDistributionPoint
*ptpost
= &cpost
->distPoints
[dex
];
618 if(ptpre
->distPointName
) {
619 if(ptpost
->distPointName
== NULL
) {
620 printf("***NULL distPointName post decode\n");
624 CE_DistributionPointName
*dpnpre
= ptpre
->distPointName
;
625 CE_DistributionPointName
*dpnpost
= ptpost
->distPointName
;
626 if(dpnpre
->nameType
!= dpnpost
->nameType
) {
627 printf("***CE_DistributionPointName.nameType miscompare\n");
631 if(dpnpre
->nameType
== CE_CDNT_FullName
) {
632 rtn
+= genNamesCompare(dpnpre
->dpn
.fullName
, dpnpost
->dpn
.fullName
);
635 rtn
+= rdnCompare(dpnpre
->dpn
.rdn
, dpnpost
->dpn
.rdn
);
639 else if(ptpost
->distPointName
!= NULL
) {
640 printf("***NON NULL distPointName post decode\n");
645 if(ptpre
->reasons
!= ptpost
->reasons
) {
646 printf("***CE_CRLDistributionPoint.reasons miscompare\n");
650 if(ptpre
->crlIssuer
) {
651 if(ptpost
->crlIssuer
== NULL
) {
652 printf("***NULL crlIssuer post decode\n");
656 CE_GeneralNames
*gnpre
= ptpre
->crlIssuer
;
657 CE_GeneralNames
*gnpost
= ptpost
->crlIssuer
;
658 rtn
+= genNamesCompare(gnpre
, gnpost
);
660 else if(ptpost
->crlIssuer
!= NULL
) {
661 printf("***NON NULL crlIssuer post decode\n");
668 static void cdpFree(void *arg
)
670 CE_CRLDistPointsSyntax
*cdp
= (CE_CRLDistPointsSyntax
*)arg
;
671 for(unsigned dex
=0; dex
<cdp
->numDistPoints
; dex
++) {
672 CE_CRLDistributionPoint
*pt
= &cdp
->distPoints
[dex
];
673 if(pt
->distPointName
) {
674 CE_DistributionPointName
*dpn
= pt
->distPointName
;
675 if(dpn
->nameType
== CE_CDNT_FullName
) {
676 genNamesFree(dpn
->dpn
.fullName
);
677 free(dpn
->dpn
.fullName
);
680 rdnFree(dpn
->dpn
.rdn
);
687 genNamesFree(pt
->crlIssuer
);
691 free(cdp
->distPoints
);
694 #pragma mark --- CE_AuthorityKeyID ---
695 static void authKeyIdCreate(void *arg
)
697 CE_AuthorityKeyID
*akid
= (CE_AuthorityKeyID
*)arg
;
699 /* all three fields optional */
701 akid
->keyIdentifierPresent
= randBool();
702 if(akid
->keyIdentifierPresent
) {
703 randData(&akid
->keyIdentifier
, 16);
706 akid
->generalNamesPresent
= randBool();
707 if(akid
->generalNamesPresent
) {
709 (CE_GeneralNames
*)malloc(sizeof(CE_GeneralNames
));
710 memset(akid
->generalNames
, 0, sizeof(CE_GeneralNames
));
711 genNamesCreate(akid
->generalNames
);
714 if(!akid
->keyIdentifierPresent
& !akid
->generalNamesPresent
) {
715 /* force at least one to be present */
716 akid
->serialNumberPresent
= CSSM_TRUE
;
719 akid
->serialNumberPresent
= randBool();
721 if(akid
->serialNumberPresent
) {
722 randData(&akid
->serialNumber
, 16);
727 static unsigned authKeyIdCompare(const void *pre
, const void *post
)
729 CE_AuthorityKeyID
*akpre
= (CE_AuthorityKeyID
*)pre
;
730 CE_AuthorityKeyID
*akpost
= (CE_AuthorityKeyID
*)post
;
733 if(compBool(akpre
->keyIdentifierPresent
, akpost
->keyIdentifierPresent
,
734 "CE_AuthorityKeyID.keyIdentifierPresent")) {
737 else if(akpre
->keyIdentifierPresent
) {
738 rtn
+= compCssmData(akpre
->keyIdentifier
,
739 akpost
->keyIdentifier
, "CE_AuthorityKeyID.keyIdentifier");
742 if(compBool(akpre
->generalNamesPresent
, akpost
->generalNamesPresent
,
743 "CE_AuthorityKeyID.generalNamesPresent")) {
746 else if(akpre
->generalNamesPresent
) {
747 rtn
+= genNamesCompare(akpre
->generalNames
,
748 akpost
->generalNames
);
751 if(compBool(akpre
->serialNumberPresent
, akpost
->serialNumberPresent
,
752 "CE_AuthorityKeyID.serialNumberPresent")) {
755 else if(akpre
->serialNumberPresent
) {
756 rtn
+= compCssmData(akpre
->serialNumber
,
757 akpost
->serialNumber
, "CE_AuthorityKeyID.serialNumber");
762 static void authKeyIdFree(void *arg
)
764 CE_AuthorityKeyID
*akid
= (CE_AuthorityKeyID
*)arg
;
766 if(akid
->keyIdentifier
.Data
) {
767 free(akid
->keyIdentifier
.Data
);
769 if(akid
->generalNames
) {
770 genNamesFree(akid
->generalNames
); // genNamesCreate mallocd
771 free(akid
->generalNames
); // we mallocd
773 if(akid
->serialNumber
.Data
) {
774 free(akid
->serialNumber
.Data
);
778 #pragma mark --- CE_CertPolicies ---
780 /* random OIDs, pick 1..NUM_CP_OIDS */
781 static CSSM_OID cpOids
[] =
783 CSSMOID_EmailAddress
,
784 CSSMOID_UnstructuredName
,
786 CSSMOID_MessageDigest
788 #define NUM_CP_OIDS 4
790 /* CPS strings, pick one of NUM_CPS_STR */
791 static char *someCPSs
[] =
793 (char *)"http://www.apple.com",
794 (char *)"https://cdnow.com",
795 (char *)"ftp:backwards.com"
797 #define NUM_CPS_STR 3
799 /* make these looks like real sequences */
800 static uint8 someUnotice
[] = {0x30, 0x03, BER_TAG_BOOLEAN
, 1, 0xff};
801 static uint8 someOtherData
[] = {0x30, 0x02, BER_TAG_NULL
, 0};
803 static void cpCreate(void *arg
)
805 CE_CertPolicies
*cp
= (CE_CertPolicies
*)arg
;
806 cp
->numPolicies
= genRand(1,3);
807 //cp->numPolicies = 1;
808 unsigned len
= sizeof(CE_PolicyInformation
) * cp
->numPolicies
;
809 cp
->policies
= (CE_PolicyInformation
*)malloc(len
);
810 memset(cp
->policies
, 0, len
);
812 for(unsigned polDex
=0; polDex
<cp
->numPolicies
; polDex
++) {
813 CE_PolicyInformation
*pi
= &cp
->policies
[polDex
];
814 unsigned die
= genRand(1, NUM_CP_OIDS
);
815 pi
->certPolicyId
= cpOids
[die
- 1];
816 unsigned numQual
= genRand(1,3);
817 pi
->numPolicyQualifiers
= numQual
;
818 len
= sizeof(CE_PolicyQualifierInfo
) * numQual
;
819 pi
->policyQualifiers
= (CE_PolicyQualifierInfo
*)
821 memset(pi
->policyQualifiers
, 0, len
);
822 for(unsigned cpiDex
=0; cpiDex
<numQual
; cpiDex
++) {
823 CE_PolicyQualifierInfo
*qi
=
824 &pi
->policyQualifiers
[cpiDex
];
826 qi
->policyQualifierId
= CSSMOID_QT_CPS
;
827 die
= genRand(1, NUM_CPS_STR
);
828 qi
->qualifier
.Data
= (uint8
*)someCPSs
[die
- 1];
829 qi
->qualifier
.Length
= strlen((char *)qi
->qualifier
.Data
);
832 qi
->policyQualifierId
= CSSMOID_QT_UNOTICE
;
834 qi
->qualifier
.Data
= someUnotice
;
835 qi
->qualifier
.Length
= 5;
838 qi
->qualifier
.Data
= someOtherData
;
839 qi
->qualifier
.Length
= 4;
846 static unsigned cpCompare(const void *pre
, const void *post
)
848 CE_CertPolicies
*cppre
= (CE_CertPolicies
*)pre
;
849 CE_CertPolicies
*cppost
= (CE_CertPolicies
*)post
;
851 if(cppre
->numPolicies
!= cppost
->numPolicies
) {
852 printf("CE_CertPolicies.numPolicies mismatch\n");
856 for(unsigned polDex
=0; polDex
<cppre
->numPolicies
; polDex
++) {
857 CE_PolicyInformation
*pipre
= &cppre
->policies
[polDex
];
858 CE_PolicyInformation
*pipost
= &cppost
->policies
[polDex
];
859 rtn
+= compCssmData(pipre
->certPolicyId
, pipost
->certPolicyId
,
860 "CE_PolicyInformation.certPolicyId");
861 if(pipre
->numPolicyQualifiers
!= pipost
->numPolicyQualifiers
) {
862 printf("CE_PolicyInformation.CE_PolicyInformation mismatch\n");
867 for(unsigned qiDex
=0; qiDex
<pipre
->numPolicyQualifiers
; qiDex
++) {
868 CE_PolicyQualifierInfo
*qipre
= &pipre
->policyQualifiers
[qiDex
];
869 CE_PolicyQualifierInfo
*qipost
= &pipost
->policyQualifiers
[qiDex
];
870 rtn
+= compCssmData(qipre
->policyQualifierId
,
871 qipost
->policyQualifierId
,
872 "CE_PolicyQualifierInfo.policyQualifierId");
873 rtn
+= compCssmData(qipre
->qualifier
,
875 "CE_PolicyQualifierInfo.qualifier");
881 static void cpFree(void *arg
)
883 CE_CertPolicies
*cp
= (CE_CertPolicies
*)arg
;
884 for(unsigned polDex
=0; polDex
<cp
->numPolicies
; polDex
++) {
885 CE_PolicyInformation
*pi
= &cp
->policies
[polDex
];
886 free(pi
->policyQualifiers
);
891 #pragma mark --- CE_AuthorityInfoAccess ---
893 /* random OIDs, pick 1..NUM_AI_OIDS */
894 static CSSM_OID aiOids
[] =
897 CSSMOID_AD_CA_ISSUERS
,
898 CSSMOID_AD_TIME_STAMPING
,
899 CSSMOID_AD_CA_REPOSITORY
901 #define NUM_AI_OIDS 4
903 static void aiaCreate(void *arg
)
905 CE_AuthorityInfoAccess
*aia
= (CE_AuthorityInfoAccess
*)arg
;
906 aia
->numAccessDescriptions
= genRand(1,3);
907 unsigned len
= aia
->numAccessDescriptions
* sizeof(CE_AccessDescription
);
908 aia
->accessDescriptions
= (CE_AccessDescription
*)malloc(len
);
909 memset(aia
->accessDescriptions
, 0, len
);
911 for(unsigned dex
=0; dex
<aia
->numAccessDescriptions
; dex
++) {
912 CE_AccessDescription
*ad
= &aia
->accessDescriptions
[dex
];
913 int die
= genRand(1, NUM_AI_OIDS
);
914 ad
->accessMethod
= aiOids
[die
- 1];
915 genNameCreate(&ad
->accessLocation
);
919 static unsigned aiaCompare(const void *pre
, const void *post
)
921 CE_AuthorityInfoAccess
*apre
= (CE_AuthorityInfoAccess
*)pre
;
922 CE_AuthorityInfoAccess
*apost
= (CE_AuthorityInfoAccess
*)post
;
925 if(apre
->numAccessDescriptions
!= apost
->numAccessDescriptions
) {
926 printf("***CE_AuthorityInfoAccess.numAccessDescriptions miscompare\n");
929 for(unsigned dex
=0; dex
<apre
->numAccessDescriptions
; dex
++) {
930 CE_AccessDescription
*adPre
= &apre
->accessDescriptions
[dex
];
931 CE_AccessDescription
*adPost
= &apost
->accessDescriptions
[dex
];
932 if(compCssmData(adPre
->accessMethod
, adPost
->accessMethod
,
933 "CE_AccessDescription.accessMethod")) {
936 rtn
+= genNameCompare(&adPre
->accessLocation
, &adPost
->accessLocation
);
941 static void aiaFree(void *arg
)
943 CE_AuthorityInfoAccess
*aia
= (CE_AuthorityInfoAccess
*)arg
;
944 for(unsigned dex
=0; dex
<aia
->numAccessDescriptions
; dex
++) {
945 CE_AccessDescription
*ad
= &aia
->accessDescriptions
[dex
];
946 genNameFree(&ad
->accessLocation
);
948 free(aia
->accessDescriptions
);
951 #pragma mark --- CE_QC_Statements ---
953 /* a static array of CE_QC_Statement.statementId */
954 static const CSSM_OID qcsOids
[] = {
955 CSSMOID_OID_QCS_SYNTAX_V1
,
956 CSSMOID_OID_QCS_SYNTAX_V2
,
957 CSSMOID_ETSI_QCS_QC_COMPLIANCE
,
959 #define NUM_QCS_OIDS 3
960 #define WHICH_QCS_V2 1
962 static void qcsCreate(void *arg
)
964 CE_QC_Statements
*qcss
= (CE_QC_Statements
*)arg
;
965 //unsigned numQcs = genRand(1,3);
967 qcss
->numQCStatements
= numQcs
;
968 qcss
->qcStatements
= (CE_QC_Statement
*)malloc(numQcs
* sizeof(CE_QC_Statement
));
969 memset(qcss
->qcStatements
, 0, numQcs
* sizeof(CE_QC_Statement
));
971 for(unsigned dex
=0; dex
<numQcs
; dex
++) {
972 CE_QC_Statement
*qcs
= &qcss
->qcStatements
[dex
];
973 unsigned whichOid
= genRand(0, NUM_QCS_OIDS
-1);
974 qcs
->statementId
= qcsOids
[whichOid
];
976 /* three legal combos of (semanticsInfo, otherInfo), constrained by whichOid */
977 unsigned coin
= genRand(1, 2);
985 * CSSMOID_OID_QCS_SYNTAX_V2 --> semanticsInfo
986 * other --> otherInfo
988 if(whichOid
== WHICH_QCS_V2
) {
989 CE_SemanticsInformation
*si
= (CE_SemanticsInformation
*)malloc(
990 sizeof(CE_SemanticsInformation
));
991 qcs
->semanticsInfo
= si
;
992 memset(si
, 0, sizeof(CE_SemanticsInformation
));
994 /* flip a coin; heads --> semanticsIdentifier */
995 coin
= genRand(1, 2);
997 si
->semanticsIdentifier
= (CSSM_OID
*)malloc(sizeof(CSSM_OID
));
998 *si
->semanticsIdentifier
= qcsOids
[0];
1001 /* flip a coin; heads --> nameRegistrationAuthorities */
1002 /* also gen this one if semanticsInfo is empty */
1003 coin
= genRand(1, 2);
1004 if((coin
== 2) || (si
->semanticsIdentifier
== NULL
)) {
1005 si
->nameRegistrationAuthorities
= (CE_NameRegistrationAuthorities
*)
1006 malloc(sizeof(CE_NameRegistrationAuthorities
));
1007 genNamesCreate(si
->nameRegistrationAuthorities
);
1011 /* ASN_ANY - just take an encoded NULL */
1012 CSSM_DATA
*otherInfo
= (CSSM_DATA
*)malloc(sizeof(CSSM_DATA
));
1013 otherInfo
->Data
= (uint8
*)malloc(2);
1014 otherInfo
->Data
[0] = 5;
1015 otherInfo
->Data
[1] = 0;
1016 otherInfo
->Length
= 2;
1017 qcs
->otherInfo
= otherInfo
;
1025 static unsigned qcsCompare(const void *pre
, const void *post
)
1027 CE_QC_Statements
*qpre
= (CE_QC_Statements
*)pre
;
1028 CE_QC_Statements
*qpost
= (CE_QC_Statements
*)post
;
1029 uint32 numQcs
= qpre
->numQCStatements
;
1030 if(numQcs
!= qpost
->numQCStatements
) {
1031 printf("***numQCStatements miscompare\n");
1036 for(unsigned dex
=0; dex
<numQcs
; dex
++) {
1037 CE_QC_Statement
*qcsPre
= &qpre
->qcStatements
[dex
];
1038 CE_QC_Statement
*qcsPost
= &qpost
->qcStatements
[dex
];
1039 if(compCssmData(qcsPre
->statementId
, qcsPost
->statementId
,
1040 "CE_QC_Statement.statementId")) {
1043 if(qcsPre
->semanticsInfo
) {
1044 if(qcsPost
->semanticsInfo
== NULL
) {
1045 printf("***semanticsInfo in pre but not in post\n");
1049 CE_SemanticsInformation
*siPre
= qcsPre
->semanticsInfo
;
1050 CE_SemanticsInformation
*siPost
= qcsPost
->semanticsInfo
;
1051 if((siPre
->semanticsIdentifier
== NULL
) != (siPost
->semanticsIdentifier
== NULL
)) {
1052 printf("***mismatch in presence of semanticsIdentifier\n");
1055 else if(siPre
->semanticsIdentifier
) {
1056 if(compCssmData(*siPre
->semanticsIdentifier
, *siPost
->semanticsIdentifier
,
1057 "CE_SemanticsInformation.semanticsIdentifier")) {
1061 if((siPre
->nameRegistrationAuthorities
== NULL
) !=
1062 (siPost
->nameRegistrationAuthorities
== NULL
)) {
1063 printf("***mismatch in presence of nameRegistrationAuthorities\n");
1066 else if(siPre
->nameRegistrationAuthorities
) {
1067 rtn
+= genNamesCompare(siPre
->nameRegistrationAuthorities
,
1068 siPost
->nameRegistrationAuthorities
);
1072 else if(qcsPost
->semanticsInfo
!= NULL
) {
1073 printf("***semanticsInfo in post but not in pre\n");
1076 if(qcsPre
->otherInfo
) {
1077 if(qcsPost
->otherInfo
== NULL
) {
1078 printf("***otherInfo in pre but not in post\n");
1082 if(compCssmData(*qcsPre
->otherInfo
, *qcsPre
->otherInfo
,
1083 "CE_QC_Statement.otherInfo")) {
1088 else if(qcsPost
->otherInfo
!= NULL
) {
1089 printf("***otherInfo in post but not in pre\n");
1096 static void qcsFree(void *arg
)
1098 CE_QC_Statements
*qcss
= (CE_QC_Statements
*)arg
;
1099 uint32 numQcs
= qcss
->numQCStatements
;
1100 for(unsigned dex
=0; dex
<numQcs
; dex
++) {
1101 CE_QC_Statement
*qcs
= &qcss
->qcStatements
[dex
];
1102 if(qcs
->semanticsInfo
) {
1103 CE_SemanticsInformation
*si
= qcs
->semanticsInfo
;
1104 if(si
->semanticsIdentifier
) {
1105 free(si
->semanticsIdentifier
);
1107 if(si
->nameRegistrationAuthorities
) {
1108 genNamesFree(si
->nameRegistrationAuthorities
);
1109 free(si
->nameRegistrationAuthorities
);
1111 free(qcs
->semanticsInfo
);
1113 if(qcs
->otherInfo
) {
1114 free(qcs
->otherInfo
->Data
);
1115 free(qcs
->otherInfo
);
1118 free(qcss
->qcStatements
);
1121 #pragma mark --- test definitions ---
1124 * Define one extension test.
1128 * Cook up this extension with random, reasonable values.
1129 * Incoming pointer refers to extension-specific C struct, mallocd
1130 * and zeroed by main test routine.
1132 typedef void (*extenCreateFcn
)(void *arg
);
1135 * Compare two instances of this extension. Return number of
1138 typedef unsigned (*extenCompareFcn
)(
1139 const void *preEncode
,
1140 const void *postEncode
);
1143 * Free struct components mallocd in extenCreateFcn. Do not free
1146 typedef void (*extenFreeFcn
)(void *arg
);
1149 /* three extension-specific functions */
1150 extenCreateFcn createFcn
;
1151 extenCompareFcn compareFcn
;
1152 extenFreeFcn freeFcn
;
1154 /* size of C struct passed to all three functions */
1157 /* the OID for this extension */
1160 /* description for error logging and blob writing */
1161 const char *extenDescr
;
1163 /* command-line letter for this one */
1168 /* empty freeFcn means no extension-specific resources to free */
1169 #define NO_FREE NULL
1171 static ExtenTest extenTests
[] = {
1172 { kuCreate
, kuCompare
, NO_FREE
,
1173 sizeof(CE_KeyUsage
), CSSMOID_KeyUsage
,
1175 { bcCreate
, bcCompare
, NO_FREE
,
1176 sizeof(CE_BasicConstraints
), CSSMOID_BasicConstraints
,
1177 "BasicConstraints", 'b' },
1178 { ekuCreate
, ekuCompare
, NO_FREE
,
1179 sizeof(CE_ExtendedKeyUsage
), CSSMOID_ExtendedKeyUsage
,
1180 "ExtendedKeyUsage", 'x' },
1181 { skidCreate
, skidCompare
, skidFree
,
1182 sizeof(CSSM_DATA
), CSSMOID_SubjectKeyIdentifier
,
1183 "SubjectKeyID", 's' },
1184 { authKeyIdCreate
, authKeyIdCompare
, authKeyIdFree
,
1185 sizeof(CE_AuthorityKeyID
), CSSMOID_AuthorityKeyIdentifier
,
1186 "AuthorityKeyID", 'a' },
1187 { genNamesCreate
, genNamesCompare
, genNamesFree
,
1188 sizeof(CE_GeneralNames
), CSSMOID_SubjectAltName
,
1189 "SubjectAltName", 't' },
1190 { genNamesCreate
, genNamesCompare
, genNamesFree
,
1191 sizeof(CE_GeneralNames
), CSSMOID_IssuerAltName
,
1192 "IssuerAltName", 'i' },
1193 { nctCreate
, nctCompare
, NO_FREE
,
1194 sizeof(CE_NetscapeCertType
), CSSMOID_NetscapeCertType
,
1195 "NetscapeCertType", 'n' },
1196 { cdpCreate
, cdpCompare
, cdpFree
,
1197 sizeof(CE_CRLDistPointsSyntax
), CSSMOID_CrlDistributionPoints
,
1198 "CRLDistPoints", 'p' },
1199 { cpCreate
, cpCompare
, cpFree
,
1200 sizeof(CE_CertPolicies
), CSSMOID_CertificatePolicies
,
1201 "CertPolicies", 'c' },
1202 { aiaCreate
, aiaCompare
, aiaFree
,
1203 sizeof(CE_AuthorityInfoAccess
), CSSMOID_AuthorityInfoAccess
,
1204 "AuthorityInfoAccess", 'A' },
1205 { aiaCreate
, aiaCompare
, aiaFree
,
1206 sizeof(CE_AuthorityInfoAccess
), CSSMOID_SubjectInfoAccess
,
1207 "SubjectInfoAccess", 'S' },
1208 { qcsCreate
, qcsCompare
, qcsFree
,
1209 sizeof(CE_QC_Statements
), CSSMOID_QC_Statements
,
1210 "QualifiedCertStatements", 'q' },
1213 #define NUM_EXTEN_TESTS (sizeof(extenTests) / sizeof(ExtenTest))
1215 static void printExten(
1216 CSSM_X509_EXTENSION
&extn
,
1221 field
.FieldOid
= extn
.extnId
;
1222 field
.FieldValue
.Data
= (uint8
*)&extn
;
1223 field
.FieldValue
.Length
= sizeof(CSSM_X509_EXTENSION
);
1224 printf("=== %s:\n", preEncode
? "PRE-ENCODE" : "POST-DECODE" );
1225 printCertField(field
, parser
, CSSM_TRUE
);
1229 CSSM_CL_HANDLE clHand
,
1230 CSSM_CSP_HANDLE cspHand
,
1231 ExtenTest
&extenTest
,
1233 const char *constFileName
, // all blobs to this file if non-NULL
1238 * 1. Cook up a random and reasonable instance of the C struct
1239 * associated with this extension.
1241 void *preEncode
= CSSM_MALLOC(extenTest
.extenSize
);
1242 memset(preEncode
, 0, extenTest
.extenSize
);
1243 extenTest
.createFcn(preEncode
);
1246 * Cook up the associated CSSM_X509_EXTENSION.
1248 CSSM_X509_EXTENSION extnPre
;
1250 extnPre
.extnId
= extenTest
.extenOid
;
1251 extnPre
.critical
= randBool();
1252 extnPre
.format
= CSSM_X509_DATAFORMAT_PARSED
;
1253 extnPre
.value
.parsedValue
= preEncode
;
1254 extnPre
.BERvalue
.Data
= NULL
;
1255 extnPre
.BERvalue
.Length
= 0;
1257 /* encode the extension in a TBSCert */
1258 CSSM_DATA_PTR rawCert
= CB_MakeCertTemplate(clHand
,
1259 0x12345678, // serial number
1266 NULL
, // subjUniqueId
1267 NULL
, // issuerUniqueId
1268 &extnPre
, // extensions
1269 1); // numExtensions
1270 if(rawCert
== NULL
) {
1271 printf("Error generating template; aborting.\n");
1272 /* show what we tried to encode */
1273 printExten(extnPre
, true, parser
);
1278 CSSM_DATA signedCert
= {0, NULL
};
1279 CSSM_CC_HANDLE sigHand
;
1280 CSSM_RETURN crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
1282 NULL
, // no passphrase for now
1286 printError("CreateSignatureContext", crtn
);
1290 crtn
= CSSM_CL_CertSign(clHand
,
1292 rawCert
, // CertToBeSigned
1293 NULL
, // SignScope per spec
1294 0, // ScopeSize per spec
1297 printError("CSSM_CL_CertSign", crtn
);
1298 /* show what we tried to encode */
1299 printExten(extnPre
, true, parser
);
1302 CSSM_DeleteContext(sigHand
);
1307 strcpy(fileName
, constFileName
);
1310 sprintf(fileName
, "%scert.der", extenTest
.extenDescr
);
1312 writeFile(fileName
, signedCert
.Data
, signedCert
.Length
);
1313 printf("...wrote %lu bytes to %s\n", signedCert
.Length
, fileName
);
1316 /* snag the same extension from the encoded cert */
1317 CSSM_DATA_PTR postField
;
1318 CSSM_HANDLE resultHand
;
1321 crtn
= CSSM_CL_CertGetFirstFieldValue(clHand
,
1323 &extenTest
.extenOid
,
1328 printf("****Extension field not found on decode for %s\n",
1329 extenTest
.extenDescr
);
1330 printError("CSSM_CL_CertGetFirstFieldValue", crtn
);
1332 /* show what we tried to encode and decode */
1333 printExten(extnPre
, true, parser
);
1337 if(numFields
!= 1) {
1338 printf("****GetFirstFieldValue: expect 1 value, got %u\n",
1339 (unsigned)numFields
);
1342 CSSM_CL_CertAbortQuery(clHand
, resultHand
);
1344 /* verify the fields we generated */
1345 CSSM_X509_EXTENSION
*extnPost
= (CSSM_X509_EXTENSION
*)postField
->Data
;
1346 if((extnPost
== NULL
) ||
1347 (postField
->Length
!= sizeof(CSSM_X509_EXTENSION
))) {
1348 printf("***Malformed CSSM_X509_EXTENSION (1) after decode\n");
1352 rtn
+= compBool(extnPre
.critical
, extnPost
->critical
,
1353 "CSSM_X509_EXTENSION.critical");
1354 rtn
+= compCssmData(extnPre
.extnId
, extnPost
->extnId
,
1355 "CSSM_X509_EXTENSION.extnId");
1357 if(extnPost
->format
!= CSSM_X509_DATAFORMAT_PARSED
) {
1358 printf("***Expected CSSM_X509_DATAFORMAT_PARSED (%x(x), got %x(x)\n",
1359 CSSM_X509_DATAFORMAT_PARSED
, extnPost
->format
);
1361 if(extnPost
->value
.parsedValue
== NULL
) {
1362 printf("***no parsedValue pointer!\n");
1366 /* down to extension-specific compare */
1367 rtn
+= extenTest
.compareFcn(preEncode
, extnPost
->value
.parsedValue
);
1370 /* print preencode only on error */
1371 printExten(extnPre
, true, parser
);
1373 if(displayExtens
|| rtn
) {
1374 printExten(*extnPost
, false, parser
);
1377 /* free the allocated data */
1378 if(extenTest
.freeFcn
) {
1379 extenTest
.freeFcn(preEncode
);
1381 CSSM_CL_FreeFieldValue(clHand
, &extenTest
.extenOid
, postField
);
1382 CSSM_FREE(rawCert
->Data
);
1384 CSSM_FREE(signedCert
.Data
);
1385 CSSM_FREE(preEncode
);
1389 static void doPause(bool pause
)
1395 printf("CR to continue ");
1399 int main(int argc
, char **argv
)
1401 CSSM_CL_HANDLE clHand
;
1402 CSSM_CSP_HANDLE cspHand
;
1410 /* user-specificied params */
1411 unsigned minExtenNum
= 0;
1412 unsigned maxExtenNum
= NUM_EXTEN_TESTS
-1;
1413 bool writeBlobs
= false;
1414 bool displayExtens
= false;
1416 unsigned loops
= LOOPS_DEF
;
1417 bool pauseLoop
= false;
1418 bool pauseCert
= false;
1419 const char *constFileName
= NULL
;
1421 for(arg
=1; arg
<argc
; arg
++) {
1428 displayExtens
= true;
1440 loops
= atoi(&argp
[2]);
1443 constFileName
= &argp
[2];
1446 if(argp
[1] != '=') {
1449 /* scan thru test array looking for epecified extension */
1450 for(i
=0; i
<NUM_EXTEN_TESTS
; i
++) {
1451 if(extenTests
[i
].extenLetter
== argp
[2]) {
1452 minExtenNum
= maxExtenNum
= i
;
1456 if(i
== NUM_EXTEN_TESTS
) {
1467 clHand
= clStartup();
1471 cspHand
= cspStartup();
1476 printf("Starting extenTest; args: ");
1477 for(i
=1; i
<(unsigned)argc
; i
++) {
1478 printf("%s ", argv
[i
]);
1482 /* one common key pair - we're definitely not testing this */
1483 crtn
= cspGenKeyPair(cspHand
,
1486 strlen(SUBJ_KEY_LABEL
),
1489 CSSM_FALSE
, // pubIsRef - should work both ways, but not yet
1491 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
1493 CSSM_TRUE
, // privIsRef - doesn't matter
1495 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
1501 /* common issuer/subject - not testing this */
1502 dummyName
= CB_BuildX509Name(dummyRdn
, NUM_DUMMY_NAMES
);
1503 if(dummyName
== NULL
) {
1504 printf("CB_BuildX509Name failure");
1508 /* not before/after in generalized time format */
1509 notBefore
= CB_BuildX509Time(0);
1510 notAfter
= CB_BuildX509Time(10000);
1512 for(unsigned loop
=0; loop
<loops
; loop
++) {
1514 printf("...loop %u\n", loop
);
1516 for(unsigned extenDex
=minExtenNum
; extenDex
<=maxExtenNum
; extenDex
++) {
1517 rtn
= doTest(clHand
, cspHand
, extenTests
[extenDex
],
1518 writeBlobs
, constFileName
, displayExtens
, parser
);
1531 printf("***%s FAILED\n", argv
[0]);
1534 printf("...%s passed\n", argv
[0]);
1539 CB_FreeX509Name(dummyName
);
1540 CB_FreeX509Time(notBefore
);
1541 CB_FreeX509Time(notAfter
);
1542 CSSM_ModuleDetach(cspHand
);
1543 CSSM_ModuleDetach(clHand
);