+++ /dev/null
-/*
- * p12Reencode - take a p12 PFX, decode and reencode
- */
-#include <Security/SecImportExport.h>\ 1
-#include <Security/Security.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <utilLib/common.h>
-
-static void usage(char **argv)
-{
- printf("Usage: %s pfx password keychain1 keychain2 [l=loops] [q(uiet)] "
- "[v(erbose)]\n", argv[0]);
- exit(1);
-}
-
-
-#define WRITE_BLOBS 0
-#if WRITE_BLOBS
-static void writeBlobs(CFDataRef pfx1, CFDataRef pfx2)
-{
- writeFile("pfx1.der", CFDataGetBytePtr(pfx1), CFDataGetLength(pfx1));
- writeFile("pfx2.der", CFDataGetBytePtr(pfx2), CFDataGetLength(pfx2));
- printf("...wrote %u bytes to pfx1.der, %u bytes to pfx2.der\n",
- CFDataGetLength(pfx1), CFDataGetLength(pfx2));
-}
-#else
-#define writeBlobs(p1, p2)
-#endif
-
-#if 0
-/* Not possible using import/export API */
-/* compare attrs, all of which are optional */
-static int compareAttrs(
- CFStringRef refFriendlyName,
- CFDataRef refLocalKeyId,
- CFStringRef testFriendlyName,
- CFDataRef testLocalKeyId,
- char *itemType,
- CSSM_BOOL quiet)
-{
- if(refFriendlyName == NULL) {
- if(testFriendlyName != NULL) {
- printf("****s refFriendlyName NULL, testFriendlyName "
- "non-NULL\n", itemType);
- return testError(quiet);
- }
- }
- else {
- CFComparisonResult res = CFStringCompare(refFriendlyName,
- testFriendlyName, 0);
- if(res != kCFCompareEqualTo) {
- printf("***%s friendlyName Miscompare\n", itemType);
- return testError(quiet);
- }
- }
-
- if(refLocalKeyId == NULL) {
- if(testLocalKeyId != NULL) {
- printf("****s refLocalKeyId NULL, testLocalKeyId "
- "non-NULL\n", itemType);
- return testError(quiet);
- }
- }
- else {
- if(compareCfData(refLocalKeyId, testLocalKeyId)) {
- printf("***%s localKeyId Miscompare\n", itemType);
- return testError(quiet);
- }
- }
-
- /* release the attrs */
- if(refFriendlyName) {
- CFRelease(refFriendlyName);
- }
- if(refLocalKeyId) {
- CFRelease(refLocalKeyId);
- }
- if(testFriendlyName) {
- CFRelease(testFriendlyName);
- }
- if(testLocalKeyId) {
- CFRelease(testLocalKeyId);
- }
- return 0;
-}
-#endif
-
-static void setUpKeyParams(
- SecKeyImportExportParameters &keyParams,
- CFStringRef pwd)
-{
- memset(&keyParams, 0, sizeof(keyParams));
- keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- keyParams.passphrase = pwd;
-}
-
-/*
- * Basic import/export: convert between CFArray of keychain items and a CFDataRef
- */
-static OSStatus p12Import(
- CFDataRef pfx,
- CFStringRef pwd,
- SecKeychainRef kcRef,
- CFArrayRef *outArray)
-{
- SecKeyImportExportParameters keyParams;
- setUpKeyParams(keyParams, pwd);
- OSStatus ortn;
- SecExternalFormat format = kSecFormatPKCS12;
-
- ortn = SecKeychainItemImport(pfx, NULL, &format, NULL, 0, &keyParams,
- kcRef, outArray);
- if(ortn) {
- cssmPerror("SecKeychainItemImport", ortn);
- }
- return ortn;
-}
-
-static OSStatus p12Export(
- CFArrayRef inArray,
- CFStringRef pwd,
- CFDataRef *pfx)
-{
- SecKeyImportExportParameters keyParams;
- setUpKeyParams(keyParams, pwd);
- OSStatus ortn;
-
- ortn = SecKeychainItemExport(inArray, kSecFormatPKCS12, 0, &keyParams, pfx);
- if(ortn) {
- cssmPerror("SecKeychainItemExport", ortn);
- }
- return ortn;
-}
-
-/*
- * Compare two CFArrayRefs containing various items, subsequent to decode. Returns
- * nonzero if they differ.
- *
- * As of April 9 2004, we do NOT see CRLs so we don't compare them. I think
- * we need a SecCRLRef...
- */
-static int compareDecodedArrays(
- CFArrayRef refArray,
- CFArrayRef testArray,
- CSSM_BOOL quiet)
-{
- OSStatus ortn;
- int ourRtn = 0;
-
- CFIndex numRefItems = CFArrayGetCount(refArray);
- CFIndex numTestItems = CFArrayGetCount(testArray);
- if(numRefItems != numTestItems) {
- printf("***item count mismatch: ref %ld test %ld\n",
- numRefItems, numTestItems);
- return 1;
- }
- for(CFIndex dex=0; dex<numRefItems; dex++) {
- CFTypeRef refItem = CFArrayGetValueAtIndex(refArray, dex);
- CFTypeRef testItem = CFArrayGetValueAtIndex(testArray, dex);
- CFTypeID theType = CFGetTypeID(refItem);
- if(theType != CFGetTypeID(testItem)) {
- printf("***item type mismatch: ref %ld test %ld\n",
- theType, CFGetTypeID(testItem));
- return 1;
- }
- if(theType == SecCertificateGetTypeID()) {
- /* cert: compare raw data */
- CSSM_DATA refData;
- CSSM_DATA testData;
- ortn = SecCertificateGetData((SecCertificateRef)refItem, &refData);
- if(ortn) {
- cssmPerror("SecCertificateGetData", ortn);
- return ++ourRtn;
- }
- ortn = SecCertificateGetData((SecCertificateRef)testItem, &testData);
- if(ortn) {
- cssmPerror("SecCertificateGetData", ortn);
- return ++ourRtn;
- }
- if(!appCompareCssmData(&refData, &testData)) {
- printf("***Data miscompare on cert %ld\n", dex);
- ourRtn = testError(quiet);
- if(ourRtn) {
- return ourRtn;
- }
- }
- }
- else if(theType == SecKeyGetTypeID()) {
- /* Keys - an inexact science to be sure since we don't attempt
- * to access the raw key material */
-
- const CSSM_KEY *refKey;
- ortn = SecKeyGetCSSMKey((SecKeyRef)refItem, &refKey);
- if(ortn) {
- cssmPerror("SecKeyGetCSSMKey", ortn);
- return ++ourRtn;
- }
- const CSSM_KEY *testKey;
- ortn = SecKeyGetCSSMKey((SecKeyRef)testItem, &testKey);
- if(ortn) {
- cssmPerror("SecPkcs12GetCssmPrivateKey", ortn);
- return ++ourRtn;
- }
-
- /* compare key sizes and algorithm */
- if(refKey->KeyHeader.LogicalKeySizeInBits !=
- testKey->KeyHeader.LogicalKeySizeInBits) {
- printf("***Key size miscompare on Key %ld\n", dex);
- ourRtn = testError(quiet);
- if(ourRtn) {
- return ourRtn;
- }
- }
- if(refKey->KeyHeader.AlgorithmId !=
- testKey->KeyHeader.AlgorithmId) {
- printf("***AlgorithmId miscompare on Key %ld\n", dex);
- ourRtn = testError(quiet);
- if(ourRtn) {
- return ourRtn;
- }
- }
- }
- else {
- /* this program may need work here. e.g. for SecCRLRefs */
- printf("***Unknown type ID (%ld)\n", theType);
- ourRtn++;
- }
- }
-
- return ourRtn;
-}
-
-int main(int argc, char **argv)
-{
- unsigned char *pfx;
- unsigned pfxLen;
- SecKeychainRef kcRef1 = nil; // reference, 1st import destination
- SecKeychainRef kcRef2 = nil; // subsequent import destination
-
- CSSM_BOOL quiet = CSSM_FALSE;
- unsigned loops = 10;
- bool verbose = false;
- bool doPause = false;
- char *kcName = NULL;
-
- int i;
-
- if(argc < 5) {
- usage(argv);
- }
-
- if(readFile(argv[1], &pfx, &pfxLen)) {
- printf("***Error reading PFX from %s. Aborting.\n", argv[1]);
- exit(1);
- }
- CFStringRef pwd = CFStringCreateWithCString(NULL, argv[2],
- kCFStringEncodingASCII);
- if(pwd == NULL) {
- printf("Bad password (%s)\n", argv[2]);
- exit(1);
- }
- kcName = argv[3];
- OSStatus ortn = SecKeychainOpen(kcName, &kcRef1);
- if(ortn) {
- cssmPerror("SecKeychainOpen", ortn);
- exit(1);
- }
- kcName = argv[4];
- ortn = SecKeychainOpen(kcName, &kcRef2);
- if(ortn) {
- cssmPerror("SecKeychainOpen", ortn);
- exit(1);
- }
-
- for(i=5; i<argc; i++) {
- char *arg = argv[i];
- switch(arg[0]) {
- case 'l':
- loops = atoi(&arg[2]);
- break;
- case 'q':
- quiet = CSSM_TRUE;
- break;
- case 'p':
- doPause = true;
- break;
- case 'v':
- verbose = true;
- break;
- default:
- usage(argv);
- }
- }
-
- /* do first decode to get the PFX into "our" form */
- CFArrayRef refArray;
- CFDataRef cfdPfx = CFDataCreate(NULL, pfx, pfxLen);
-
- if(verbose) {
- printf(" ...initial decode\n");
- }
- ortn = p12Import(cfdPfx, pwd, kcRef1, &refArray);
- if(ortn) {
- printf("Error on initial p12Import; aborting.\n");
- exit(1);
- }
-
- /* reencode. At this point the PFXs will not be identical since
- * everyone packages these up a little differently. */
- CFDataRef refPfx = NULL;
- if(verbose) {
- printf(" ...first reencode\n");
- }
- ortn = p12Export(refArray, pwd, &refPfx);
- if(ortn) {
- printf("Error on initial p12Export; aborting.\n");
- exit(1);
- }
- CFDataRef pfxToDecode = refPfx;
- CFRetain(pfxToDecode);
-
- for(unsigned loop=0; loop<loops; loop++) {
- if(!quiet) {
- printf("..loop %u\n", loop);
- }
- CFArrayRef testArray;
- if(verbose) {
- printf(" ...decode\n");
- }
- ortn = p12Import(pfxToDecode, pwd, kcRef2, &testArray);
- if(ortn) {
- return ortn;
- }
-
- /*
- * Compare that decode to our original
- */
- if(compareDecodedArrays(refArray, testArray, quiet)) {
- exit(1);
- }
-
- /* now reencode, should get blob with same length but different
- * data (because salt is random each time) */
- CFDataRef newPfx = NULL;
- if(verbose) {
- printf(" ...reencode\n");
- }
- ortn = p12Export(testArray, pwd, &newPfx);
- if(ortn) {
- exit(1);
- }
-
- if(CFDataGetLength(refPfx) != CFDataGetLength(newPfx)) {
- printf("***PFX length miscompare after reencode\n");
- writeBlobs(refPfx, newPfx);
- return 1;
- }
- if(!memcmp(CFDataGetBytePtr(refPfx), CFDataGetBytePtr(newPfx),
- CFDataGetLength(refPfx))) {
- printf("***Unexpected PFX data compare after reencode\n");
- writeBlobs(refPfx, newPfx);
- return 1;
- }
- CFRelease(pfxToDecode);
- pfxToDecode = newPfx;
- if(doPause) {
- fpurge(stdin);
- printf("Hit CR to continue: ");
- getchar();
- }
-
- /* delete everything we imported into kcRef2 */
- CFIndex numItems = CFArrayGetCount(testArray);
- for(CFIndex dex=0; dex<numItems; dex++) {
- SecKeychainItemRef itemRef =
- (SecKeychainItemRef)CFArrayGetValueAtIndex(refArray, dex);
- ortn = SecKeychainItemDelete(itemRef);
- if(ortn) {
- cssmPerror("SecKeychainItemDelete", ortn);
- /*
- * keep going, but if we're looping this will result in a dup
- * item error on the next import
- */
- }
- }
- CFRelease(testArray);
- }
- if(!quiet) {
- printf("...p12Reencode complete\n");
- }
- return ortn;
-}
-