]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/p12Reencode/p12Reencode.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / p12Reencode / p12Reencode.cpp
1 /*
2 * p12Reencode - take a p12 PFX, decode and reencode
3 */
4 #include <Security/SecImportExport.h>\ 1
5 #include <Security/Security.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <security_cdsa_utils/cuFileIo.h>
9 #include <utilLib/common.h>
10
11 static void usage(char **argv)
12 {
13 printf("Usage: %s pfx password keychain1 keychain2 [l=loops] [q(uiet)] "
14 "[v(erbose)]\n", argv[0]);
15 exit(1);
16 }
17
18
19 #define WRITE_BLOBS 0
20 #if WRITE_BLOBS
21 static void writeBlobs(CFDataRef pfx1, CFDataRef pfx2)
22 {
23 writeFile("pfx1.der", CFDataGetBytePtr(pfx1), CFDataGetLength(pfx1));
24 writeFile("pfx2.der", CFDataGetBytePtr(pfx2), CFDataGetLength(pfx2));
25 printf("...wrote %u bytes to pfx1.der, %u bytes to pfx2.der\n",
26 CFDataGetLength(pfx1), CFDataGetLength(pfx2));
27 }
28 #else
29 #define writeBlobs(p1, p2)
30 #endif
31
32 #if 0
33 /* Not possible using import/export API */
34 /* compare attrs, all of which are optional */
35 static int compareAttrs(
36 CFStringRef refFriendlyName,
37 CFDataRef refLocalKeyId,
38 CFStringRef testFriendlyName,
39 CFDataRef testLocalKeyId,
40 char *itemType,
41 CSSM_BOOL quiet)
42 {
43 if(refFriendlyName == NULL) {
44 if(testFriendlyName != NULL) {
45 printf("****s refFriendlyName NULL, testFriendlyName "
46 "non-NULL\n", itemType);
47 return testError(quiet);
48 }
49 }
50 else {
51 CFComparisonResult res = CFStringCompare(refFriendlyName,
52 testFriendlyName, 0);
53 if(res != kCFCompareEqualTo) {
54 printf("***%s friendlyName Miscompare\n", itemType);
55 return testError(quiet);
56 }
57 }
58
59 if(refLocalKeyId == NULL) {
60 if(testLocalKeyId != NULL) {
61 printf("****s refLocalKeyId NULL, testLocalKeyId "
62 "non-NULL\n", itemType);
63 return testError(quiet);
64 }
65 }
66 else {
67 if(compareCfData(refLocalKeyId, testLocalKeyId)) {
68 printf("***%s localKeyId Miscompare\n", itemType);
69 return testError(quiet);
70 }
71 }
72
73 /* release the attrs */
74 if(refFriendlyName) {
75 CFRelease(refFriendlyName);
76 }
77 if(refLocalKeyId) {
78 CFRelease(refLocalKeyId);
79 }
80 if(testFriendlyName) {
81 CFRelease(testFriendlyName);
82 }
83 if(testLocalKeyId) {
84 CFRelease(testLocalKeyId);
85 }
86 return 0;
87 }
88 #endif
89
90 static void setUpKeyParams(
91 SecKeyImportExportParameters &keyParams,
92 CFStringRef pwd)
93 {
94 memset(&keyParams, 0, sizeof(keyParams));
95 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
96 keyParams.passphrase = pwd;
97 }
98
99 /*
100 * Basic import/export: convert between CFArray of keychain items and a CFDataRef
101 */
102 static OSStatus p12Import(
103 CFDataRef pfx,
104 CFStringRef pwd,
105 SecKeychainRef kcRef,
106 CFArrayRef *outArray)
107 {
108 SecKeyImportExportParameters keyParams;
109 setUpKeyParams(keyParams, pwd);
110 OSStatus ortn;
111 SecExternalFormat format = kSecFormatPKCS12;
112
113 ortn = SecKeychainItemImport(pfx, NULL, &format, NULL, 0, &keyParams,
114 kcRef, outArray);
115 if(ortn) {
116 cssmPerror("SecKeychainItemImport", ortn);
117 }
118 return ortn;
119 }
120
121 static OSStatus p12Export(
122 CFArrayRef inArray,
123 CFStringRef pwd,
124 CFDataRef *pfx)
125 {
126 SecKeyImportExportParameters keyParams;
127 setUpKeyParams(keyParams, pwd);
128 OSStatus ortn;
129
130 ortn = SecKeychainItemExport(inArray, kSecFormatPKCS12, 0, &keyParams, pfx);
131 if(ortn) {
132 cssmPerror("SecKeychainItemExport", ortn);
133 }
134 return ortn;
135 }
136
137 /*
138 * Compare two CFArrayRefs containing various items, subsequent to decode. Returns
139 * nonzero if they differ.
140 *
141 * As of April 9 2004, we do NOT see CRLs so we don't compare them. I think
142 * we need a SecCRLRef...
143 */
144 static int compareDecodedArrays(
145 CFArrayRef refArray,
146 CFArrayRef testArray,
147 CSSM_BOOL quiet)
148 {
149 OSStatus ortn;
150 int ourRtn = 0;
151
152 CFIndex numRefItems = CFArrayGetCount(refArray);
153 CFIndex numTestItems = CFArrayGetCount(testArray);
154 if(numRefItems != numTestItems) {
155 printf("***item count mismatch: ref %ld test %ld\n",
156 numRefItems, numTestItems);
157 return 1;
158 }
159 for(CFIndex dex=0; dex<numRefItems; dex++) {
160 CFTypeRef refItem = CFArrayGetValueAtIndex(refArray, dex);
161 CFTypeRef testItem = CFArrayGetValueAtIndex(testArray, dex);
162 CFTypeID theType = CFGetTypeID(refItem);
163 if(theType != CFGetTypeID(testItem)) {
164 printf("***item type mismatch: ref %ld test %ld\n",
165 theType, CFGetTypeID(testItem));
166 return 1;
167 }
168 if(theType == SecCertificateGetTypeID()) {
169 /* cert: compare raw data */
170 CSSM_DATA refData;
171 CSSM_DATA testData;
172 ortn = SecCertificateGetData((SecCertificateRef)refItem, &refData);
173 if(ortn) {
174 cssmPerror("SecCertificateGetData", ortn);
175 return ++ourRtn;
176 }
177 ortn = SecCertificateGetData((SecCertificateRef)testItem, &testData);
178 if(ortn) {
179 cssmPerror("SecCertificateGetData", ortn);
180 return ++ourRtn;
181 }
182 if(!appCompareCssmData(&refData, &testData)) {
183 printf("***Data miscompare on cert %ld\n", dex);
184 ourRtn = testError(quiet);
185 if(ourRtn) {
186 return ourRtn;
187 }
188 }
189 }
190 else if(theType == SecKeyGetTypeID()) {
191 /* Keys - an inexact science to be sure since we don't attempt
192 * to access the raw key material */
193
194 const CSSM_KEY *refKey;
195 ortn = SecKeyGetCSSMKey((SecKeyRef)refItem, &refKey);
196 if(ortn) {
197 cssmPerror("SecKeyGetCSSMKey", ortn);
198 return ++ourRtn;
199 }
200 const CSSM_KEY *testKey;
201 ortn = SecKeyGetCSSMKey((SecKeyRef)testItem, &testKey);
202 if(ortn) {
203 cssmPerror("SecPkcs12GetCssmPrivateKey", ortn);
204 return ++ourRtn;
205 }
206
207 /* compare key sizes and algorithm */
208 if(refKey->KeyHeader.LogicalKeySizeInBits !=
209 testKey->KeyHeader.LogicalKeySizeInBits) {
210 printf("***Key size miscompare on Key %ld\n", dex);
211 ourRtn = testError(quiet);
212 if(ourRtn) {
213 return ourRtn;
214 }
215 }
216 if(refKey->KeyHeader.AlgorithmId !=
217 testKey->KeyHeader.AlgorithmId) {
218 printf("***AlgorithmId miscompare on Key %ld\n", dex);
219 ourRtn = testError(quiet);
220 if(ourRtn) {
221 return ourRtn;
222 }
223 }
224 }
225 else {
226 /* this program may need work here. e.g. for SecCRLRefs */
227 printf("***Unknown type ID (%ld)\n", theType);
228 ourRtn++;
229 }
230 }
231
232 return ourRtn;
233 }
234
235 int main(int argc, char **argv)
236 {
237 unsigned char *pfx;
238 unsigned pfxLen;
239 SecKeychainRef kcRef1 = nil; // reference, 1st import destination
240 SecKeychainRef kcRef2 = nil; // subsequent import destination
241
242 CSSM_BOOL quiet = CSSM_FALSE;
243 unsigned loops = 10;
244 bool verbose = false;
245 bool doPause = false;
246 char *kcName = NULL;
247
248 int i;
249
250 if(argc < 5) {
251 usage(argv);
252 }
253
254 if(readFile(argv[1], &pfx, &pfxLen)) {
255 printf("***Error reading PFX from %s. Aborting.\n", argv[1]);
256 exit(1);
257 }
258 CFStringRef pwd = CFStringCreateWithCString(NULL, argv[2],
259 kCFStringEncodingASCII);
260 if(pwd == NULL) {
261 printf("Bad password (%s)\n", argv[2]);
262 exit(1);
263 }
264 kcName = argv[3];
265 OSStatus ortn = SecKeychainOpen(kcName, &kcRef1);
266 if(ortn) {
267 cssmPerror("SecKeychainOpen", ortn);
268 exit(1);
269 }
270 kcName = argv[4];
271 ortn = SecKeychainOpen(kcName, &kcRef2);
272 if(ortn) {
273 cssmPerror("SecKeychainOpen", ortn);
274 exit(1);
275 }
276
277 for(i=5; i<argc; i++) {
278 char *arg = argv[i];
279 switch(arg[0]) {
280 case 'l':
281 loops = atoi(&arg[2]);
282 break;
283 case 'q':
284 quiet = CSSM_TRUE;
285 break;
286 case 'p':
287 doPause = true;
288 break;
289 case 'v':
290 verbose = true;
291 break;
292 default:
293 usage(argv);
294 }
295 }
296
297 /* do first decode to get the PFX into "our" form */
298 CFArrayRef refArray;
299 CFDataRef cfdPfx = CFDataCreate(NULL, pfx, pfxLen);
300
301 if(verbose) {
302 printf(" ...initial decode\n");
303 }
304 ortn = p12Import(cfdPfx, pwd, kcRef1, &refArray);
305 if(ortn) {
306 printf("Error on initial p12Import; aborting.\n");
307 exit(1);
308 }
309
310 /* reencode. At this point the PFXs will not be identical since
311 * everyone packages these up a little differently. */
312 CFDataRef refPfx = NULL;
313 if(verbose) {
314 printf(" ...first reencode\n");
315 }
316 ortn = p12Export(refArray, pwd, &refPfx);
317 if(ortn) {
318 printf("Error on initial p12Export; aborting.\n");
319 exit(1);
320 }
321 CFDataRef pfxToDecode = refPfx;
322 CFRetain(pfxToDecode);
323
324 for(unsigned loop=0; loop<loops; loop++) {
325 if(!quiet) {
326 printf("..loop %u\n", loop);
327 }
328 CFArrayRef testArray;
329 if(verbose) {
330 printf(" ...decode\n");
331 }
332 ortn = p12Import(pfxToDecode, pwd, kcRef2, &testArray);
333 if(ortn) {
334 return ortn;
335 }
336
337 /*
338 * Compare that decode to our original
339 */
340 if(compareDecodedArrays(refArray, testArray, quiet)) {
341 exit(1);
342 }
343
344 /* now reencode, should get blob with same length but different
345 * data (because salt is random each time) */
346 CFDataRef newPfx = NULL;
347 if(verbose) {
348 printf(" ...reencode\n");
349 }
350 ortn = p12Export(testArray, pwd, &newPfx);
351 if(ortn) {
352 exit(1);
353 }
354
355 if(CFDataGetLength(refPfx) != CFDataGetLength(newPfx)) {
356 printf("***PFX length miscompare after reencode\n");
357 writeBlobs(refPfx, newPfx);
358 return 1;
359 }
360 if(!memcmp(CFDataGetBytePtr(refPfx), CFDataGetBytePtr(newPfx),
361 CFDataGetLength(refPfx))) {
362 printf("***Unexpected PFX data compare after reencode\n");
363 writeBlobs(refPfx, newPfx);
364 return 1;
365 }
366 CFRelease(pfxToDecode);
367 pfxToDecode = newPfx;
368 if(doPause) {
369 fpurge(stdin);
370 printf("Hit CR to continue: ");
371 getchar();
372 }
373
374 /* delete everything we imported into kcRef2 */
375 CFIndex numItems = CFArrayGetCount(testArray);
376 for(CFIndex dex=0; dex<numItems; dex++) {
377 SecKeychainItemRef itemRef =
378 (SecKeychainItemRef)CFArrayGetValueAtIndex(refArray, dex);
379 ortn = SecKeychainItemDelete(itemRef);
380 if(ortn) {
381 cssmPerror("SecKeychainItemDelete", ortn);
382 /*
383 * keep going, but if we're looping this will result in a dup
384 * item error on the next import
385 */
386 }
387 }
388 CFRelease(testArray);
389 }
390 if(!quiet) {
391 printf("...p12Reencode complete\n");
392 }
393 return ortn;
394 }
395