1/*
2 * multipurpose pkcs12 tool.
3 */
4#include <security_cdsa_utils/cuFileIo.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <CoreFoundation/CoreFoundation.h>
8#include "p12.h"
9#include <security_cdsa_utils/cuCdsaUtils.h>
10
11static void usage(char **argv)
12{
13	printf("Usage:\n");
14	printf("  %s p infile [options]    parse\n", argv[0]);
15	printf("  %s d infile [options]    decode\n", argv[0]);
16	printf("  %s e infile [options]    decode-->encode\n", argv[0]);
17	printf("  %s i infile keychain     import to keychain\n", argv[0]);
18	printf("  %s x outfile keychain    export from keychain\n", argv[0]);
19
20	printf("Options:\n");
21	printf("   p=password\n");
22	printf("   z=keychainPassword\n");
23	printf("   P (use secure passphrase)\n");
24	printf("   k=keychain\n");
25	printf("   l=loops\n");
26	printf("   n(o prompt; export only)\n");
27	printf("   v(erbose)\n");
28	/* others here */
29	exit(1);
30}
31
32typedef enum {
33	PR_Parse,
34	PR_Decode,
35	PR_Reencode,
36	PR_Import,
37	PR_Export
38} P12op;
39
40int main(int argc, char **argv)
41{
42	char *inFile;
43	P12op op;
44	int minArgs = 1;
45	CFStringRef pwd = NULL;
46	bool verbose = false;
47	unsigned loops = 1;
48	char *kcName = NULL;
49	bool noPrompt = false;
50	char *kcPwd = NULL;
51	bool usePassKey = false;
52
53	if(argc < 2) {
54		usage(argv);
55	}
56	switch(argv[1][0]) {
57		case 'p':
58			op = PR_Parse;
59			minArgs = 3;
60			break;
61		case 'd':
62			op = PR_Decode;
63			minArgs = 3;
64			break;
65		case 'e':
66			op = PR_Reencode;
67			minArgs = 3;
68			break;
69		case 'i':
70			op = PR_Import;
71			minArgs = 4;
72			break;
73		case 'x':
74			op = PR_Export;
75			minArgs = 4;
76			break;
77		default:
78			usage(argv);
79	}
80	if(argc < minArgs) {
81		usage(argv);
82	}
83	for(int arg=minArgs; arg<argc; arg++) {
84		char *argp = argv[arg];
85		switch(argp[0]) {
86			case 'p':
87				pwd = CFStringCreateWithCString(NULL, &argp[2],
88					kCFStringEncodingASCII);
89				break;
90			case 'k':
91				kcName = &argp[2];
92				break;
93			case 'P':
94				usePassKey = true;
95				break;
96			case 'v':
97				verbose = true;
98				break;
99			case 'n':
100				noPrompt = true;
101				break;
102			case 'l':
103				loops = atoi(&argp[2]);
104				break;
105			case 'z':
106				kcPwd = &argp[2];
107				break;
108			default:
109				usage(argv);
110
111		}
112	}
113
114	/* import/export - ready to go right now */
115	switch(op) {
116		case PR_Import:
117			return p12Import(argv[2], argv[3], pwd, usePassKey, kcPwd);
118		case PR_Export:
119			return p12Export(argv[2], argv[3], pwd, usePassKey, kcPwd, noPrompt);
120		default:
121			break;
122	}
123
124	/* all other ops: read infile */
125	inFile = argv[2];
126	CSSM_DATA rawBlob;
127	unsigned len;
128	if(readFile(inFile, &rawBlob.Data, &len)) {
129		printf("***Error reading %s. Aborting.\n", inFile);
130		exit(1);
131	}
132	rawBlob.Length = len;
133
134	CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE);
135	int rtn = 0;
136	switch(op) {
137		case PR_Decode:
138			rtn = p12Decode(rawBlob, cspHand, pwd, usePassKey, verbose, loops);
139			break;
140		case PR_Reencode:
141			rtn = p12Reencode(rawBlob, cspHand, pwd, verbose, loops);
142			break;
143		case PR_Parse:
144			rtn = p12ParseTop(rawBlob, cspHand, pwd, verbose);
145			break;
146		default:
147			/* NOT REACHED */
148			printf("GAK!\n");
149			rtn = -1;
150			break;
151	}
152	return rtn;
153}
154