1 /* Copyright (c) 1998-2003,2005-2006,2008 Apple Inc.
5 * Create two certs - a root, and a subject cert signed by the root. Includes
6 * extension construction. Verify certs every which way, including various expected
7 * failures. This version uses CSSM_TP_SubmitCredRequest to create the certs.
11 #include <utilLib/common.h>
12 #include <utilLib/cspwrap.h>
13 #include <security_cdsa_utils/cuFileIo.h>
14 #include <clAppUtils/clutils.h>
18 #include <Security/cssm.h>
19 #include <Security/x509defs.h>
20 #include <Security/oidsattr.h>
21 #include <Security/oidscert.h>
22 #include <Security/oidsalg.h>
23 #include <Security/certextensions.h>
24 #include <Security/cssmapple.h>
27 #define SUBJ_KEY_LABEL "subjectKey"
28 #define ROOT_KEY_LABEL "rootKey"
29 /* default key and signature algorithm */
30 #define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
31 #define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
32 #define KEY_ALG_DEFAULT CSSM_ALGID_RSA
34 /* for write certs/keys option */
35 #define ROOT_CERT_FILE_NAME "ssRootCert.cer"
36 #define SUBJ_CERT_FILE_NAME "ssSubjCert.cer"
37 #define ROOT_KEY_FILE_NAME "ssRootKey.der"
38 #define SUBJ_KEY_FILE_NAME "ssSubjKey.der"
40 /* public key in ref form, TP supports this as of 1/30/02 */
41 #define PUB_KEY_IS_REF CSSM_TRUE
43 #define SERIAL_DEFAULT 0x12345678
45 static void usage(char **argv
)
47 printf("Usage: %s [options]\n", argv
[0]);
49 printf(" w[rite certs and keys]\n");
50 printf(" a=alg where alg is s(RSA/SHA1), m(RSA/MD5), f(FEE/MD5), F(FEE/SHA1),\n");
51 printf(" 2(RSA/SHA224), 6(RSA/SHA256), 3(RSA/SHA384) 5=RSA/SHA512,\n");
52 printf(" e(ECDSA), E(ANSI/ECDSA), 7(ECDSA/SHA256), 8(ECDSA/SHA384), 9(ECDSA/SHA512)\n");
53 printf(" k=keySizeInBits\n");
54 printf(" c=commonName (for SSL compatible subject name)\n");
55 printf(" P (loop and pause for malloc debug)\n");
56 printf("Extension options:\n");
57 printf(" t=authorityKeyName -- AuthorityKeyID, generalNames, DNSName plus s/n variant\n");
58 printf(" s -- SubjectKey, data = aabbccddeeff\n");
59 printf(" e=emailAddress -- subjectAltName, RFC822Name variant\n");
60 printf(" i=issuerAltName -- DNSName variant\n");
61 printf(" r=crlDistributionPoint -- dpn, URI variant\n");
62 printf(" u=authorityInfoAccess -- OCSP, DNSName variant\n");
63 printf(" p=certPolicyString -- CertPolicies, id_cps variant\n");
64 printf(" n=netscapeCertType -- NetscapeCertType, specify an integer\n");
65 printf(" N=serialNumber -- in decimal, default is 0x%x\n", SERIAL_DEFAULT
);
70 * RDN components for root, subject
72 static CSSM_APPLE_TP_NAME_OID rootRdn
[] =
74 { "Apple Computer", &CSSMOID_OrganizationName
},
75 { "The Big Cheesy Debug Root", &CSSMOID_CommonName
}
77 #define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
79 static CSSM_APPLE_TP_NAME_OID subjRdn
[] =
81 /* note extra space for normalize test */
82 { "Apple Computer", &CSSMOID_OrganizationName
},
83 /* this can get overridden by cmd line */
84 { "Doug Mitchell", &CSSMOID_CommonName
}
86 #define NUM_SUBJ_NAMES (sizeof(subjRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
88 static CSSM_BOOL
compareKeyData(const CSSM_KEY
*key1
, const CSSM_KEY
*key2
);
89 static CSSM_RETURN
verifyCert(CSSM_CL_HANDLE clHand
,
90 CSSM_CSP_HANDLE cspHand
,
92 CSSM_DATA_PTR signerCert
,
94 CSSM_ALGORITHMS sigAlg
,
95 CSSM_RETURN expectResult
,
96 const char *opString
);
99 * Cook up trivial CE_GeneralName, one component of specified NameType.
101 static void makeGeneralName(
102 CE_GeneralName
*genName
, /* locally declared, persistent */
104 CE_GeneralNameType nameType
) /* GNT_RFC822Name, etc. */
106 genName
->nameType
= nameType
;
107 genName
->berEncoded
= CSSM_FALSE
;
108 genName
->name
.Data
= (uint8
*)str
;
109 genName
->name
.Length
= strlen(str
);
113 * Cook up a trivial CE_GeneralNames, one component of specified NameType.
115 static void makeGeneralNames(
116 CE_GeneralNames
*genNames
, /* pointer from CE_DataAndType */
117 CE_GeneralName
*genName
, /* locally declared, persistent */
119 CE_GeneralNameType nameType
) /* GNT_RFC822Name, etc. */
121 genNames
->numNames
= 1;
122 genNames
->generalName
= genName
;
123 makeGeneralName(genName
, str
, nameType
);
126 int main(int argc
, char **argv
)
128 CSSM_CL_HANDLE clHand
; // CL handle
129 CSSM_CSP_HANDLE cspHand
; // CSP handle
130 CSSM_TP_HANDLE tpHand
; // TP handle
131 CSSM_DATA signedRootCert
; // from CSSM_CL_CertSign
132 CSSM_DATA signedSubjCert
; // from CSSM_CL_CertSign
133 CSSM_KEY subjPubKey
; // subject's RSA public key blob
134 CSSM_KEY subjPrivKey
; // subject's RSA private key - ref format
135 CSSM_KEY rootPubKey
; // root's RSA public key blob
136 CSSM_KEY rootPrivKey
; // root's RSA private key - ref format
138 CSSM_KEY_PTR extractRootKey
; // from CSSM_CL_CertGetKeyInfo()
139 CSSM_KEY_PTR extractSubjKey
; // ditto
142 unsigned errorCount
= 0;
143 CSSM_DATA refId
; // mallocd by CSSM_TP_SubmitCredRequest
144 CSSM_APPLE_TP_CERT_REQUEST certReq
;
145 CSSM_TP_REQUEST_SET reqSet
;
147 CSSM_BOOL confirmRequired
;
148 CSSM_TP_RESULT_SET_PTR rootResultSet
;
149 CSSM_TP_RESULT_SET_PTR subjResultSet
;
150 CSSM_ENCODED_CERT
*rootEncCert
;
151 CSSM_ENCODED_CERT
*subjEncCert
;
152 CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext
;
155 /* extension support */
156 CE_GeneralName sanGenName
; /* subjectAltName */
157 CE_GeneralName ianGenName
; /* issuerAltName */
158 CE_DistributionPointName distPointName
;
159 CE_GeneralName crlGenName
;
160 CE_GeneralNames crlGenNames
;
161 CE_CRLDistributionPoint cdp
;
162 CE_AccessDescription accessDescr
;
163 CE_GeneralNames authKeyIdGenNames
;
164 CE_GeneralName authKeyIdGenName
;
165 uint8 authKeyIdSerial
[4] = {0x22, 0x33, 0x44, 0x55 };
166 uint8 subjKeyIdData
[6] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
167 CE_PolicyQualifierInfo polQualInfo
;
168 CE_PolicyInformation polInfo
;
170 /* user-spec'd variables */
171 CSSM_BOOL writeBlobs
= CSSM_FALSE
;
172 CSSM_ALGORITHMS keyAlg
= KEY_ALG_DEFAULT
;
173 CSSM_ALGORITHMS sigAlg
= SIG_ALG_DEFAULT
;
174 CSSM_OID sigOid
= SIG_OID_DEFAULT
;
175 uint32 keySizeInBits
= CSP_KEY_SIZE_DEFAULT
;
176 char *subjectEmail
= NULL
; // for S/MIME subjectAltName
177 char *issuerAltName
= NULL
;
178 char *crlDistPoint
= NULL
;
179 char *authorityInfoAccess
= NULL
;
180 char *authKeyIdName
= NULL
;
181 bool subjectKeyId
= false;
182 char *certPoliciesStr
= NULL
;
183 bool netscapeTypeSpec
= false;
184 uint16 netscapeType
= 0;
185 uint32 serialNumber
= SERIAL_DEFAULT
;
186 bool loopPause
= false;
189 * Extensions. Subject at least one (KeyUsage).
190 * Root has KeyUsage and BasicConstraints.
192 CE_DataAndType exts
[8];
193 CE_DataAndType
*extp
= &exts
[0];
195 for(arg
=1; arg
<argc
; arg
++) {
196 switch(argv
[arg
][0]) {
198 writeBlobs
= CSSM_TRUE
;
201 if((argv
[arg
][1] == '\0') || (argv
[arg
][2] == '\0')) {
204 switch(argv
[arg
][2]) {
206 keyAlg
= CSSM_ALGID_RSA
;
207 sigAlg
= CSSM_ALGID_SHA1WithRSA
;
208 sigOid
= CSSMOID_SHA1WithRSA
;
211 keyAlg
= CSSM_ALGID_RSA
;
212 sigAlg
= CSSM_ALGID_MD5WithRSA
;
213 sigOid
= CSSMOID_MD5WithRSA
;
216 keyAlg
= CSSM_ALGID_RSA
;
217 sigAlg
= CSSM_ALGID_SHA224WithRSA
;
218 sigOid
= CSSMOID_SHA224WithRSA
;
221 keyAlg
= CSSM_ALGID_RSA
;
222 sigAlg
= CSSM_ALGID_SHA256WithRSA
;
223 sigOid
= CSSMOID_SHA256WithRSA
;
226 keyAlg
= CSSM_ALGID_RSA
;
227 sigAlg
= CSSM_ALGID_SHA384WithRSA
;
228 sigOid
= CSSMOID_SHA384WithRSA
;
231 keyAlg
= CSSM_ALGID_RSA
;
232 sigAlg
= CSSM_ALGID_SHA512WithRSA
;
233 sigOid
= CSSMOID_SHA512WithRSA
;
236 keyAlg
= CSSM_ALGID_FEE
;
237 sigAlg
= CSSM_ALGID_FEE_MD5
;
238 sigOid
= CSSMOID_APPLE_FEE_MD5
;
241 keyAlg
= CSSM_ALGID_FEE
;
242 sigAlg
= CSSM_ALGID_FEE_SHA1
;
243 sigOid
= CSSMOID_APPLE_FEE_SHA1
;
246 keyAlg
= CSSM_ALGID_FEE
;
247 sigAlg
= CSSM_ALGID_SHA1WithECDSA
;
248 sigOid
= CSSMOID_APPLE_ECDSA
;
251 keyAlg
= CSSM_ALGID_ECDSA
;
252 sigAlg
= CSSM_ALGID_SHA1WithECDSA
;
253 sigOid
= CSSMOID_ECDSA_WithSHA1
;
256 keyAlg
= CSSM_ALGID_ECDSA
;
257 sigAlg
= CSSM_ALGID_SHA256WithECDSA
;
258 sigOid
= CSSMOID_ECDSA_WithSHA256
;
261 keyAlg
= CSSM_ALGID_ECDSA
;
262 sigAlg
= CSSM_ALGID_SHA384WithECDSA
;
263 sigOid
= CSSMOID_ECDSA_WithSHA384
;
266 keyAlg
= CSSM_ALGID_ECDSA
;
267 sigAlg
= CSSM_ALGID_SHA512WithECDSA
;
268 sigOid
= CSSMOID_ECDSA_WithSHA512
;
275 keySizeInBits
= atoi(&argv
[arg
][2]);
278 subjectEmail
= &argv
[arg
][2];
281 issuerAltName
= &argv
[arg
][2];
284 crlDistPoint
= &argv
[arg
][2];
287 authorityInfoAccess
= &argv
[arg
][2];
290 authKeyIdName
= &argv
[arg
][2];
296 certPoliciesStr
= &argv
[arg
][2];
299 netscapeTypeSpec
= true;
300 netscapeType
= atoi(&argv
[arg
][2]);
303 subjRdn
[NUM_SUBJ_NAMES
-1].string
= &argv
[arg
][2];
306 serialNumber
= atoi(&argv
[arg
][2]);
316 /* connect to CL, TP, and CSP */
317 clHand
= clStartup();
321 tpHand
= tpStartup();
325 cspHand
= cspStartup();
330 /* subsequent errors to abort: to detach */
332 /* cook up an RSA key pair for the subject */
333 crtn
= cspGenKeyPair(cspHand
,
336 strlen(SUBJ_KEY_LABEL
),
342 CSSM_FALSE
, // pubIsRef
344 CSSM_KEYUSE_VERIFY
| CSSM_KEYUSE_ENCRYPT
,
345 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
347 writeBlobs
? CSSM_FALSE
: CSSM_TRUE
, // privIsRef
348 CSSM_KEYUSE_SIGN
| CSSM_KEYUSE_DECRYPT
,
349 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
357 crtn
= cspGenKeyPair(cspHand
,
360 strlen(ROOT_KEY_LABEL
),
363 CSSM_FALSE
, // pubIsRef - should work both ways, but not yet
365 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
367 writeBlobs
? CSSM_FALSE
: CSSM_TRUE
, // privIsRef
369 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
376 if(compareKeyData(&rootPubKey
, &subjPubKey
)) {
377 printf("**WARNING: Identical root and subj keys!\n");
381 writeFile(ROOT_KEY_FILE_NAME
, rootPrivKey
.KeyData
.Data
,
382 rootPrivKey
.KeyData
.Length
);
383 printf("...wrote %lu bytes to %s\n", rootPrivKey
.KeyData
.Length
,
385 writeFile(SUBJ_KEY_FILE_NAME
, subjPrivKey
.KeyData
.Data
,
386 subjPrivKey
.KeyData
.Length
);
387 printf("...wrote %lu bytes to %s\n", subjPrivKey
.KeyData
.Length
,
393 printf("pausing before root CSSM_TP_SubmitCredRequest; CR to continue:");
398 /* A KeyUsage extension for both certs */
399 exts
[0].type
= DT_KeyUsage
;
400 exts
[0].critical
= CSSM_FALSE
;
401 exts
[0].extension
.keyUsage
= CE_KU_DigitalSignature
| CE_KU_KeyCertSign
;
403 /* root - BasicConstraints extensions */
404 exts
[1].type
= DT_BasicConstraints
;
405 exts
[1].critical
= CSSM_TRUE
;
406 exts
[1].extension
.basicConstraints
.cA
= CSSM_TRUE
;
407 exts
[1].extension
.basicConstraints
.pathLenConstraintPresent
= CSSM_TRUE
;
408 exts
[1].extension
.basicConstraints
.pathLenConstraint
= 2;
410 /* certReq for root */
411 memset(&certReq
, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST
));
412 certReq
.cspHand
= cspHand
;
413 certReq
.clHand
= clHand
;
414 certReq
.serialNumber
= serialNumber
;
415 certReq
.numSubjectNames
= NUM_ROOT_NAMES
;
416 certReq
.subjectNames
= rootRdn
;
417 certReq
.numIssuerNames
= 0;
418 certReq
.issuerNames
= NULL
;
419 certReq
.certPublicKey
= &rootPubKey
;
420 certReq
.issuerPrivateKey
= &rootPrivKey
;
421 certReq
.signatureAlg
= sigAlg
;
422 certReq
.signatureOid
= sigOid
;
423 certReq
.notBefore
= 0; // now
424 certReq
.notAfter
= 10000; // seconds from now
425 certReq
.numExtensions
= 2;
426 certReq
.extensions
= exts
;
428 reqSet
.NumberOfRequests
= 1;
429 reqSet
.Requests
= &certReq
;
431 /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */
432 memset(&CallerAuthContext
, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT
));
433 memset(&policyId
, 0, sizeof(CSSM_FIELD
));
434 policyId
.FieldOid
= CSSMOID_APPLE_TP_LOCAL_CERT_GEN
;
435 CallerAuthContext
.Policy
.NumberOfPolicyIds
= 1;
436 CallerAuthContext
.Policy
.PolicyIds
= &policyId
;
438 /* generate root cert */
439 printf("Creating root cert...\n");
440 crtn
= CSSM_TP_SubmitCredRequest(tpHand
,
441 NULL
, // PreferredAuthority
442 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
,
448 printError("CSSM_TP_SubmitCredRequest", crtn
);
452 crtn
= CSSM_TP_RetrieveCredResult(tpHand
,
454 NULL
, // CallerAuthCredentials
459 printError("CSSM_TP_RetrieveCredResult", crtn
);
463 CSSM_FREE(refId
.Data
);
464 if(rootResultSet
== NULL
) {
465 printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
469 rootEncCert
= (CSSM_ENCODED_CERT
*)rootResultSet
->Results
;
470 signedRootCert
= rootEncCert
->CertBlob
;
472 writeFile(ROOT_CERT_FILE_NAME
, signedRootCert
.Data
, signedRootCert
.Length
);
473 printf("...wrote %lu bytes to %s\n", signedRootCert
.Length
,
474 ROOT_CERT_FILE_NAME
);
479 printf("pausing before subject CSSM_TP_SubmitCredRequest; CR to continue:");
483 /* now a subject cert signed by the root cert */
484 printf("Creating subject cert...\n");
485 certReq
.serialNumber
= serialNumber
+ 1;
486 certReq
.numSubjectNames
= NUM_SUBJ_NAMES
;
487 certReq
.subjectNames
= subjRdn
;
488 certReq
.numIssuerNames
= NUM_ROOT_NAMES
;
489 certReq
.issuerNames
= rootRdn
;
490 certReq
.certPublicKey
= &subjPubKey
;
491 certReq
.issuerPrivateKey
= &rootPrivKey
;
492 certReq
.numExtensions
= 1;
493 certReq
.extensions
= exts
;
495 /* subject cert extensions - at least KeyUsage, maybe more */
496 exts
[0].type
= DT_KeyUsage
;
497 exts
[0].critical
= CSSM_FALSE
;
498 exts
[0].extension
.keyUsage
=
499 CE_KU_DigitalSignature
| CE_KU_DataEncipherment
| CE_KU_KeyAgreement
;
503 /* subjectAltName extension */
504 makeGeneralNames(&extp
->extension
.subjectAltName
, &sanGenName
,
505 subjectEmail
, GNT_RFC822Name
);
506 extp
->type
= DT_SubjectAltName
;
507 extp
->critical
= CSSM_FALSE
;
508 certReq
.numExtensions
++;
513 /* AuthorityKeyID extension */
514 makeGeneralNames(&authKeyIdGenNames
, &authKeyIdGenName
,
515 authKeyIdName
, GNT_DNSName
);
516 CE_AuthorityKeyID
*akid
= &extp
->extension
.authorityKeyID
;
517 memset(akid
, 0, sizeof(*akid
));
518 akid
->generalNamesPresent
= CSSM_TRUE
;
519 akid
->generalNames
= &authKeyIdGenNames
;
520 akid
->serialNumberPresent
= CSSM_TRUE
;
521 akid
->serialNumber
.Data
= authKeyIdSerial
;
522 akid
->serialNumber
.Length
= sizeof(authKeyIdSerial
);
524 extp
->type
= DT_AuthorityKeyID
;
525 extp
->critical
= CSSM_FALSE
;
526 certReq
.numExtensions
++;
531 /* SubjectKeyID extension */
532 CSSM_DATA
*skid
= &extp
->extension
.subjectKeyID
;
533 skid
->Data
= subjKeyIdData
;
534 skid
->Length
= sizeof(subjKeyIdData
);
536 extp
->type
= DT_SubjectKeyID
;
537 extp
->critical
= CSSM_FALSE
;
538 certReq
.numExtensions
++;
543 /* issuerAltName extension */
544 makeGeneralNames(&extp
->extension
.issuerAltName
, &ianGenName
,
545 issuerAltName
, GNT_DNSName
);
546 extp
->type
= DT_IssuerAltName
;
547 extp
->critical
= CSSM_FALSE
;
548 certReq
.numExtensions
++;
553 /* CRLDistributionPoints extension */
554 memset(&distPointName
, 0, sizeof(distPointName
));
555 makeGeneralNames(&crlGenNames
, &crlGenName
,
556 crlDistPoint
, GNT_URI
);
557 distPointName
.nameType
= CE_CDNT_FullName
;
558 distPointName
.dpn
.fullName
= &crlGenNames
;
560 cdp
.distPointName
= &distPointName
;
561 cdp
.reasonsPresent
= CSSM_FALSE
;
563 cdp
.crlIssuer
= NULL
;
565 CE_CRLDistPointsSyntax
*dps
= &extp
->extension
.crlDistPoints
;
566 dps
->numDistPoints
= 1;
567 dps
->distPoints
= &cdp
;
568 extp
->type
= DT_CrlDistributionPoints
;
569 extp
->critical
= CSSM_FALSE
;
571 certReq
.numExtensions
++;
575 if(authorityInfoAccess
) {
576 /* AuthorityInfoAccess extension */
577 CE_AuthorityInfoAccess
*cad
= &extp
->extension
.authorityInfoAccess
;
578 cad
->numAccessDescriptions
= 1;
579 cad
->accessDescriptions
= &accessDescr
;
580 makeGeneralName(&accessDescr
.accessLocation
, authorityInfoAccess
,
582 accessDescr
.accessMethod
= CSSMOID_AD_OCSP
;
583 extp
->type
= DT_AuthorityInfoAccess
;
584 extp
->critical
= CSSM_FALSE
;
585 certReq
.numExtensions
++;
589 if(certPoliciesStr
) {
590 /* Cert Policies extension */
591 CE_CertPolicies
*cp
= &extp
->extension
.certPolicies
;
593 cp
->policies
= &polInfo
;
594 /* just make this policy OID up */
595 polInfo
.certPolicyId
= CSSMOID_APPLE_TP_PKINIT_CLIENT
;
596 polInfo
.numPolicyQualifiers
= 1;
597 polInfo
.policyQualifiers
= &polQualInfo
;
598 polQualInfo
.policyQualifierId
= CSSMOID_QT_CPS
;
599 polQualInfo
.qualifier
.Data
= (uint8
*)certPoliciesStr
;
600 polQualInfo
.qualifier
.Length
= strlen(certPoliciesStr
);
602 extp
->type
= DT_CertPolicies
;
603 extp
->critical
= CSSM_FALSE
;
604 certReq
.numExtensions
++;
608 if(netscapeTypeSpec
) {
609 /* NetscapeCertType extension */
610 extp
->extension
.netscapeCertType
= netscapeType
;
611 extp
->type
= DT_NetscapeCertType
;
612 extp
->critical
= CSSM_FALSE
;
613 certReq
.numExtensions
++;
617 crtn
= CSSM_TP_SubmitCredRequest(tpHand
,
618 NULL
, // PreferredAuthority
619 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
,
625 printError("CSSM_TP_SubmitCredRequest (2)", crtn
);
629 crtn
= CSSM_TP_RetrieveCredResult(tpHand
,
631 NULL
, // CallerAuthCredentials
636 printError("CSSM_TP_RetrieveCredResult (2)", crtn
);
640 CSSM_FREE(refId
.Data
);
641 if(subjResultSet
== NULL
) {
642 printf("***CSSM_TP_RetrieveCredResult (2) returned NULL result set.\n");
646 subjEncCert
= (CSSM_ENCODED_CERT
*)subjResultSet
->Results
;
647 signedSubjCert
= subjEncCert
->CertBlob
;
650 writeFile(SUBJ_CERT_FILE_NAME
, signedSubjCert
.Data
, signedSubjCert
.Length
);
651 printf("...wrote %lu bytes to %s\n", signedSubjCert
.Length
,
652 SUBJ_CERT_FILE_NAME
);
656 * Extract public keys from the two certs, verify.
658 crtn
= CSSM_CL_CertGetKeyInfo(clHand
, &signedSubjCert
, &extractSubjKey
);
660 printError("CSSM_CL_CertGetKeyInfo", crtn
);
663 /* compare key data - header is different.
664 * Known header differences:
665 * -- CspID - CSSM_CL_CertGetKeyInfo returns a key with NULL for
667 * -- Format. rootPubKey : 6 (CSSM_KEYBLOB_RAW_FORMAT_BSAFE)
668 * extractRootKey : 1 (CSSM_KEYBLOB_RAW_FORMAT_PKCS1)
669 * -- KeyAttr. rootPubKey : 0x20 (CSSM_KEYATTR_EXTRACTABLE)
670 * extractRootKey : 0x0
672 if(!compareKeyData(extractSubjKey
, &subjPubKey
)) {
673 printf("***CSSM_CL_CertGetKeyInfo(signedSubjCert) returned bad key data\n");
675 if(extractSubjKey
->KeyHeader
.LogicalKeySizeInBits
!=
676 subjPubKey
.KeyHeader
.LogicalKeySizeInBits
) {
677 printf("***EffectiveKeySizeInBits mismatch: extract %u subj %u\n",
678 (unsigned)extractSubjKey
->KeyHeader
.LogicalKeySizeInBits
,
679 (unsigned)subjPubKey
.KeyHeader
.LogicalKeySizeInBits
);
682 crtn
= CSSM_CL_CertGetKeyInfo(clHand
, &signedRootCert
, &extractRootKey
);
684 printError("CSSM_CL_CertGetKeyInfo", crtn
);
687 if(!compareKeyData(extractRootKey
, &rootPubKey
)) {
688 printf("***CSSM_CL_CertGetKeyInfo(signedRootCert) returned bad key data\n");
695 printf("Verifying certificates...\n");
698 * Verify root cert by root pub key, should succeed.
700 if(verifyCert(clHand
,
707 "Verify(root by root key)")) {
713 * Verify root cert by root cert, should succeed.
715 if(verifyCert(clHand
,
720 CSSM_ALGID_NONE
, // sigAlg not used here
722 "Verify(root by root cert)")) {
729 * Verify subject cert by root pub key, should succeed.
731 if(verifyCert(clHand
,
738 "Verify(subj by root key)")) {
744 * Verify subject cert by root cert, should succeed.
746 if(verifyCert(clHand
,
751 CSSM_ALGID_NONE
, // sigAlg not used here
753 "Verify(subj by root cert)")) {
759 * Verify subject cert by root cert AND key, should succeed.
761 if(verifyCert(clHand
,
768 "Verify(subj by root cert and key)")) {
774 * Verify subject cert by extracted root pub key, should succeed.
776 if(verifyCert(clHand
,
783 "Verify(subj by extracted root key)")) {
789 * Verify subject cert by subject pub key, should fail.
791 if(verifyCert(clHand
,
797 CSSMERR_CL_VERIFICATION_FAILURE
,
798 "Verify(subj by subj key)")) {
804 * Verify subject cert by subject cert, should fail.
806 if(verifyCert(clHand
,
811 CSSM_ALGID_NONE
, // sigAlg not used here
812 CSSMERR_CL_VERIFICATION_FAILURE
,
813 "Verify(subj by subj cert)")) {
819 * Verify erroneous subject cert by root pub key, should fail.
821 badByte
= genRand(1, signedSubjCert
.Length
- 1);
822 signedSubjCert
.Data
[badByte
] ^= 0x55;
823 if(verifyCert(clHand
,
829 CSSMERR_CL_VERIFICATION_FAILURE
,
830 "Verify(bad subj by root key)")) {
836 /* free/delete certs and keys */
837 CSSM_FREE(signedSubjCert
.Data
);
838 CSSM_FREE(signedRootCert
.Data
);
839 CSSM_FREE(rootEncCert
);
840 CSSM_FREE(subjEncCert
);
841 CSSM_FREE(rootResultSet
);
842 CSSM_FREE(subjResultSet
);
844 /* These don't work because CSSM_CL_CertGetKeyInfo() gives keys with
845 * a bogus GUID. This may be a problem with the Apple CSP...
847 cspFreeKey(cspHand, extractRootKey);
848 cspFreeKey(cspHand, extractSubjKey);
850 * do it this way instead...*/
851 CSSM_FREE(extractRootKey
->KeyData
.Data
);
852 CSSM_FREE(extractSubjKey
->KeyData
.Data
);
854 /* need to do this regardless...*/
855 CSSM_FREE(extractRootKey
);
856 CSSM_FREE(extractSubjKey
);
860 printf("pausing at end of loop; CR to continue:");
866 cspFreeKey(cspHand
, &rootPubKey
);
867 cspFreeKey(cspHand
, &subjPubKey
);
870 CSSM_ModuleDetach(cspHand
);
873 CSSM_ModuleDetach(clHand
);
876 CSSM_ModuleDetach(tpHand
);
880 printf("Signer/Subject test failed with %d errors\n", errorCount
);
883 printf("Signer/Subject test succeeded\n");
889 /* compare KeyData for two keys. */
890 static CSSM_BOOL
compareKeyData(const CSSM_KEY
*key1
, const CSSM_KEY
*key2
)
892 if(key1
->KeyData
.Length
!= key2
->KeyData
.Length
) {
895 if(memcmp(key1
->KeyData
.Data
,
897 key1
->KeyData
.Length
)) {
903 /* verify a cert using specified key and/or signerCert */
904 static CSSM_RETURN
verifyCert(CSSM_CL_HANDLE clHand
,
905 CSSM_CSP_HANDLE cspHand
,
907 CSSM_DATA_PTR signerCert
, // optional
908 CSSM_KEY_PTR key
, // ditto, to work spec one, other, or both
909 CSSM_ALGORITHMS sigAlg
, // CSSM_ALGID_SHA1WithRSA, etc.
910 CSSM_RETURN expectResult
,
911 const char *opString
)
914 CSSM_CC_HANDLE signContext
= CSSM_INVALID_HANDLE
;
917 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
923 printf("Failure during %s\n", opString
);
924 printError("CSSM_CSP_CreateSignatureContext", crtn
);
928 crtn
= CSSM_CL_CertVerify(clHand
,
930 cert
, // CertToBeVerified
931 signerCert
, // SignerCert
935 /* Hack to accomodate ECDSA returning CSSMERR_CSP_INVALID_SIGNATURE - a more detailed */
936 if(crtn
!= expectResult
) {
937 printf("Failure during %s\n", opString
);
938 if(crtn
== CSSM_OK
) {
939 printf("Unexpected CSSM_CL_CertVerify success\n");
941 else if(expectResult
== CSSM_OK
) {
942 printError("CSSM_CL_CertVerify", crtn
);
945 printError("CSSM_CL_CertVerify: expected", expectResult
);
946 printError("CSSM_CL_CertVerify: got ", crtn
);
948 return CSSMERR_CL_VERIFICATION_FAILURE
;
950 if(signContext
!= CSSM_INVALID_HANDLE
) {
951 crtn
= CSSM_DeleteContext(signContext
);
953 printf("Failure during %s\n", opString
);
954 printError("CSSM_DeleteContext", crtn
);