]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/extendAttrTest/extendAttrTest.cpp
Security-57031.30.12.tar.gz
[apple/security.git] / SecurityTests / clxutils / extendAttrTest / extendAttrTest.cpp
1 /*
2 * extendAttrTest.cpp
3 */
4
5 #include <stdlib.h>
6 #include <strings.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <Security/SecKeychainItemExtendedAttributes.h>
10 #include <Security/Security.h>
11 #include <security_cdsa_utils/cuFileIo.h>
12 #include <utilLib/common.h>
13
14 #define DEFAULT_KC_NAME "extendAttr.keychain"
15
16 static void usage(char **argv)
17 {
18 printf("usage: %s [options]\n", argv[0]);
19 printf("Options:\n");
20 printf(" -k keychain -- default is %s\n", DEFAULT_KC_NAME);
21 printf(" -n -- don't delete attributes or keychain\n");
22 printf(" -q -- quiet\n");
23 exit(1);
24 }
25
26 /* RSA keys, both in OpenSSL format */
27 #define PUB_KEY "rsakey_pub.der"
28 #define PRIV_KEY "rsakey_priv.der"
29 #define CERT_FILE "amazon_v3.100.cer"
30 #define PWD_SERVICE "some service"
31 #define PWD_ACCOUNT "some account"
32 #define PWD_PWD "some password"
33
34 /* set up unique extended attributes for each tested item */
35 typedef struct {
36 CFStringRef attr1Name;
37 const char *attr1Value;
38 CFStringRef attr2Name;
39 const char *attr2Value;
40 } ItemAttrs;
41
42 static const ItemAttrs pubKeyAttrs = {
43 CFSTR("one pub key Attribute"),
44 "some pub key value",
45 CFSTR("another pub key Attribute"),
46 "another pub key value"
47 };
48
49 static const ItemAttrs privKeyAttrs = {
50 CFSTR("one priv key Attribute"),
51 "some priv key value",
52 CFSTR("another priv key Attribute"),
53 "another priv key value"
54 };
55
56 static const ItemAttrs certAttrs = {
57 CFSTR("one cert Attribute"),
58 "some cert value",
59 CFSTR("another cert Attribute"),
60 "another cert value"
61 };
62
63 static const ItemAttrs pwdAttrs = {
64 CFSTR("one pwd Attribute"),
65 "some pwd value",
66 CFSTR("another pwd Attribute"),
67 "another pwd value"
68 };
69
70 #define CFRELEASE(cf) if(cf) { CFRelease(cf); }
71
72 /* import file as key into specified keychain */
73 static int doImportKey(
74 const char *fileName,
75 SecExternalFormat format,
76 SecExternalItemType itemType,
77 SecKeychainRef kcRef,
78 SecKeyRef *keyRef) // RETURNED
79 {
80 unsigned char *item = NULL;
81 unsigned itemLen = 0;
82
83 if(readFile(fileName, &item, &itemLen)) {
84 printf("***Error reading %s. \n", fileName);
85 }
86 CFDataRef cfd = CFDataCreate(NULL, (const UInt8 *)item, itemLen);
87 free(item);
88 SecKeyImportExportParameters params;
89 memset(&params, 0, sizeof(params));
90 params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
91 params.keyUsage = CSSM_KEYUSE_ANY;
92 params.keyAttributes = CSSM_KEYATTR_PERMANENT;
93 if(itemType == kSecItemTypePrivateKey) {
94 params.keyAttributes |= CSSM_KEYATTR_SENSITIVE;
95 }
96 CFArrayRef outArray = NULL;
97 OSStatus ortn;
98 ortn = SecKeychainItemImport(cfd, NULL, &format, &itemType, 0, &params, kcRef, &outArray);
99 if(ortn) {
100 cssmPerror("SecKeychainItemImport", ortn);
101 }
102 CFRelease(cfd);
103 if(ortn) {
104 return -1;
105 }
106 if((outArray == NULL) || (CFArrayGetCount(outArray) == 0)) {
107 printf("SecKeychainItemImport succeeded, but no returned items\n");
108 return -1;
109 }
110 *keyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0);
111 if(CFGetTypeID(*keyRef) != SecKeyGetTypeID()) {
112 printf("***Unknown type returned after import\n");
113 return -1;
114 }
115 CFRetain(*keyRef);
116 CFRelease(outArray);
117 return 0;
118 }
119
120 /* import file as cert into specified keychain */
121 static int doImportCert(
122 const char *fileName,
123 SecKeychainRef kcRef,
124 SecCertificateRef *certRef) // RETURNED
125 {
126 unsigned char *item = NULL;
127 unsigned itemLen = 0;
128
129 if(readFile(fileName, &item, &itemLen)) {
130 printf("***Error reading %s. \n", fileName);
131 return -1;
132 }
133 CSSM_DATA certData = {itemLen, (uint8 *)item};
134 OSStatus ortn = SecCertificateCreateFromData(&certData,
135 CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, certRef);
136 if(ortn) {
137 cssmPerror("SecCertificateCreateFromData", ortn);
138 return -1;
139 }
140 ortn = SecCertificateAddToKeychain(*certRef, kcRef);
141 if(ortn) {
142 cssmPerror("SecCertificateAddToKeychain", ortn);
143 return -1;
144 }
145 return 0;
146 }
147
148 /*
149 * Verify specified attr does not exist
150 * set it
151 * make sure we get it back
152 */
153 int testOneAttr(
154 SecKeychainItemRef itemRef,
155 CFStringRef attrName,
156 CFDataRef attrVal,
157 bool quiet)
158 {
159 OSStatus ortn;
160 CFDataRef fetchedVal = NULL;
161 int ourRtn = 0;
162
163 if(!quiet) {
164 printf(" ...verifying attribute doesn't exist\n");
165 }
166 ortn = SecKeychainItemCopyExtendedAttribute(itemRef, attrName, &fetchedVal);
167 if(ortn != errSecNoSuchAttr) {
168 printf("***First SecKeychainItemCopyExtendedAttribute returned %d, expected %d\n",
169 (int)ortn, (int)errSecNoSuchAttr);
170 ourRtn = -1;
171 goto errOut;
172 }
173 if(!quiet) {
174 printf(" ...setting attribute\n");
175 }
176 ortn = SecKeychainItemSetExtendedAttribute(itemRef, attrName, attrVal);
177 if(ortn) {
178 cssmPerror("SecKeychainItemSetExtendedAttribute", ortn);
179 ourRtn = -1;
180 goto errOut;
181 }
182 if(!quiet) {
183 printf(" ...verify attribute\n");
184 }
185 ortn = SecKeychainItemCopyExtendedAttribute(itemRef, attrName, &fetchedVal);
186 if(ortn) {
187 cssmPerror("SecKeychainItemCopyExtendedAttribute", ortn);
188 ourRtn = -1;
189 goto errOut;
190 }
191 if(!CFEqual(fetchedVal, attrVal)) {
192 printf("***Mismatch in set and fetched attribute\n");
193 ourRtn = -1;
194 }
195 errOut:
196 CFRELEASE(fetchedVal);
197 return ourRtn;
198 }
199
200 /*
201 * Set two distinct extended attributes;
202 * Ensure that each comes back via SecKeychainItemCopyExtendedAttribute();
203 * Ensure that both come back via SecKeychainItemCopyAllExtendedAttributes();
204 */
205 int doTest(SecKeychainItemRef itemRef,
206 const ItemAttrs &itemAttrs,
207 bool quiet)
208 {
209 CFDataRef attrVal1 = CFDataCreate(NULL,
210 (const UInt8 *)itemAttrs.attr1Value, strlen(itemAttrs.attr1Value));
211 if(testOneAttr(itemRef, itemAttrs.attr1Name, attrVal1, quiet)) {
212 return -1;
213 }
214 CFDataRef attrVal2 = CFDataCreate(NULL,
215 (const UInt8 *)itemAttrs.attr2Value, strlen(itemAttrs.attr2Value));
216 if(testOneAttr(itemRef, itemAttrs.attr2Name, attrVal2, quiet)) {
217 return -1;
218 }
219
220 if(!quiet) {
221 printf(" ...verify both attributes via CopyAllExtendedAttributes()\n");
222 }
223 /* make sure they both come back in SecKeychainItemCopyAllExtendedAttributes */
224 CFArrayRef attrNames = NULL;
225 CFArrayRef attrValues = NULL;
226 OSStatus ortn = SecKeychainItemCopyAllExtendedAttributes(itemRef, &attrNames, &attrValues);
227 if(ortn) {
228 cssmPerror("SecKeychainItemCopyAllExtendedAttributes", ortn);
229 return -1;
230 }
231 CFIndex numNames = CFArrayGetCount(attrNames);
232 CFIndex numValues = CFArrayGetCount(attrValues);
233 if((numNames != 2) || (numValues != 2)) {
234 printf("***Bad array count after SecKeychainItemCopyAllExtendedAttributes\n");
235 printf(" numNames %ld numValues %ld; expected 2 for both\n",
236 (long)numNames, (long)numValues);
237 return -1;
238 }
239 bool found1 = false;
240 bool found2 = false;
241 for(CFIndex dex=0; dex<numNames; dex++) {
242 CFStringRef attrName = (CFStringRef)CFArrayGetValueAtIndex(attrNames, dex);
243 CFDataRef valToCompare = NULL;
244 if(CFEqual(attrName, itemAttrs.attr1Name)) {
245 found1 = true;
246 valToCompare = attrVal1;
247 }
248 else if(CFEqual(attrName, itemAttrs.attr2Name)) {
249 found2 = true;
250 valToCompare = attrVal2;
251 }
252 else {
253 printf("***Found unknown attribute name\n");
254 return -1;
255 }
256 CFDataRef foundVal = (CFDataRef)CFArrayGetValueAtIndex(attrValues, dex);
257 if(!CFEqual(foundVal, valToCompare)) {
258 printf("***Attribute Value miscompare\n");
259 return -1;
260 }
261 }
262 CFRelease(attrNames);
263 CFRelease(attrValues);
264 CFRelease(attrVal1);
265 CFRelease(attrVal2);
266
267 if(!found1 || !found2) {
268 printf("***wrote two attribute; found1 %s, found2 %s\n",
269 found1 ? "true" : "false", found2 ? "true" : "false");
270 return 1;
271 }
272
273 return 0;
274 }
275
276 /* delete two attrs, verify that none are left */
277 static int doDeleteTest(
278 SecKeychainItemRef itemRef,
279 const ItemAttrs &itemAttrs,
280 bool quiet)
281 {
282 if(!quiet) {
283 printf(" ...deleting both attributes, verifying none are left\n");
284 }
285
286 OSStatus ortn = SecKeychainItemSetExtendedAttribute(itemRef, itemAttrs.attr1Name, NULL);
287 if(ortn) {
288 cssmPerror("SecKeychainItemSetExtendedAttribute (NULL)", ortn);
289 return -1;
290 }
291 ortn = SecKeychainItemSetExtendedAttribute(itemRef, itemAttrs.attr2Name, NULL);
292 if(ortn) {
293 cssmPerror("SecKeychainItemSetExtendedAttribute (NULL)", ortn);
294 return -1;
295 }
296 CFArrayRef attrNames = NULL;
297 CFArrayRef attrValues = NULL;
298 ortn = SecKeychainItemCopyAllExtendedAttributes(itemRef, &attrNames, &attrValues);
299 if(ortn != errSecNoSuchAttr) {
300 printf("***Last SecKeychainItemCopyExtendedAttribute returned %d, expected %d\n",
301 (int)ortn, (int)errSecNoSuchAttr);
302 return -1;
303 }
304 return 0;
305 }
306
307 /*
308 * Verify that SecKeychainItemDelete() also deletes extended attributes.
309 *
310 * Assuming empty keychain:
311 * Import a cert;
312 * Set two extended attributes, make sure they're there;
313 * Delete the cert;
314 * Import the cert again;
315 * Verify that the new item has *no* extended attributes;
316 */
317 static int doDeleteItemTest(
318 SecKeychainRef kcRef,
319 bool quiet)
320 {
321 SecCertificateRef certRef = NULL;
322
323 if(doImportCert(CERT_FILE, kcRef, &certRef)) {
324 return 1;
325 }
326 if(!quiet) {
327 printf("...testing cert\n");
328 }
329 if(doTest((SecKeychainItemRef)certRef, certAttrs, quiet)) {
330 return -1;
331 }
332
333 /* doTest() verified that there are two extended attrs */
334 if(!quiet) {
335 printf("...deleting cert\n");
336 }
337 OSStatus ortn = SecKeychainItemDelete((SecKeychainItemRef)certRef);
338 if(ortn) {
339 cssmPerror("SecKeychainItemDelete", ortn);
340 return -1;
341 }
342 CFRelease(certRef);
343
344 if(!quiet) {
345 printf("...reimporting cert, verifying it has no extended attributes\n");
346 }
347 if(doImportCert(CERT_FILE, kcRef, &certRef)) {
348 return 1;
349 }
350 CFArrayRef attrNames = NULL;
351 ortn = SecKeychainItemCopyAllExtendedAttributes((SecKeychainItemRef)certRef, &attrNames,
352 NULL);
353 if(ortn != errSecNoSuchAttr) {
354 printf("***Deleted cert, re-imported it, and the new cert has extended attributes!\n");
355 return -1;
356 }
357 CFRelease(certRef);
358 return 0;
359 }
360
361 int main(int argc, char **argv)
362 {
363 const char *kcName = DEFAULT_KC_NAME;
364 extern char *optarg;
365 int arg;
366 bool quiet = false;
367 bool noDelete = false;
368
369 while ((arg = getopt(argc, argv, "k:qnh")) != -1) {
370 switch (arg) {
371 case 'k':
372 kcName = optarg;
373 break;
374 case 'n':
375 noDelete = true;
376 break;
377 case 'q':
378 quiet = true;
379 break;
380 case 'h':
381 usage(argv);
382 }
383 }
384 if(optind != argc) {
385 usage(argv);
386 }
387
388 testStartBanner("extendAttrTest", argc, argv);
389
390 SecKeychainRef kcRef = NULL;
391 OSStatus ortn;
392
393 if(!quiet) {
394 printf("Deleting possible existing keychain and creating %s...\n", kcName);
395
396 }
397 /* delete possible existing keychain, then create it */
398 if (SecKeychainOpen(kcName, &kcRef) == noErr)
399 {
400 SecKeychainDelete(kcRef);
401 CFRelease(kcRef);
402 }
403
404 kcRef = NULL;
405 ortn = SecKeychainCreate(kcName,
406 strlen(DEFAULT_KC_NAME), DEFAULT_KC_NAME,
407 false, NULL, &kcRef);
408 if(ortn) {
409 cssmPerror("SecKeychainCreate", ortn);
410 exit(1);
411 }
412
413 /* import keys */
414 SecKeyRef pubKey = NULL;
415 SecKeyRef privKey = NULL;
416 if(!quiet) {
417 printf("Importing %s to keychain...\n", PUB_KEY);
418 }
419 if(doImportKey(PUB_KEY, kSecFormatOpenSSL, kSecItemTypePublicKey, kcRef, &pubKey)) {
420 exit(1);
421 }
422 if(!quiet) {
423 printf("Importing %s to keychain...\n", PRIV_KEY);
424 }
425 if(doImportKey(PRIV_KEY, kSecFormatOpenSSL, kSecItemTypePrivateKey, kcRef, &privKey)) {
426 exit(1);
427 }
428
429 if(!quiet) {
430 printf("...testing public key\n");
431 }
432 if(doTest((SecKeychainItemRef)pubKey, pubKeyAttrs, quiet)) {
433 return -1;
434 }
435 if(!quiet) {
436 printf("...testing private key\n");
437 }
438 if(doTest((SecKeychainItemRef)privKey, privKeyAttrs, quiet)) {
439 return -1;
440 }
441
442 /*
443 * Those keys and their extended attrs are still in the keychain. Test a cert.
444 */
445 SecCertificateRef certRef = NULL;
446 if(doImportCert(CERT_FILE, kcRef, &certRef)) {
447 exit(1);
448 }
449 if(!quiet) {
450 printf("...testing cert\n");
451 }
452 if(doTest((SecKeychainItemRef)certRef, certAttrs, quiet)) {
453 return -1;
454 }
455
456 /* leaving everything in place, test a generic password. */
457 SecKeychainItemRef pwdRef = NULL;
458 ortn = SecKeychainAddGenericPassword(kcRef,
459 strlen(PWD_SERVICE), PWD_SERVICE,
460 strlen(PWD_ACCOUNT), PWD_ACCOUNT,
461 strlen(PWD_PWD), PWD_PWD,
462 &pwdRef);
463 if(ortn) {
464 cssmPerror("SecKeychainAddGenericPassword", ortn);
465 exit(1);
466 }
467 if(!quiet) {
468 printf("...testing generic password\n");
469 }
470 if(doTest(pwdRef, pwdAttrs, quiet)) {
471 return -1;
472 }
473
474 if(noDelete) {
475 goto done;
476 }
477
478 /* delete extended attrs; make sure they really get deleted */
479 if(!quiet) {
480 printf("...removing extended attributes from public key\n");
481 }
482 if(doDeleteTest((SecKeychainItemRef)pubKey, pubKeyAttrs, quiet)) {
483 exit(1);
484 }
485 if(!quiet) {
486 printf("...removing extended attributes from private key\n");
487 }
488 if(doDeleteTest((SecKeychainItemRef)privKey, privKeyAttrs, quiet)) {
489 exit(1);
490 }
491 if(!quiet) {
492 printf("...removing extended attributes from certificate\n");
493 }
494 if(doDeleteTest((SecKeychainItemRef)certRef, certAttrs, quiet)) {
495 exit(1);
496 }
497 if(!quiet) {
498 printf("...removing extended attributes from generic password\n");
499 }
500 if(doDeleteTest(pwdRef, pwdAttrs, quiet)) {
501 exit(1);
502 }
503
504 CFRelease(pubKey);
505 CFRelease(privKey);
506 CFRelease(pwdRef);
507
508 /* Verify that SecKeychainItemDelete() also deletes extended attributes */
509 ortn = SecKeychainItemDelete((SecKeychainItemRef)certRef);
510 if(ortn) {
511 cssmPerror("SecKeychainItemDelete", ortn);
512 exit(1);
513 }
514 CFRelease(certRef);
515 if(doDeleteItemTest(kcRef, quiet)) {
516 exit(1);
517 }
518
519 SecKeychainDelete(kcRef);
520 CFRelease(kcRef);
521 done:
522 if(!quiet) {
523 printf("...Success\n");
524 }
525 return 0;
526 }