4 Description: certificate manipulation tool
8 Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
10 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
11 Computer, Inc. ("Apple") in consideration of your agreement to
12 the following terms, and your use, installation, modification
13 or redistribution of this Apple software constitutes acceptance
14 of these terms. If you do not agree with these terms, please
15 do not use, install, modify or redistribute this Apple software.
17 In consideration of your agreement to abide by the following
18 terms, and subject to these terms, Apple grants you a personal,
19 non-exclusive license, under Apple's copyrights in this
20 original Apple software (the "Apple Software"), to use,
21 reproduce, modify and redistribute the Apple Software, with
22 or without modifications, in source and/or binary forms;
23 provided that if you redistribute the Apple Software in
24 its entirety and without modifications, you must retain
25 this notice and the following text and disclaimers in all
26 such redistributions of the Apple Software. Neither the
27 name, trademarks, service marks or logos of Apple Computer,
28 Inc. may be used to endorse or promote products derived from the
29 Apple Software without specific prior written permission from
30 Apple. Except as expressly stated in this notice, no other
31 rights or licenses, express or implied, are granted by Apple
32 herein, including but not limited to any patent rights that
33 may be infringed by your derivative works or by other works
34 in which the Apple Software may be incorporated.
36 The Apple Software is provided by Apple on an "AS IS" basis.
37 APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
38 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
39 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
40 REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE
41 OR IN COMBINATION WITH YOUR PRODUCTS.
43 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
44 INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
48 AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
49 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING
50 NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE
51 HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 #include <Security/SecKeychainItem.h>
55 #include <Security/SecKeychain.h>
56 #include <Security/certextensions.h>
57 #include <Security/cssmapple.h>
58 #include <Security/oidsattr.h>
59 #include <Security/oidscert.h>
60 #include <Security/oidsalg.h>
65 #include <sys/param.h>
66 #include <cdsaUtils/cdsaUtils.h>
67 #include <cdsaUtils/printCert.h>
68 #include <cdsaUtils/fileIo.h>
69 #include <cdsaUtils/pem.h>
70 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
72 #include <CoreFoundation/CoreFoundation.h>
73 #include <Security/utilities.h>
75 /* will change soon */
76 #include <Security/SecCertificate.h>
82 /* SecKeychainGetCSPHandle implemented? */
83 #define SEC_KEYCHAIN_GET_CSP 0
85 /* SecCertificateAddToKeychain fully functional? */
86 #define SEC_CERT_ADD_TO_KC 1
88 /* SecKeyCreatePair() implemented */
89 #define SEC_KEY_CREATE_PAIR 0
91 #if !SEC_KEY_CREATE_PAIR
92 /* munge Label attr if manually generating keys */
93 #define MUNGE_LABEL_ATTR 1
96 #define KC_DB_PATH "Library/Keychains" /* relative to home */
99 * defaults for undocumented 'Z' option
101 #define ZDEF_KEY_LABEL "testCert"
102 #define ZDEF_KEY_ALG CSSM_ALGID_RSA
103 #define ZDEF_KEY_SIZE 512
104 #define ZDEF_KEY_USAGE (kKeyUseSigning | kKeyUseEncrypting)
105 #define ZDEF_SIG_ALG CSSM_ALGID_SHA1WithRSA
106 #define ZDEF_SIG_OID CSSMOID_SHA1WithRSA
107 #define ZDEF_COMMON_NAME "10.0.61.5"
108 #define ZDEF_ORG_NAME "Apple Computer - DEBUG ONLY"
109 #define ZDEF_COUNTRY "US"
110 #define ZDEF_STATE "Washington"
111 #define ZDEF_CHALLENGE "someChallenge"
113 static void usage(char **argv
)
116 printf(" Create a keypair and cert: %s c [options]\n", argv
[0]);
117 printf(" Create a CSR: %s r outFileName [options]\n",
119 printf(" Verify a CSR: %s v infileName [options]\n", argv
[0]);
120 #if SEC_CERT_ADD_TO_KC
121 printf(" Import a certificate: %s i inFileName [options]\n", argv
[0]);
123 /* this one needs the printName */
124 printf(" Import a certificate: %s i inFileName printName [options]\n",
127 printf(" Display a certificate: %s d inFileName [options]\n", argv
[0]);
128 printf("Options:\n");
129 printf(" k=keychainName\n");
130 printf(" c(reate the keychain)\n");
131 printf(" v(erbose)\n");
132 printf(" d (CSR in DER format; default is PEM)\n");
137 #if SEC_KEY_CREATE_PAIR
138 #error Work needed to generate key pair using Keychain.
142 * Workaround to manually generate a key pair and munge its DB attributes
143 * to include the hash of the public key in the private key's Label attr.
147 /* Convert a reference key to a raw key. */
148 static CSSM_RETURN
refKeyToRaw(
149 CSSM_CSP_HANDLE cspHand
,
150 const CSSM_KEY
*refKey
,
151 CSSM_KEY_PTR rawKey
) // RETURNED
153 CSSM_CC_HANDLE ccHand
;
155 CSSM_ACCESS_CREDENTIALS creds
;
157 memset(rawKey
, 0, sizeof(CSSM_KEY
));
158 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
159 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
162 &creds
, // passPhrase
163 NULL
, // wrapping key
165 CSSM_PADDING_NONE
, // Padding
169 showError(crtn
, "refKeyToRaw: context err");
172 crtn
= CSSM_WrapKey(ccHand
,
175 NULL
, // DescriptiveData
177 if(crtn
!= CSSM_OK
) {
178 showError(crtn
, "refKeyToRaw: CSSM_WrapKey");
181 CSSM_DeleteContext(ccHand
);
186 * Find private key by label, modify its Label attr to be the
187 * hash of the associated public key.
189 static CSSM_RETURN
setPubKeyHash(
190 CSSM_CSP_HANDLE cspHand
,
191 CSSM_DL_DB_HANDLE dlDbHand
,
192 const CSSM_KEY
*pubKey
, // to get hash
193 CSSM_KEY_PTR privKey
, // its record gets updated
194 const char *keyLabel
) // look up by this
197 CSSM_SELECTION_PREDICATE predicate
;
198 CSSM_DB_UNIQUE_RECORD_PTR record
= NULL
;
201 CSSM_HANDLE resultHand
;
203 labelData
.Data
= (uint8
*)keyLabel
;
204 labelData
.Length
= strlen(keyLabel
) + 1; // incl. NULL
205 query
.RecordType
= CSSM_DL_DB_RECORD_PRIVATE_KEY
;
206 query
.Conjunctive
= CSSM_DB_NONE
;
207 query
.NumSelectionPredicates
= 1;
208 predicate
.DbOperator
= CSSM_DB_EQUAL
;
210 predicate
.Attribute
.Info
.AttributeNameFormat
=
211 CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
212 predicate
.Attribute
.Info
.Label
.AttributeName
= "Label";
213 predicate
.Attribute
.Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
214 /* hope this cast is OK */
215 predicate
.Attribute
.Value
= &labelData
;
216 query
.SelectionPredicate
= &predicate
;
218 query
.QueryLimits
.TimeLimit
= 0; // FIXME - meaningful?
219 query
.QueryLimits
.SizeLimit
= 1; // FIXME - meaningful?
220 query
.QueryFlags
= 0; // CSSM_QUERY_RETURN_DATA; // FIXME - used?
222 /* build Record attribute with one attr */
223 CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs
;
224 CSSM_DB_ATTRIBUTE_DATA attr
;
225 attr
.Info
.AttributeNameFormat
= CSSM_DB_ATTRIBUTE_NAME_AS_STRING
;
226 attr
.Info
.Label
.AttributeName
= "Label";
227 attr
.Info
.AttributeFormat
= CSSM_DB_ATTRIBUTE_FORMAT_BLOB
;
229 recordAttrs
.DataRecordType
= CSSM_DL_DB_RECORD_PRIVATE_KEY
;
230 recordAttrs
.NumberOfAttributes
= 1;
231 recordAttrs
.AttributeData
= &attr
;
233 crtn
= CSSM_DL_DataGetFirst(dlDbHand
,
237 NULL
, // hopefully optional ...theData,
239 /* abort only on success */
240 if(crtn
!= CSSM_OK
) {
241 showError(crtn
, "CSSM_DL_DataGetFirst");
242 printf("***setPubKeyHash: can't find private key\n");
246 /* do NULL unwrap of public key for use with raw CSP */
248 crtn
= refKeyToRaw(cspHand
, pubKey
, &rawPubKey
);
250 printf("***Error converting public key to raw format\n");
254 /* connect to raw CSP */
255 CSSM_CSP_HANDLE rawCspHand
= cuCspStartup(CSSM_TRUE
);
256 if(rawCspHand
== 0) {
257 printf("***Error connecting to raw CSP; aborting.\n");
261 /* calculate hash of pub key */
262 CSSM_DATA_PTR keyDigest
= NULL
;
263 CSSM_CC_HANDLE ccHand
;
264 crtn
= CSSM_CSP_CreatePassThroughContext(rawCspHand
,
268 showError(crtn
, "CSSM_CSP_CreatePassThroughContext");
269 printf("***Error calculating public key hash. Aborting.\n");
272 crtn
= CSSM_CSP_PassThrough(ccHand
,
273 CSSM_APPLECSP_KEYDIGEST
,
275 (void **)&keyDigest
);
277 showError(crtn
, "CSSM_CSP_PassThrough(PUBKEYHASH)");
278 printf("***Error calculating public key hash. Aborting.\n");
281 CSSM_FreeKey(cspHand
, NULL
, &rawPubKey
, CSSM_FALSE
);
282 CSSM_DeleteContext(ccHand
);
283 CSSM_ModuleDetach(rawCspHand
);
286 * Replace Label attr data with hash.
287 * NOTE: the module which allocated this attribute data - a DL -
288 * was loaded and attached by the Sec layer, not by us. Thus
289 * we can't use the memory allocator functions *we* used when
290 * attaching to the CSPDL - we have to use the ones
291 * which the Sec layer registered with the DL.
293 CSSM_API_MEMORY_FUNCS memFuncs
;
294 crtn
= CSSM_GetAPIMemoryFunctions(dlDbHand
.DLHandle
, &memFuncs
);
296 showError(crtn
, "CSSM_GetAPIMemoryFunctions(DLHandle)");
297 /* oh well, leak and continue */
300 memFuncs
.free_func(attr
.Value
->Data
, memFuncs
.AllocRef
);
301 memFuncs
.free_func(attr
.Value
, memFuncs
.AllocRef
);
303 attr
.Value
= keyDigest
;
305 /* modify key attributes */
306 crtn
= CSSM_DL_DataModify(dlDbHand
,
307 CSSM_DL_DB_RECORD_PRIVATE_KEY
,
310 NULL
, // DataToBeModified
311 CSSM_DB_MODIFY_ATTRIBUTE_REPLACE
);
313 showError(crtn
, "CSSM_DL_DataModify(PUBKEYHASH)");
314 printf("***Error setting public key hash. Aborting.\n");
317 crtn
= CSSM_DL_DataAbortQuery(dlDbHand
, resultHand
);
319 showError(crtn
, "CSSM_DL_DataAbortQuery");
320 /* let's keep going in this case */
322 crtn
= CSSM_DL_FreeUniqueRecord(dlDbHand
, record
);
324 showError(crtn
, "CSSM_DL_FreeUniqueRecord");
325 /* let's keep going in this case */
330 cuAppFree(keyDigest
->Data
, NULL
);
333 #endif /* MUNGE_LABEL_ATTR */
335 /* Still on the !SEC_KEY_CREATE_PAIR workaround */
338 * Generate a key pair using the CSPDL.
340 static OSStatus
generateKeyPair(
341 CSSM_CSP_HANDLE cspHand
,
342 CSSM_DL_DB_HANDLE dlDbHand
,
343 CSSM_ALGORITHMS keyAlg
, // e.g., CSSM_ALGID_RSA
344 uint32 keySizeInBits
,
345 const char *keyLabel
, // C string
346 CU_KeyUsage keyUsage
, // CUK_Signing, etc.
348 CSSM_KEY_PTR
*pubKeyPtr
, // mallocd, created, RETURNED
349 CSSM_KEY_PTR
*privKeyPtr
) // mallocd, created, RETURNED
351 CSSM_KEY_PTR pubKey
= reinterpret_cast<CSSM_KEY_PTR
>(
352 APP_MALLOC(sizeof(CSSM_KEY
)));
353 CSSM_KEY_PTR privKey
= reinterpret_cast<CSSM_KEY_PTR
>(
354 APP_MALLOC(sizeof(CSSM_KEY
)));
355 if((pubKey
== NULL
) || (privKey
== NULL
)) {
360 CSSM_KEYUSE pubKeyUse
= 0;
361 CSSM_KEYUSE privKeyUse
= 0;
363 if(keyUsage
& kKeyUseSigning
) {
364 pubKeyUse
|= CSSM_KEYUSE_VERIFY
;
365 privKeyUse
|= CSSM_KEYUSE_SIGN
;
367 if(keyUsage
& kKeyUseEncrypting
) {
368 pubKeyUse
|= (CSSM_KEYUSE_ENCRYPT
| CSSM_KEYUSE_WRAP
);
369 privKeyUse
|= (CSSM_KEYUSE_DECRYPT
| CSSM_KEYUSE_UNWRAP
);
372 crtn
= cuCspGenKeyPair(cspHand
,
376 strlen(keyLabel
) + 1,
380 CSSM_KEYATTR_EXTRACTABLE
| CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_PERMANENT
,
383 CSSM_KEYATTR_SENSITIVE
| CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_PERMANENT
);
390 printf("...%u bit key pair generated.\n",
391 (unsigned)keySizeInBits
);
395 /* bind private key to cert by public key hash */
396 crtn
= setPubKeyHash(cspHand
,
402 printf("***Error setting public key hash. Continuing at peril.\n");
404 #endif /* MUNGE_LABEL_ATTR */
407 *privKeyPtr
= privKey
;
410 #endif /* SEC_KEY_CREATE_PAIR */
412 static void verifyCsr(
413 CSSM_CL_HANDLE clHand
,
414 const char *fileName
,
417 unsigned char *csr
= NULL
;
420 unsigned char *der
= NULL
;
423 if(readFile(fileName
, &csr
, &csrLen
)) {
424 printf("***Error reading CSR from file %s. Aborting.\n",
429 int rtn
= pemDecode(csr
, csrLen
, &der
, &derLen
);
431 printf("***%s: Bad PEM formatting. Aborting.\n", fileName
);
435 csrData
.Length
= derLen
;
439 csrData
.Length
= csrLen
;
442 CSSM_RETURN crtn
= CSSM_CL_PassThrough(clHand
,
444 CSSM_APPLEX509CL_VERIFY_CSR
,
448 cuPrintError("Verify CSR", crtn
);
451 printf("...CSR verified successfully.\n");
461 static void displayCert(
462 const char *fileName
,
465 unsigned char *rawCert
= NULL
;
466 unsigned rawCertSize
;
467 unsigned char *derCert
= NULL
;
468 unsigned derCertSize
;
471 rtn
= readFile(fileName
, &rawCert
, &rawCertSize
);
473 printf("Error reading %s; aborting.\n", fileName
);
477 rtn
= pemDecode(rawCert
, rawCertSize
, &derCert
, &derCertSize
);
479 printf("***%s: Bad PEM formatting. Aborting.\n", fileName
);
482 printCert(derCert
, derCertSize
, CSSM_TRUE
);
486 printCert(rawCert
, rawCertSize
, CSSM_TRUE
);
490 static void importCert(
491 SecKeychainRef kcRef
, // if SEC_CERT_ADD_TO_KC
492 CSSM_DL_DB_HANDLE dlDbHand
, // otherwise
493 const char *fileName
,
495 /* cruft needed by cuAddCertToDb */
496 const char *printName
) // C string
498 unsigned char *cert
= NULL
;
501 unsigned char *der
= NULL
;
503 #if !SEC_CERT_ADD_TO_KC
504 CSSM_DATA pubKeyHash
= {3, (uint8
*)"foo"};
507 if(readFile(fileName
, &cert
, &certLen
)) {
508 printf("***Error reading certificate from file %s. Aborting.\n",
513 int rtn
= pemDecode(cert
, certLen
, &der
, &derLen
);
515 printf("***%s: Bad PEM formatting. Aborting.\n", fileName
);
519 certData
.Length
= derLen
;
522 certData
.Data
= cert
;
523 certData
.Length
= certLen
;
526 #if SEC_CERT_ADD_TO_KC
527 SecCertificateRef certRef
;
528 OSStatus ortn
= SecCertificateCreateFromData(
531 CSSM_CERT_ENCODING_DER
,
534 printf("***SecCertificateCreateFromData returned %d; aborting.\n",
538 ortn
= SecCertificateAddToKeychain(certRef
, kcRef
);
540 printf("***SecCertificateAddToKeychain returned %d; aborting.\n",
545 CSSM_RETURN crtn
= cuAddCertToDb(dlDbHand
,
548 CSSM_CERT_ENCODING_DER
,
549 printName
, // printName
552 printf("***Error adding cert to keychain. Aborting.\n");
555 #endif /* SEC_CERT_ADD_TO_KC */
557 printf("...certificate successfully imported.\n");
567 static OSStatus
createCertCsr(
568 CSSM_BOOL createCsr
, // true: CSR, false: Cert
569 CSSM_TP_HANDLE tpHand
, // eventually, a SecKeychainRef
570 CSSM_CL_HANDLE clHand
,
571 CSSM_CSP_HANDLE cspHand
,
572 CSSM_KEY_PTR subjPubKey
,
573 CSSM_KEY_PTR signerPrivKey
,
574 CSSM_ALGORITHMS sigAlg
,
575 const CSSM_OID
*sigOid
,
576 CU_KeyUsage keyUsage
, // kKeyUseSigning, etc.
578 * Issuer's RDN is obtained from the issuer cert, if present, or is
579 * assumed to be the same as the subject name (i.e., we're creating
580 * a self-signed root cert).
582 const CSSM_DATA
*issuerCert
,
583 CSSM_BOOL useAllDefaults
,
584 CSSM_DATA_PTR certData
) // mallocd and RETURNED
586 CE_DataAndType exts
[2];
587 CE_DataAndType
*extp
= exts
;
590 CSSM_DATA refId
; // mallocd by CSSM_TP_SubmitCredRequest
591 CSSM_APPLE_TP_CERT_REQUEST certReq
;
592 CSSM_TP_REQUEST_SET reqSet
;
594 CSSM_BOOL confirmRequired
;
595 CSSM_TP_RESULT_SET_PTR resultSet
;
596 CSSM_ENCODED_CERT
*encCert
;
597 CSSM_APPLE_TP_NAME_OID subjectNames
[MAX_NAMES
];
599 CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext
;
602 /* Note a lot of the CSSM_APPLE_TP_CERT_REQUEST fields are not
603 * used for the createCsr option, but we'll fill in as much as is practical
606 if(issuerCert
!= NULL
) {
607 printf("createCertCsr: issuerCert not implemented\n");
613 char challengeBuf
[400];
616 strcpy(challengeBuf
, ZDEF_CHALLENGE
);
620 getStringWithPrompt("Enter challenge string: ",
621 challengeBuf
, sizeof(challengeBuf
));
622 if(challengeBuf
[0] != '\0') {
627 certReq
.challengeString
= challengeBuf
;
631 certReq
.challengeString
= NULL
;
633 /* KeyUsage extension */
634 extp
->type
= DT_KeyUsage
;
635 extp
->critical
= CSSM_FALSE
;
636 extp
->extension
.keyUsage
= 0;
637 if(keyUsage
& kKeyUseSigning
) {
638 extp
->extension
.keyUsage
|=
639 (CE_KU_DigitalSignature
| CE_KU_KeyCertSign
);
641 if(keyUsage
& kKeyUseEncrypting
) {
642 extp
->extension
.keyUsage
|=
643 (CE_KU_KeyEncipherment
| CE_KU_DataEncipherment
);
648 /* BasicConstraints */
649 extp
->type
= DT_BasicConstraints
;
650 extp
->critical
= CSSM_TRUE
;
651 extp
->extension
.basicConstraints
.cA
= CSSM_TRUE
;
652 extp
->extension
.basicConstraints
.pathLenConstraintPresent
= CSSM_FALSE
;
657 /* name array, get from user. */
659 subjectNames
[0].string
= ZDEF_COMMON_NAME
;
660 subjectNames
[0].oid
= &CSSMOID_CommonName
;
661 subjectNames
[1].string
= ZDEF_ORG_NAME
;
662 subjectNames
[1].oid
= &CSSMOID_OrganizationName
;
663 subjectNames
[2].string
= ZDEF_COUNTRY
;
664 subjectNames
[2].oid
= &CSSMOID_CountryName
;
665 subjectNames
[3].string
= ZDEF_STATE
;
666 subjectNames
[3].oid
= &CSSMOID_StateProvinceName
;
670 getNameOids(subjectNames
, &numNames
);
674 certReq
.cspHand
= cspHand
;
675 certReq
.clHand
= clHand
;
676 certReq
.serialNumber
= 0x12345678; // TBD - random? From user?
677 certReq
.numSubjectNames
= numNames
;
678 certReq
.subjectNames
= subjectNames
;
680 /* TBD - if we're passed in a signing cert, certReq.issuerNameX509 will
681 * be obtained from that cert. For now we specify "self-signed" cert
682 * by not providing an issuer name at all. */
683 certReq
.numIssuerNames
= 0; // root for now
684 certReq
.issuerNames
= NULL
;
685 certReq
.issuerNameX509
= NULL
;
686 certReq
.certPublicKey
= subjPubKey
;
687 certReq
.issuerPrivateKey
= signerPrivKey
;
688 certReq
.signatureAlg
= sigAlg
;
689 certReq
.signatureOid
= *sigOid
;
690 certReq
.notBefore
= 0; // TBD - from user
691 certReq
.notAfter
= 60 * 60 * 24 * 30; // seconds from now
692 certReq
.numExtensions
= numExts
;
693 certReq
.extensions
= exts
;
695 reqSet
.NumberOfRequests
= 1;
696 reqSet
.Requests
= &certReq
;
698 /* a CSSM_TP_CALLERAUTH_CONTEXT to specify an OID */
699 memset(&CallerAuthContext
, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT
));
700 memset(&policyId
, 0, sizeof(CSSM_FIELD
));
702 policyId
.FieldOid
= CSSMOID_APPLE_TP_CSR_GEN
;
705 policyId
.FieldOid
= CSSMOID_APPLE_TP_LOCAL_CERT_GEN
;
707 CallerAuthContext
.Policy
.NumberOfPolicyIds
= 1;
708 CallerAuthContext
.Policy
.PolicyIds
= &policyId
;
710 CSSM_RETURN crtn
= CSSM_TP_SubmitCredRequest(tpHand
,
711 NULL
, // PreferredAuthority
712 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
,
718 /* before proceeding, free resources allocated thus far */
719 if(!useAllDefaults
) {
720 freeNameOids(subjectNames
, numNames
);
724 cuPrintError("CSSM_TP_SubmitCredRequest", crtn
);
727 crtn
= CSSM_TP_RetrieveCredResult(tpHand
,
729 NULL
, // CallerAuthCredentials
734 cuPrintError("CSSM_TP_RetrieveCredResult", crtn
);
737 if(resultSet
== NULL
) {
738 printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
741 encCert
= (CSSM_ENCODED_CERT
*)resultSet
->Results
;
742 *certData
= encCert
->CertBlob
;
744 /* free resources allocated by TP */
745 APP_FREE(refId
.Data
);
760 int main(int argc
, char **argv
)
762 SecKeychainRef kcRef
= nil
;
763 char kcPath
[MAXPATHLEN
+ 1];
764 UInt32 kcPathLen
= MAXPATHLEN
+ 1;
765 CSSM_BOOL createKc
= CSSM_FALSE
;
767 CSSM_DL_DB_HANDLE dlDbHand
= {0, 0};
768 CSSM_CSP_HANDLE cspHand
= 0;
769 CSSM_TP_HANDLE tpHand
= 0;
770 CSSM_CL_HANDLE clHand
= 0;
772 CSSM_KEY_PTR privKey
;
775 CSSM_BOOL verbose
= CSSM_FALSE
;
776 CSSM_ALGORITHMS keyAlg
;
777 CSSM_ALGORITHMS sigAlg
;
778 const CSSM_OID
*sigOid
;
779 CSSM_DATA certData
= {0, NULL
};
781 CU_KeyUsage keyUsage
= 0;
784 #if !SEC_KEY_CREATE_PAIR && !MUNGE_LABEL_ATTR
785 CSSM_DATA pubKeyHash
= {3, (uint8
*)"foo"};
787 CSSM_BOOL createCsr
= CSSM_FALSE
; // else create cert
790 /* command line arguments */
791 char *fileName
= NULL
;
792 CSSM_BOOL pemFormat
= CSSM_TRUE
;
793 char *certPrintName
= NULL
;
795 uint32 keySizeInBits
;
797 CSSM_BOOL useAllDefaults
= CSSM_FALSE
; // undoc'd cmd option
812 createCsr
= CSSM_TRUE
;
825 #if SEC_CERT_ADD_TO_KC
834 certPrintName
= argv
[3];
836 #endif /* SEC_CERT_ADD_TO_KC */
851 for(arg
=optArgs
; arg
<argc
; arg
++) {
861 pemFormat
= CSSM_FALSE
;
864 createKc
= CSSM_TRUE
;
867 /* undocumented "use all defaults quickly" option */
868 useAllDefaults
= CSSM_TRUE
;
874 if(op
== CO_DisplayCert
) {
876 displayCert(fileName
, pemFormat
);
880 clHand
= cuClStartup();
882 printf("Error connecting to CL. Aborting.\n");
886 /* that's all we need for verifying a CSR */
887 if(op
== CO_VerifyCSR
) {
888 verifyCsr(clHand
, fileName
, pemFormat
);
892 /* remaining ops need TP and CSP as well */
893 #if !SEC_KEYCHAIN_GET_CSP
894 /* get it from keychain */
895 cspHand
= cuCspStartup(CSSM_FALSE
);
897 printf("Error connecting to CSP/DL. Aborting.\n");
901 tpHand
= cuTpStartup();
903 printf("Error connecting to TP. Aborting.\n");
908 char *userHome
= getenv("HOME");
910 if(userHome
== NULL
) {
911 /* well, this is probably not going to work */
914 sprintf(kcPath
, "%s/%s/%s", userHome
, KC_DB_PATH
, kcName
);
918 /* use default keychain */
919 ortn
= SecKeychainCopyDefault(&kcRef
);
921 showError(ortn
, "SecKeychainCopyDefault");
924 ortn
= SecKeychainGetPath(kcRef
, &kcPathLen
, kcPath
);
926 showError(ortn
, "SecKeychainGetPath");
931 * OK, we have a path, we have to release the first KC ref,
932 * then get another one by opening it
937 ortn
= SecKeychainCreate(kcPath
,
941 nil
, // initialAccess
943 /* fixme - do we have to open it? */
945 showError(ortn
, "SecKeychainCreateNew");
946 printf("***Error creating keychain at %s; aborting.\n", kcPath
);
951 ortn
= SecKeychainOpen(kcPath
, &kcRef
);
953 showError(ortn
, "SecKeychainOpen");
954 printf("Cannot open keychain at %s. Aborting.\n", kcPath
);
959 /* get associated DL/DB handle */
960 ortn
= SecKeychainGetDLDBHandle(kcRef
, &dlDbHand
);
962 showError(ortn
, "SecKeychainGetDLDBHandle");
966 if(op
== CO_ImportCert
) {
967 importCert(kcRef
, dlDbHand
, fileName
, pemFormat
, certPrintName
);
971 #if SEC_KEYCHAIN_GET_CSP
972 /* create cert, CSR need CSP handle */
973 ortn
= SecKeychainGetCSPHandle(kcRef
, &cspHand
);
975 showError(ortn
, "SecKeychainGetCSPHandle");
981 * TBD: eventually we want to present the option of using an existing
982 * SecIdentityRef from the keychain as the signing cert/key. If none
983 * found or the user says they want a root, we generate the signing key
984 * pair as follows....
989 * Generate a key pair. For now we do this via CDSA.
993 strcpy(labelBuf
, ZDEF_KEY_LABEL
);
997 getStringWithPrompt("Enter key and certificate label: ", labelBuf
,
999 if(labelBuf
[0] != '\0') {
1004 keyLabel
.Data
= (uint8
*)labelBuf
;
1005 keyLabel
.Length
= strlen(labelBuf
);
1007 /* get key algorithm and size */
1008 if(useAllDefaults
) {
1009 keyAlg
= ZDEF_KEY_ALG
;
1010 keySizeInBits
= ZDEF_KEY_SIZE
;
1013 getKeyParams(keyAlg
, keySizeInBits
);
1016 /* get usage for keys and certs */
1017 if(useAllDefaults
) {
1018 keyUsage
= ZDEF_KEY_USAGE
;
1021 keyUsage
= getKeyUsage(isRoot
);
1024 printf("...Generating key pair...\n");
1025 ortn
= generateKeyPair(cspHand
,
1035 printf("Error generating keys; aborting.\n");
1039 /* get signing algorithm per the signing key */
1040 if(useAllDefaults
) {
1041 sigAlg
= ZDEF_SIG_ALG
;
1042 sigOid
= &ZDEF_SIG_OID
;
1045 ortn
= getSigAlg(privKey
, sigAlg
, sigOid
);
1047 printf("Can not sign with this private key. Aborting.\n");
1053 printf("...creating CSR...\n");
1056 printf("...creating certificate...\n");
1058 /* generate the cert */
1059 ortn
= createCertCsr(createCsr
,
1068 NULL
, // issuer cert
1075 printCert(certData
.Data
, certData
.Length
, CSSM_FALSE
);
1076 printCertShutdown();
1080 /* just write this to a file */
1081 unsigned char *pem
= NULL
;
1086 rtn
= pemEncode(certData
.Data
, certData
.Length
, &pem
, &pemLen
,
1087 "CERTIFICATE REQUEST");
1089 /* very unlikely, I think malloc is the only failure */
1090 printf("***Error PEM-encoding CSR. Aborting.\n");
1093 rtn
= writeFile(fileName
, pem
, pemLen
);
1096 rtn
= writeFile(fileName
, certData
.Data
, certData
.Length
);
1099 printf("***Error writing CSR to %s\n", fileName
);
1102 printf("Wrote %u bytes of CSR to %s\n", (unsigned)certData
.Length
,
1110 /* store the cert in the same DL/DB as the key pair */
1111 #if SEC_CERT_ADD_TO_KC
1112 crtn
= cuAddCertToKC(kcRef
,
1115 CSSM_CERT_ENCODING_DER
,
1116 labelBuf
, // printName
1119 crtn
= cuAddCertToDb(dlDbHand
,
1122 CSSM_CERT_ENCODING_DER
,
1123 labelBuf
, // printName
1125 #endif /* SEC_CERT_ADD_TO_KC */
1126 if(crtn
== CSSM_OK
) {
1127 printf("..cert stored in Keychain.\n");