2 * p12ImportExport.cpp - high-level libnsspkcs12 exerciser
5 #include <security_pkcs12/SecPkcs12.h>
6 #include <security_cdsa_utils/cuFileIo.h>
7 #include <Security/Security.h>
10 #include <security_cdsa_utilities/KeySchema.h>
11 #include <security_cdsa_utils/cuCdsaUtils.h>
12 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
13 #include "p12GetPassKey.h"
15 static void printOsError(
21 case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA
:
22 errStr
= "CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA"; break;
23 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST
:
24 errStr
= "CSSMERR_DL_DATASTORE_DOESNOT_EXIST"; break;
25 case errSecDuplicateItem
:
26 errStr
= "errSecDuplicateItem"; break;
27 case errSecNotAvailable
:
28 errStr
= "errSecNotAvailable"; break;
29 case errSecAuthFailed
:
30 errStr
= "errSecAuthFailed"; break;
31 case errSecItemNotFound
:
32 errStr
= "errSecItemNotFound"; break;
33 case errSecInvalidItemRef
:
34 errStr
= "errSecInvalidItemRef"; break;
39 printf("%s returned %s\n", op
, errStr
);
42 printf("%s returned %d\n", op
, (int)ortn
);
47 * For now we assume "import everything"
52 CFStringRef pwd
, // explicit passphrase, mutually exclusive with...
53 bool usePassKey
, // use SECURE_PASSPHRASE key
54 const char *kcPwd
) // optional
62 if(readFile(pfxFile
, &pfx
, &pfxLen
)) {
63 printf("***Error reading pfx from %s. Aborting.\n", pfxFile
);
66 CFDataRef cfd
= CFDataCreate(NULL
, pfx
, pfxLen
);
68 /* import to keychain specified by kcName */
69 SecKeychainRef kcRef
= NULL
;
70 ortn
= SecKeychainOpen(kcName
, &kcRef
);
72 printOsError("SecKeychainOpen", ortn
);
77 ortn
= SecKeychainUnlock(kcRef
, strlen(kcPwd
), (void *)kcPwd
, true);
79 printOsError("SecKeychainUnlock", ortn
);
83 /* set up a pkcs12 coder for import */
84 SecPkcs12CoderRef coder
;
85 ortn
= SecPkcs12CoderCreate(&coder
);
87 printOsError("SecPkcs12CoderCreate", ortn
);
91 ortn
= SecPkcs12SetKeychain(coder
, kcRef
);
93 printOsError("SecPkcs12SetKeychain", ortn
);
98 CSSM_CSP_HANDLE cspHand
;
99 ortn
= SecKeychainGetCSPHandle(kcRef
, &cspHand
);
101 printOsError("SecPkcs12SetKeychain", ortn
);
104 ortn
= p12GetPassKey(cspHand
, GPK_Decode
, false, &passKey
);
108 ortn
= SecPkcs12SetMACPassKey(coder
, &passKey
);
110 printOsError("SecPkcs12SetMACPassKey", ortn
);
115 ortn
= SecPkcs12SetMACPassphrase(coder
, pwd
);
117 printOsError("SecPkcs12SetMACPassphrase", ortn
);
123 * For now we assume "import everything"
125 ortn
= SecPkcs12SetImportToKeychain(coder
,
126 kSecImportCertificates
|
130 printOsError("SecPkcs12SetImportFromKeychain", ortn
);
135 ortn
= SecPkcs12Decode(coder
, cfd
);
137 printOsError("SecPkcs12Decode", ortn
);
141 /* report how many of each item got imported */
143 SecPkcs12CertificateCount(coder
, &num
);
144 printf("...%d certs imported\n", (int)num
);
145 SecPkcs12CrlCount(coder
, &num
);
146 printf("...%d CRLs imported\n", (int)num
);
147 SecPkcs12PrivateKeyCount(coder
, &num
);
148 printf("...%d private keys imported\n", (int)num
);
150 SecPkcs12CoderRelease(coder
);
152 free(pfx
); // mallocd by readFile()
157 * Use the kludge from hell to get the name-as-int form of a specified
158 * "known" name-as-string for the Key Schema.
160 OSStatus
attrNameToInt(
164 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO
*attrList
=
165 KeySchema::KeySchemaAttributeList
;
166 unsigned numAttrs
= KeySchema::KeySchemaAttributeCount
;
167 for(unsigned dex
=0; dex
<numAttrs
; dex
++) {
168 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO
*info
= &attrList
[dex
];
169 if(!strcmp(name
, info
->AttributeName
)) {
170 *attrInt
= info
->AttributeId
;
177 static int p12AddExportedItem(
178 SecKeychainItemRef item
,
179 CFMutableArrayRef itemArray
,
183 CFArrayAppendValue(itemArray
, item
);
187 CFTypeID itemId
= CFGetTypeID(item
);
190 /* the printable name attr */
192 char *itemClass
= "";
193 if(itemId
== SecCertificateGetTypeID()) {
194 itemClass
= "Certificate";
195 nameAttr
= kSecLabelItemAttr
;
197 else if(itemId
== SecKeyGetTypeID()) {
198 itemClass
= "Private Key";
199 ortn
= attrNameToInt("PrintName", &nameAttr
);
201 /* out of sync with Sec layer? With KeySchema? */
202 printf("warning: attrNameToInt failure\n");
207 /* we don't know how to deal with this */
208 printf("p12AddExportedItem: internal screwup\n");
212 /* get the printable name attr */
213 SecKeychainAttributeInfo attrInfo
;
215 attrInfo
.tag
= &nameAttr
;
216 attrInfo
.format
= NULL
; // ???
218 /* FIXME header says this is an IN/OUT param, but it's not */
219 SecKeychainAttributeList
*attrList
= NULL
;
221 ortn
= SecKeychainItemCopyAttributesAndData(
226 NULL
, // don't need the data
229 printOsError("SecKeychainItemCopyAttributesAndData", ortn
);
232 if(attrList
->count
!= 1) {
233 printf("***Unexpected attribute count (%u) for %s\n",
234 (unsigned)attrList
->count
, itemClass
);
237 SecKeychainAttribute
*attr
= attrList
->attr
;
239 /* it's a UTF8 string: use CFString to convert to C ASCII string */
240 CFStringRef cfStr
= CFStringCreateWithBytes(NULL
,
241 (UInt8
*)attr
->data
, attr
->length
,
242 kCFStringEncodingUTF8
, false);
243 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
245 printf("***Error converting %s name to UTF CFSTring.\n",
250 CFIndex strLen
= CFStringGetLength(cfStr
);
251 char *printName
= (char *)malloc(strLen
+ 1);
252 if(!CFStringGetCString(cfStr
, printName
, strLen
+ 1, kCFStringEncodingASCII
)) {
253 printf("***Error converting %s name to ASCII\n", itemClass
);
258 char *aliasCStr
= NULL
;
259 if((itemId
== SecCertificateGetTypeID())) {
260 /* the alias attr, for cert email */
261 CFStringRef aliasCFStr
= NULL
;
262 nameAttr
= kSecAlias
;
264 attrInfo
.tag
= &nameAttr
;
265 attrInfo
.format
= NULL
; // ???
268 ortn
= SecKeychainItemCopyAttributesAndData(
273 NULL
, // don't need the data
276 printOsError("SecKeychainItemCopyAttributesAndData", ortn
);
279 if(attrList
->count
!= 1) {
280 printf("***Unexpected attribute count (%u) for Alias\n",
281 (unsigned)attrList
->count
);
284 attr
= attrList
->attr
;
286 /* it's a UTF8 string: use CFString to convert to C ASCII string */
287 aliasCFStr
= CFStringCreateWithBytes(NULL
,
288 (UInt8
*)attr
->data
, attr
->length
,
289 kCFStringEncodingUTF8
, false);
290 if(aliasCFStr
== NULL
) {
291 printf("***Error converting Alias name to UTF CFSTring.\n");
295 strLen
= CFStringGetLength(aliasCFStr
);
296 aliasCStr
= (char *)malloc(strLen
+ 1);
297 if(!CFStringGetCString(aliasCFStr
, aliasCStr
, strLen
+ 1,
298 kCFStringEncodingASCII
)) {
299 printf("***Error converting Alias name to ASCII\n");
302 CFRelease(aliasCFStr
);
307 printf("Found %s\n", itemClass
);
308 printf(" printable name : %s\n", printName
);
309 if(aliasCStr
!= NULL
) {
310 printf(" alias : %s\n", aliasCStr
);
312 printf("Export (y/anything)? ");
315 CFArrayAppendValue(itemArray
, item
);
328 CFStringRef pwd
, // explicit passphrase, mutually exclusive with...
329 bool usePassKey
, // use SECURE_PASSPHRASE key
330 const char *kcPwd
, // optional
331 bool noPrompt
) // true --> export all
336 /* set up a pkcs12 coder for export */
337 SecPkcs12CoderRef coder
;
338 ortn
= SecPkcs12CoderCreate(&coder
);
340 printOsError("SecPkcs12CoderCreate", ortn
);
345 Ê* Since we're not providing the SecPkcs12CoderRef with a
346 * keychain, we have to provide the CSPDL handle
348 CSSM_CSP_HANDLE cspHand
= cuCspStartup(CSSM_FALSE
);
350 printf("***Error attaching to CSPDL. Aborting.\n");
355 ortn
= p12GetPassKey(cspHand
, GPK_Encode
, false, &passKey
);
359 ortn
= SecPkcs12SetMACPassKey(coder
, &passKey
);
361 printOsError("SecPkcs12SetMACPassKey", ortn
);
366 ortn
= SecPkcs12SetMACPassphrase(coder
, pwd
);
368 printOsError("SecPkcs12SetMACPassphrase", ortn
);
373 ortn
= SecPkcs12SetCspHandle(coder
, cspHand
);
375 printOsError("SecPkcs12SetCspHandle", ortn
);
379 /* the array of things we want to export */
380 CFMutableArrayRef items
= CFArrayCreateMutable(NULL
, 0, NULL
);
382 /* export from keychain specified by kcName */
383 SecKeychainRef kcRef
= NULL
;
384 ortn
= SecKeychainOpen(kcName
, &kcRef
);
386 printOsError("SecKeychainOpen", ortn
);
391 ortn
= SecKeychainUnlock(kcRef
, strlen(kcPwd
), (void *)kcPwd
, true);
393 printOsError("SecKeychainUnlock", ortn
);
398 * Prompt user for each known item - it would be nice if we
399 * could search for anything, eh?
402 SecKeychainSearchRef srchRef
;
403 ortn
= SecKeychainSearchCreateFromAttributes(kcRef
,
404 kSecCertificateItemClass
,
408 printOsError("SecKeychainSearchCreateFromAttributes", ortn
);
413 SecKeychainItemRef certRef
;
414 ortn
= SecKeychainSearchCopyNext(srchRef
, &certRef
);
418 exported
+= p12AddExportedItem(certRef
, items
, noPrompt
);
422 /* now private keys */
423 ortn
= SecKeychainSearchCreateFromAttributes(kcRef
,
424 CSSM_DL_DB_RECORD_PRIVATE_KEY
, // undocumented
428 printOsError("SecKeychainSearchCreateFromAttributes", ortn
);
432 SecKeychainItemRef keyRef
;
433 ortn
= SecKeychainSearchCopyNext(srchRef
, &keyRef
);
437 exported
+= p12AddExportedItem(keyRef
, items
, noPrompt
);
441 printf("...Hmmm, no items to export. Done.\n");
444 ortn
= SecPkcs12ExportKeychainItems(coder
, items
);
446 printOsError("SecPkcs12ExportKeychainItems", ortn
);
452 ortn
= SecPkcs12Encode(coder
, &pfx
);
454 printOsError("SecPkcs12ExportKeychainItems", ortn
);
458 if(writeFile(pfxFile
, CFDataGetBytePtr(pfx
),
459 CFDataGetLength(pfx
))) {
460 printf("***Error writing pfx to %s\n", pfxFile
);
463 printf("...%u items exported; %ld bytes written to %s\n",
464 exported
, CFDataGetLength(pfx
), pfxFile
);
467 SecPkcs12CoderRelease(coder
);