p12.cpp   [plain text]


/*
 * multipurpose pkcs12 tool. 
 */
#include <security_cdsa_utils/cuFileIo.h>
#include <stdlib.h>
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include "p12.h"
#include <security_cdsa_utils/cuCdsaUtils.h>

static void usage(char **argv)
{
	printf("Usage:\n");
	printf("  %s p infile [options]    parse\n", argv[0]);
	printf("  %s d infile [options]    decode\n", argv[0]);
	printf("  %s e infile [options]    decode-->encode\n", argv[0]);
	printf("  %s i infile keychain     import to keychain\n", argv[0]);
	printf("  %s x outfile keychain    export from keychain\n", argv[0]);
	
	printf("Options:\n");
	printf("   p=password\n");
	printf("   z=keychainPassword\n");
	printf("   P (use secure passphrase)\n");
	printf("   k=keychain\n");
	printf("   l=loops\n");
	printf("   n(o prompt; export only)\n");
	printf("   v(erbose)\n");
	/* others here */
	exit(1);
}

typedef enum {
	PR_Parse,
	PR_Decode,
	PR_Reencode,
	PR_Import,
	PR_Export
} P12op;

int main(int argc, char **argv)
{	
	char *inFile;
	P12op op;
	int minArgs = 1;
	CFStringRef pwd = NULL;
	bool verbose = false;
	unsigned loops = 1;
	char *kcName = NULL;
	bool noPrompt = false;
	char *kcPwd = NULL;
	bool usePassKey = false;
	
	if(argc < 2) {
		usage(argv);
	}
	switch(argv[1][0]) {
		case 'p':
			op = PR_Parse;
			minArgs = 3;
			break;
		case 'd':
			op = PR_Decode;
			minArgs = 3;
			break;
		case 'e':
			op = PR_Reencode;
			minArgs = 3;
			break;
		case 'i':
			op = PR_Import;
			minArgs = 4;
			break;
		case 'x':
			op = PR_Export;
			minArgs = 4;
			break;
		default:
			usage(argv);
	}
	if(argc < minArgs) {
		usage(argv);
	}
	for(int arg=minArgs; arg<argc; arg++) {
		char *argp = argv[arg];
		switch(argp[0]) {
			case 'p':
				pwd = CFStringCreateWithCString(NULL, &argp[2],
					kCFStringEncodingASCII);
				break;
			case 'k':
				kcName = &argp[2];
				break;
			case 'P':
				usePassKey = true;
				break;
			case 'v':
				verbose = true;
				break;
			case 'n':
				noPrompt = true;
				break;
			case 'l':
				loops = atoi(&argp[2]);
				break;
			case 'z':
				kcPwd = &argp[2];
				break;
			default:
				usage(argv);

		}
	}
	
	/* import/export - ready to go right now */
	switch(op) {
		case PR_Import:
			return p12Import(argv[2], argv[3], pwd, usePassKey, kcPwd);
		case PR_Export:
			return p12Export(argv[2], argv[3], pwd, usePassKey, kcPwd, noPrompt);
		default:
			break;
	}
	
	/* all other ops: read infile */
	inFile = argv[2];	
	CSSM_DATA rawBlob;
	unsigned len;
	if(readFile(inFile, &rawBlob.Data, &len)) {
		printf("***Error reading %s. Aborting.\n", inFile);
		exit(1);
	}
	rawBlob.Length = len;
	
	CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE);
	int rtn = 0;
	switch(op) {
		case PR_Decode:
			rtn = p12Decode(rawBlob, cspHand, pwd, usePassKey, verbose, loops);
			break;
		case PR_Reencode:
			rtn = p12Reencode(rawBlob, cspHand, pwd, verbose, loops);
			break;
		case PR_Parse:
			rtn = p12ParseTop(rawBlob, cspHand, pwd, verbose);
			break;
		default:
			/* NOT REACHED */
			printf("GAK!\n");
			rtn = -1;
			break;
	}
	return rtn;
}