2 * kcExport.cpp - export keychain items using SecKeychainItemExport
5 #include <Security/Security.h>
6 #include <Security/SecImportExport.h>
7 #include <security_cdsa_utils/cuFileIo.h>
12 #include <utilLib/common.h>
14 static void usage(char **argv
)
16 printf("Usage: %s keychain [option ...]\n", argv
[0]);
18 printf(" -t <type> itemType = certs|allKeys|pubKeys|privKeys|identities|all\n");
19 printf(" ...default itemType=all\n");
20 printf(" -f <format> format = openssl|openssh1|openssh2|bsafe|pkcs7|pkcs8|pkcs12|pemseq\n"
21 " ...default itemType is pemseq for aggregate, openssl\n"
23 printf(" -p PEM encode\n");
24 printf(" -w Private keys are wrapped\n");
25 printf(" -o outFileName (default is stdout)\n");
26 printf(" -z passphrase (for PKCS12 and wrapped keys only)\n");
27 printf(" -Z Use secure passphrase\n");
28 printf(" -q Quiet\n");
43 * Add all itmes of specified class from a keychain to an array.
44 * Item class are things like kSecCertificateItemClass, and
45 * CSSM_DL_DB_RECORD_PRIVATE_KEY. Identities are searched separately.
47 static OSStatus
addKcItems(
49 SecItemClass itemClass
, // kSecCertificateItemClass
50 CFMutableArrayRef outArray
)
53 SecKeychainSearchRef srchRef
;
55 ortn
= SecKeychainSearchCreateFromAttributes(kcRef
,
60 cssmPerror("SecKeychainSearchCreateFromAttributes", ortn
);
64 SecKeychainItemRef itemRef
;
65 ortn
= SecKeychainSearchCopyNext(srchRef
, &itemRef
);
67 if(ortn
== errSecItemNotFound
) {
68 /* normal search end */
72 cssmPerror("SecKeychainSearchCopyNext", ortn
);
76 CFArrayAppendValue(outArray
, itemRef
);
77 CFRelease(itemRef
); // array owns it
84 * Add all SecIdentityRefs from a keychain into an array.
86 static OSStatus
addIdentities(
88 CFMutableArrayRef outArray
)
90 /* Search for all identities */
91 SecIdentitySearchRef srchRef
;
92 OSStatus ortn
= SecIdentitySearchCreate(kcRef
,
96 cssmPerror("SecIdentitySearchCreate", ortn
);
101 SecIdentityRef identity
;
102 ortn
= SecIdentitySearchCopyNext(srchRef
, &identity
);
104 if(ortn
== errSecItemNotFound
) {
105 /* normal search end */
109 cssmPerror("SecIdentitySearchCopyNext", ortn
);
113 CFArrayAppendValue(outArray
, identity
);
115 /* the array has the retain count we need */
117 } while(ortn
== noErr
);
122 int main(int argc
, char **argv
)
128 const char *kcName
= argv
[1];
129 SecKeychainRef kcRef
= NULL
;
130 OSStatus ortn
= SecKeychainOpen(kcName
, &kcRef
);
132 cssmPerror("SecKeychainOpen", ortn
);
136 /* user specified options */
137 ItemSpec itemSpec
= IS_All
; // default
138 SecExternalFormat exportForm
= kSecFormatUnknown
;
139 bool pemEncode
= false;
140 const char *outFile
= NULL
;
141 CFStringRef passphrase
= NULL
;
142 bool securePassphrase
= false;
144 bool wrapPrivKeys
= false;
151 while ((arg
= getopt(argc
, argv
, "t:f:po:z:Zhqw")) != -1) {
154 if(!strcmp("certs", optarg
)) {
157 else if(!strcmp("allKeys", optarg
)) {
158 itemSpec
= IS_AllKeys
;
160 else if(!strcmp("pubKeys", optarg
)) {
161 itemSpec
= IS_PubKeys
;
163 else if(!strcmp("privKeys", optarg
)) {
164 itemSpec
= IS_PrivKeys
;
166 else if(!strcmp("identities", optarg
)) {
167 itemSpec
= IS_Identities
;
169 else if(!strcmp("all", optarg
)) {
177 if(!strcmp("openssl", optarg
)) {
178 exportForm
= kSecFormatOpenSSL
;
180 else if(!strcmp("openssh1", optarg
)) {
181 exportForm
= kSecFormatSSH
;
183 else if(!strcmp("openssh2", optarg
)) {
184 exportForm
= kSecFormatSSHv2
;
186 else if(!strcmp("bsafe", optarg
)) {
187 exportForm
= kSecFormatBSAFE
;
189 else if(!strcmp("pkcs7", optarg
)) {
190 exportForm
= kSecFormatPKCS7
;
192 else if(!strcmp("pkcs8", optarg
)) {
193 exportForm
= kSecFormatWrappedPKCS8
;
195 else if(!strcmp("pkcs12", optarg
)) {
196 exportForm
= kSecFormatPKCS12
;
198 else if(!strcmp("pemseq", optarg
)) {
199 exportForm
= kSecFormatPEMSequence
;
212 passphrase
= CFStringCreateWithCString(NULL
, optarg
,
213 kCFStringEncodingASCII
);
216 securePassphrase
= true;
232 /* getopt does not return '?' */
237 case kSecFormatOpenSSL
:
238 case kSecFormatUnknown
: // i.e., use default
239 exportForm
= kSecFormatWrappedOpenSSL
;
242 exportForm
= kSecFormatWrappedSSH
;
244 case kSecFormatSSHv2
:
245 /* there is no wrappedSSHv2 */
246 exportForm
= kSecFormatWrappedOpenSSL
;
248 case kSecFormatWrappedPKCS8
:
252 printf("Don't know how to wrap in specified format/type.\n");
258 CFMutableArrayRef exportItems
= CFArrayCreateMutable(NULL
, 0,
259 &kCFTypeArrayCallBacks
);
262 ortn
= addKcItems(kcRef
, kSecCertificateItemClass
, exportItems
);
269 ortn
= addKcItems(kcRef
, CSSM_DL_DB_RECORD_PRIVATE_KEY
, exportItems
);
276 ortn
= addKcItems(kcRef
, CSSM_DL_DB_RECORD_PUBLIC_KEY
, exportItems
);
283 ortn
= addKcItems(kcRef
, CSSM_DL_DB_RECORD_PRIVATE_KEY
, exportItems
);
287 ortn
= addKcItems(kcRef
, CSSM_DL_DB_RECORD_PUBLIC_KEY
, exportItems
);
294 /* No public keys here - PKCS12 doesn't support them */
295 ortn
= addKcItems(kcRef
, kSecCertificateItemClass
, exportItems
);
299 ortn
= addKcItems(kcRef
, CSSM_DL_DB_RECORD_PRIVATE_KEY
, exportItems
);
306 ortn
= addIdentities(kcRef
, exportItems
);
312 printf("Huh? Bogus itemSpec!\n");
316 CFIndex numItems
= CFArrayGetCount(exportItems
);
318 if(exportForm
== kSecFormatUnknown
) {
319 /* Use default export format per set of items */
321 exportForm
= kSecFormatPEMSequence
;
324 exportForm
= kSecFormatOpenSSL
;
327 uint32 expFlags
= 0; // SecItemImportExportFlags
329 expFlags
|= kSecItemPemArmour
;
332 /* optional key related arguments */
333 SecKeyImportExportParameters keyParams
;
334 SecKeyImportExportParameters
*keyParamPtr
= NULL
;
335 if((passphrase
!= NULL
) || securePassphrase
) {
336 memset(&keyParams
, 0, sizeof(keyParams
));
337 keyParams
.version
= SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION
;
338 if(securePassphrase
) {
339 /* give this precedence */
340 keyParams
.flags
|= kSecKeySecurePassphrase
;
343 keyParams
.passphrase
= passphrase
; // may be NULL
345 keyParamPtr
= &keyParams
;
349 CFDataRef outData
= NULL
;
350 ortn
= SecKeychainItemExport(exportItems
, exportForm
, expFlags
, keyParamPtr
,
353 cssmPerror("SecKeychainItemExport", ortn
);
357 unsigned len
= CFDataGetLength(outData
);
359 int rtn
= writeFile(outFile
, CFDataGetBytePtr(outData
), len
);
362 printf("...%u bytes written to %s\n", len
, outFile
);
366 printf("***Error writing to %s\n", outFile
);
370 int irtn
= write(STDOUT_FILENO
, CFDataGetBytePtr(outData
), len
);
371 if(irtn
!= (int)len
) {
376 fprintf(stderr
, "\n%u items exported.\n", (unsigned)numItems
);
379 /* FIXME this in conjunction with the release of the KC crashes */
380 CFRelease(exportItems
);
383 CFRelease(passphrase
);