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");