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
);