]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/idTool/idTool.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / idTool / idTool.cpp
1 /*
2 * Examine and test a keychain's identity
3 */
4 #include <Security/Security.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
8 #include <security_cdsa_utils/cuPrintCert.h>
9 #include <utilLib/common.h>
10 #include <utilLib/cspwrap.h>
11 #include <clAppUtils/clutils.h>
12
13 typedef enum {
14 KC_Nop,
15 KC_GetInfo,
16 KC_LockKC,
17 KC_UnlockKC,
18 KC_SignVfy,
19 KC_KeyCertInfo
20 } KcOp;
21
22 static void usage(char **argv)
23 {
24 printf("Usage: %s keychain|- cmd [options]\n", argv[0]);
25 printf("Command:\n");
26 printf(" i get KC info\n");
27 printf(" k get key and cert info\n");
28 printf(" l lock\n");
29 printf(" u unlock\n");
30 printf(" s sign and verify\n");
31 printf("Options:\n");
32 printf(" p=passphrase\n");
33 printf("Specifying '-' for keychain means NULL, default\n");
34 exit(1);
35 }
36
37 static void showError(
38 OSStatus ortn,
39 const char *msg)
40 {
41 const char *errStr = NULL;
42 switch(ortn) {
43 case errSecItemNotFound:
44 errStr = "errSecItemNotFound"; break;
45 case errSecNoSuchKeychain:
46 errStr = "errSecNoSuchKeychain"; break;
47 case errSecNotAvailable:
48 errStr = "errSecNotAvailable"; break;
49 /* more? */
50 default:
51 if(ortn < (CSSM_BASE_ERROR +
52 (CSSM_ERRORCODE_MODULE_EXTENT * 8))) {
53 /* assume CSSM error */
54 errStr = cssmErrToStr(ortn);
55 }
56 break;
57
58 }
59 if(errStr) {
60 printf("***Error on %s: %s\n", msg, errStr);
61 }
62 else {
63 printf("***Error on %s: %d(d)\n", msg, (int)ortn);
64 }
65 }
66
67 static void printDataAsHex(
68 const CSSM_DATA *d,
69 unsigned maxToPrint = 0) // optional, 0 means print it all
70 {
71 unsigned i;
72 bool more = false;
73 uint32 len = d->Length;
74 uint8 *cp = d->Data;
75
76 if((maxToPrint != 0) && (len > maxToPrint)) {
77 len = maxToPrint;
78 more = true;
79 }
80 for(i=0; i<len; i++) {
81 printf("%02X ", ((unsigned char *)cp)[i]);
82 }
83 if(more) {
84 printf("...\n");
85 }
86 else {
87 printf("\n");
88 }
89 }
90
91 static void printKeyHeader(
92 const CSSM_KEYHEADER &hdr)
93 {
94 printf(" Algorithm : ");
95 switch(hdr.AlgorithmId) {
96 case CSSM_ALGID_RSA:
97 printf("RSA\n");
98 break;
99 case CSSM_ALGID_DSA:
100 printf("DSA\n");
101 break;
102 case CSSM_ALGID_FEE:
103 printf("FEE\n");
104 break;
105 case CSSM_ALGID_DH:
106 printf("Diffie-Hellman\n");
107 break;
108 default:
109 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr.AlgorithmId,
110 (unsigned)hdr.AlgorithmId);
111 }
112 printf(" Key Size : %u bits\n",
113 (unsigned)hdr.LogicalKeySizeInBits);
114 printf(" Key Use : ");
115 CSSM_KEYUSE usage = hdr.KeyUsage;
116 if(usage & CSSM_KEYUSE_ANY) {
117 printf("CSSM_KEYUSE_ANY ");
118 }
119 if(usage & CSSM_KEYUSE_ENCRYPT) {
120 printf("CSSM_KEYUSE_ENCRYPT ");
121 }
122 if(usage & CSSM_KEYUSE_DECRYPT) {
123 printf("CSSM_KEYUSE_DECRYPT ");
124 }
125 if(usage & CSSM_KEYUSE_SIGN) {
126 printf("CSSM_KEYUSE_SIGN ");
127 }
128 if(usage & CSSM_KEYUSE_VERIFY) {
129 printf("CSSM_KEYUSE_VERIFY ");
130 }
131 if(usage & CSSM_KEYUSE_SIGN_RECOVER) {
132 printf("CSSM_KEYUSE_SIGN_RECOVER ");
133 }
134 if(usage & CSSM_KEYUSE_VERIFY_RECOVER) {
135 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
136 }
137 if(usage & CSSM_KEYUSE_WRAP) {
138 printf("CSSM_KEYUSE_WRAP ");
139 }
140 if(usage & CSSM_KEYUSE_UNWRAP) {
141 printf("CSSM_KEYUSE_UNWRAP ");
142 }
143 if(usage & CSSM_KEYUSE_DERIVE) {
144 printf("CSSM_KEYUSE_DERIVE ");
145 }
146 printf("\n");
147
148 }
149
150 static OSStatus getIdentity(
151 SecKeychainRef kcRef,
152 CSSM_KEYUSE keyUse,
153 SecIdentityRef &idRef)
154 {
155 SecIdentitySearchRef srchRef = nil;
156 OSStatus ortn = SecIdentitySearchCreate(kcRef, keyUse, &srchRef);
157 if(ortn) {
158 showError(ortn, "SecIdentitySearchCreate");
159 return ortn;
160 }
161 ortn = SecIdentitySearchCopyNext(srchRef, &idRef);
162 if(ortn) {
163 showError(ortn, "SecIdentitySearchCopyNext");
164 return ortn;
165 }
166 if(CFGetTypeID(idRef) != SecIdentityGetTypeID()) {
167 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
168 return paramErr;
169 }
170 return noErr;
171 }
172
173 static OSStatus getKeyCertInfo(
174 SecCertificateRef certRef,
175 SecKeyRef keyRef,
176 CSSM_KEY_PTR cssmKey,
177 CSSM_CSP_HANDLE cspHand)
178 {
179 /* display the private key */
180 if(cssmKey == NULL) {
181 printf(" ***malformed CSSM_KEY\n");
182 }
183 else {
184 printf("Private Key :\n");
185 printKeyHeader(cssmKey->KeyHeader);
186 printf(" Key Blob : ");
187 printDataAsHex(&cssmKey->KeyData, 8);
188 }
189
190 /* and the cert */
191 CSSM_DATA certData;
192 OSStatus ortn = SecCertificateGetData(certRef, &certData);
193 if(ortn) {
194 showError(ortn, "SecCertificateGetData");
195 return ortn;
196 }
197 printf("\nCertificate :\n");
198 printCert((unsigned char *)certData.Data, (unsigned)certData.Length,
199 CSSM_TRUE);
200 return noErr;
201 }
202
203 #define SIG_ALG CSSM_ALGID_SHA1WithRSA
204
205 static OSStatus signVfy(
206 SecCertificateRef certRef,
207 SecKeyRef keyRef,
208 CSSM_KEY_PTR cssmKey,
209 CSSM_CSP_HANDLE cspHand)
210 {
211 uint8 someData[] = {0,1,2,3,4,5,6,7,8};
212 CSSM_DATA ptext = {sizeof(someData), someData};
213 CSSM_DATA sig = {0, NULL};
214 CSSM_RETURN crtn;
215
216 /* sign with CSPDL */
217 crtn = cspSign(cspHand, SIG_ALG, cssmKey, &ptext, &sig);
218 if(crtn) {
219 printf("Error signing with private key\n");
220 return crtn;
221 }
222
223 /* attach to CL */
224 CSSM_CL_HANDLE clHand = clStartup();
225 if(clHand == 0) {
226 printf("***Error attaching to CL\n");
227 return ioErr;
228 }
229
230 /* get the public key from the cert */
231 CSSM_DATA certData;
232 OSStatus ortn = SecCertificateGetData(certRef, &certData);
233 if(ortn) {
234 showError(ortn, "SecCertificateGetData");
235 return ortn;
236 }
237 CSSM_KEY_PTR pubKey = NULL;
238 crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, &pubKey);
239 if(crtn) {
240 printError("CSSM_CL_CertGetKeyInfo", crtn);
241 return crtn;
242 }
243
244 /* attach to raw CSP */
245 CSSM_CSP_HANDLE rawCspHand = cspStartup();
246 if(rawCspHand == 0) {
247 printf("***Error attaching to raw CSP\n");
248 return ioErr;
249 }
250
251 /* verify with raw CSP and raw public key */
252 crtn = cspSigVerify(rawCspHand, SIG_ALG, pubKey, &ptext,
253 &sig, CSSM_OK);
254 if(crtn) {
255 printf("Error verifying with public key\n");
256 return crtn;
257 }
258
259 /* free everything */
260 CSSM_ModuleDetach(rawCspHand);
261 CSSM_ModuleDetach(clHand);
262 printf("...sign with private key, vfy with cert OK\n");
263 return noErr;
264 }
265
266 /* get cert and private key (in Sec and CSSM form) from identity */
267 static OSStatus getKeyCert(
268 SecIdentityRef idRef,
269 SecCertificateRef &certRef, // RETURNED
270 SecKeyRef &keyRef, // private key, RETURNED
271 CSSM_KEY_PTR &cssmKey) // private key, RETURNED
272 {
273 OSStatus ortn = SecIdentityCopyCertificate(idRef, &certRef);
274 if(ortn) {
275 showError(ortn, "SecIdentityCopyCertificate");
276 return ortn;
277 }
278 ortn = SecIdentityCopyPrivateKey(idRef, &keyRef);
279 if(ortn) {
280 showError(ortn, "SecIdentityCopyPrivateKey");
281 return ortn;
282 }
283 ortn = SecKeyGetCSSMKey(keyRef, (const CSSM_KEY **)&cssmKey);
284 if(ortn) {
285 showError(ortn, "SecKeyGetCSSMKey");
286 }
287 return ortn;
288 }
289
290 int main(int argc, char **argv)
291 {
292 SecKeychainRef kcRef = nil;
293 OSStatus ortn;
294 int arg;
295 char *argp;
296
297 /* user-spec'd variables */
298 KcOp op = KC_Nop;
299 char *pwd = NULL;
300 char *kcName;
301
302 if(argc < 3) {
303 usage(argv);
304 }
305 kcName = argv[1];
306 if(!strcmp("-", kcName)) {
307 /* null - no open */
308 kcName = NULL;
309 }
310 switch(argv[2][0]) {
311 case 'i':
312 op = KC_GetInfo; break;
313 case 'l':
314 op = KC_LockKC; break;
315 case 'u':
316 op = KC_UnlockKC; break;
317 case 's':
318 op = KC_SignVfy; break;
319 case 'k':
320 op = KC_KeyCertInfo; break;
321 default:
322 usage(argv);
323 }
324 for(arg=3; arg<argc; arg++) {
325 argp = argv[arg];
326 switch(argp[0]) {
327 case 'p':
328 pwd = &argp[2];
329 break;
330 default:
331 usage(argv);
332 }
333 }
334
335 if(kcName != NULL) {
336 ortn = SecKeychainOpen(kcName, &kcRef);
337 if(ortn) {
338 showError(ortn, "SecKeychainOpen");
339 printf("Cannot open keychain at %s. Aborting.\n", kcName);
340 exit(1);
341 }
342 }
343
344 /* handle trivial commands right now */
345 switch(op) {
346 case KC_LockKC:
347 ortn = SecKeychainLock(kcRef);
348 if(ortn) {
349 showError(ortn, "SecKeychainLock");
350 exit(1);
351 }
352 printf("...keychain %s locked.\n", argv[1]);
353 exit(0);
354
355 case KC_UnlockKC:
356 if(pwd == NULL) {
357 printf("***Warning: unlocking with no password\n");
358 }
359 ortn = SecKeychainUnlock(kcRef,
360 pwd ? strlen(pwd) : 0,
361 pwd,
362 pwd ? true : false); // usePassword
363 if(ortn) {
364 showError(ortn, "SecKeychainUnlock");
365 exit(1);
366 }
367 printf("...keychain %s unlocked.\n", argv[1]);
368 exit(0);
369
370 case KC_GetInfo:
371 {
372 SecKeychainStatus kcStat;
373 ortn = SecKeychainGetStatus(kcRef, &kcStat);
374 if(ortn) {
375 showError(ortn, "SecKeychainGetStatus");
376 exit(1);
377 }
378 printf("...SecKeychainStatus = %u ( ", (unsigned)kcStat);
379 if(kcStat & kSecUnlockStateStatus) {
380 printf("UnlockState ");
381 }
382 if(kcStat & kSecReadPermStatus) {
383 printf("RdPerm ");
384 }
385 if(kcStat & kSecWritePermStatus) {
386 printf("WrPerm ");
387 }
388 printf(")\n");
389 exit(0);
390 }
391
392 default:
393 /* more processing below */
394 break;
395 }
396
397 /* remaining cmds need an identity */
398 SecIdentityRef idRef;
399 ortn = getIdentity(kcRef, CSSM_KEYUSE_SIGN, idRef);
400 if(ortn) {
401 printf("***No identity found in keychain %s. Aborting.\n", kcName);
402 exit(1);
403 }
404
405 /* and a CSP */
406 CSSM_CSP_HANDLE cspHand;
407 ortn = SecKeychainGetCSPHandle(kcRef, &cspHand);
408 if(ortn) {
409 showError(ortn, "SecKeychainGetCSPHandle");
410 exit(1);
411 }
412
413 /* and the cert and keys */
414 SecCertificateRef certRef = nil;
415 SecKeyRef keyRef = nil;
416 CSSM_KEY_PTR privKey = NULL;
417 ortn = getKeyCert(idRef, certRef, keyRef, privKey);
418 if(ortn) {
419 printf("***Incomplete identity\n");
420 exit(1);
421 }
422
423 switch(op) {
424 case KC_KeyCertInfo:
425 ortn = getKeyCertInfo(certRef, keyRef, privKey, cspHand);
426 break;
427 case KC_SignVfy:
428 ortn = signVfy(certRef, keyRef, privKey, cspHand);
429 break;
430 default:
431 printf("BRRRZAP!\n");
432 exit(1);
433 }
434 CFRelease(idRef);
435 if(kcRef) {
436 CFRelease(kcRef);
437 }
438 return (int)ortn;
439 }