2 * Examine and test a keychain's identity
4 #include <Security/Security.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>
22 static void usage(char **argv
)
24 printf("Usage: %s keychain|- cmd [options]\n", argv
[0]);
26 printf(" i get KC info\n");
27 printf(" k get key and cert info\n");
29 printf(" u unlock\n");
30 printf(" s sign and verify\n");
32 printf(" p=passphrase\n");
33 printf("Specifying '-' for keychain means NULL, default\n");
37 static void showError(
41 const char *errStr
= NULL
;
43 case errSecItemNotFound
:
44 errStr
= "errSecItemNotFound"; break;
45 case errSecNoSuchKeychain
:
46 errStr
= "errSecNoSuchKeychain"; break;
47 case errSecNotAvailable
:
48 errStr
= "errSecNotAvailable"; break;
51 if(ortn
< (CSSM_BASE_ERROR
+
52 (CSSM_ERRORCODE_MODULE_EXTENT
* 8))) {
53 /* assume CSSM error */
54 errStr
= cssmErrToStr(ortn
);
60 printf("***Error on %s: %s\n", msg
, errStr
);
63 printf("***Error on %s: %d(d)\n", msg
, (int)ortn
);
67 static void printDataAsHex(
69 unsigned maxToPrint
= 0) // optional, 0 means print it all
73 uint32 len
= d
->Length
;
76 if((maxToPrint
!= 0) && (len
> maxToPrint
)) {
80 for(i
=0; i
<len
; i
++) {
81 printf("%02X ", ((unsigned char *)cp
)[i
]);
91 static void printKeyHeader(
92 const CSSM_KEYHEADER
&hdr
)
94 printf(" Algorithm : ");
95 switch(hdr
.AlgorithmId
) {
106 printf("Diffie-Hellman\n");
109 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr
.AlgorithmId
,
110 (unsigned)hdr
.AlgorithmId
);
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 ");
119 if(usage
& CSSM_KEYUSE_ENCRYPT
) {
120 printf("CSSM_KEYUSE_ENCRYPT ");
122 if(usage
& CSSM_KEYUSE_DECRYPT
) {
123 printf("CSSM_KEYUSE_DECRYPT ");
125 if(usage
& CSSM_KEYUSE_SIGN
) {
126 printf("CSSM_KEYUSE_SIGN ");
128 if(usage
& CSSM_KEYUSE_VERIFY
) {
129 printf("CSSM_KEYUSE_VERIFY ");
131 if(usage
& CSSM_KEYUSE_SIGN_RECOVER
) {
132 printf("CSSM_KEYUSE_SIGN_RECOVER ");
134 if(usage
& CSSM_KEYUSE_VERIFY_RECOVER
) {
135 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
137 if(usage
& CSSM_KEYUSE_WRAP
) {
138 printf("CSSM_KEYUSE_WRAP ");
140 if(usage
& CSSM_KEYUSE_UNWRAP
) {
141 printf("CSSM_KEYUSE_UNWRAP ");
143 if(usage
& CSSM_KEYUSE_DERIVE
) {
144 printf("CSSM_KEYUSE_DERIVE ");
150 static OSStatus
getIdentity(
151 SecKeychainRef kcRef
,
153 SecIdentityRef
&idRef
)
155 SecIdentitySearchRef srchRef
= nil
;
156 OSStatus ortn
= SecIdentitySearchCreate(kcRef
, keyUse
, &srchRef
);
158 showError(ortn
, "SecIdentitySearchCreate");
161 ortn
= SecIdentitySearchCopyNext(srchRef
, &idRef
);
163 showError(ortn
, "SecIdentitySearchCopyNext");
166 if(CFGetTypeID(idRef
) != SecIdentityGetTypeID()) {
167 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
173 static OSStatus
getKeyCertInfo(
174 SecCertificateRef certRef
,
176 CSSM_KEY_PTR cssmKey
,
177 CSSM_CSP_HANDLE cspHand
)
179 /* display the private key */
180 if(cssmKey
== NULL
) {
181 printf(" ***malformed CSSM_KEY\n");
184 printf("Private Key :\n");
185 printKeyHeader(cssmKey
->KeyHeader
);
186 printf(" Key Blob : ");
187 printDataAsHex(&cssmKey
->KeyData
, 8);
192 OSStatus ortn
= SecCertificateGetData(certRef
, &certData
);
194 showError(ortn
, "SecCertificateGetData");
197 printf("\nCertificate :\n");
198 printCert((unsigned char *)certData
.Data
, (unsigned)certData
.Length
,
203 #define SIG_ALG CSSM_ALGID_SHA1WithRSA
205 static OSStatus
signVfy(
206 SecCertificateRef certRef
,
208 CSSM_KEY_PTR cssmKey
,
209 CSSM_CSP_HANDLE cspHand
)
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
};
216 /* sign with CSPDL */
217 crtn
= cspSign(cspHand
, SIG_ALG
, cssmKey
, &ptext
, &sig
);
219 printf("Error signing with private key\n");
224 CSSM_CL_HANDLE clHand
= clStartup();
226 printf("***Error attaching to CL\n");
230 /* get the public key from the cert */
232 OSStatus ortn
= SecCertificateGetData(certRef
, &certData
);
234 showError(ortn
, "SecCertificateGetData");
237 CSSM_KEY_PTR pubKey
= NULL
;
238 crtn
= CSSM_CL_CertGetKeyInfo(clHand
, &certData
, &pubKey
);
240 printError("CSSM_CL_CertGetKeyInfo", crtn
);
244 /* attach to raw CSP */
245 CSSM_CSP_HANDLE rawCspHand
= cspStartup();
246 if(rawCspHand
== 0) {
247 printf("***Error attaching to raw CSP\n");
251 /* verify with raw CSP and raw public key */
252 crtn
= cspSigVerify(rawCspHand
, SIG_ALG
, pubKey
, &ptext
,
255 printf("Error verifying with public key\n");
259 /* free everything */
260 CSSM_ModuleDetach(rawCspHand
);
261 CSSM_ModuleDetach(clHand
);
262 printf("...sign with private key, vfy with cert OK\n");
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
273 OSStatus ortn
= SecIdentityCopyCertificate(idRef
, &certRef
);
275 showError(ortn
, "SecIdentityCopyCertificate");
278 ortn
= SecIdentityCopyPrivateKey(idRef
, &keyRef
);
280 showError(ortn
, "SecIdentityCopyPrivateKey");
283 ortn
= SecKeyGetCSSMKey(keyRef
, (const CSSM_KEY
**)&cssmKey
);
285 showError(ortn
, "SecKeyGetCSSMKey");
290 int main(int argc
, char **argv
)
292 SecKeychainRef kcRef
= nil
;
297 /* user-spec'd variables */
306 if(!strcmp("-", kcName
)) {
312 op
= KC_GetInfo
; break;
314 op
= KC_LockKC
; break;
316 op
= KC_UnlockKC
; break;
318 op
= KC_SignVfy
; break;
320 op
= KC_KeyCertInfo
; break;
324 for(arg
=3; arg
<argc
; arg
++) {
336 ortn
= SecKeychainOpen(kcName
, &kcRef
);
338 showError(ortn
, "SecKeychainOpen");
339 printf("Cannot open keychain at %s. Aborting.\n", kcName
);
344 /* handle trivial commands right now */
347 ortn
= SecKeychainLock(kcRef
);
349 showError(ortn
, "SecKeychainLock");
352 printf("...keychain %s locked.\n", argv
[1]);
357 printf("***Warning: unlocking with no password\n");
359 ortn
= SecKeychainUnlock(kcRef
,
360 pwd
? strlen(pwd
) : 0,
362 pwd
? true : false); // usePassword
364 showError(ortn
, "SecKeychainUnlock");
367 printf("...keychain %s unlocked.\n", argv
[1]);
372 SecKeychainStatus kcStat
;
373 ortn
= SecKeychainGetStatus(kcRef
, &kcStat
);
375 showError(ortn
, "SecKeychainGetStatus");
378 printf("...SecKeychainStatus = %u ( ", (unsigned)kcStat
);
379 if(kcStat
& kSecUnlockStateStatus
) {
380 printf("UnlockState ");
382 if(kcStat
& kSecReadPermStatus
) {
385 if(kcStat
& kSecWritePermStatus
) {
393 /* more processing below */
397 /* remaining cmds need an identity */
398 SecIdentityRef idRef
;
399 ortn
= getIdentity(kcRef
, CSSM_KEYUSE_SIGN
, idRef
);
401 printf("***No identity found in keychain %s. Aborting.\n", kcName
);
406 CSSM_CSP_HANDLE cspHand
;
407 ortn
= SecKeychainGetCSPHandle(kcRef
, &cspHand
);
409 showError(ortn
, "SecKeychainGetCSPHandle");
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
);
419 printf("***Incomplete identity\n");
425 ortn
= getKeyCertInfo(certRef
, keyRef
, privKey
, cspHand
);
428 ortn
= signVfy(certRef
, keyRef
, privKey
, cspHand
);
431 printf("BRRRZAP!\n");