]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/idTool/idTool.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / idTool / idTool.cpp
diff --git a/SecurityTests/clxutils/idTool/idTool.cpp b/SecurityTests/clxutils/idTool/idTool.cpp
new file mode 100644 (file)
index 0000000..e861388
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * Examine and test a keychain's identity
+ */
+#include <Security/Security.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
+#include <security_cdsa_utils/cuPrintCert.h>
+#include <utilLib/common.h>
+#include <utilLib/cspwrap.h>
+#include <clAppUtils/clutils.h>
+
+typedef enum {
+       KC_Nop,
+       KC_GetInfo,
+       KC_LockKC,
+       KC_UnlockKC,
+       KC_SignVfy,
+       KC_KeyCertInfo
+} KcOp;
+
+static void usage(char **argv)
+{
+       printf("Usage: %s keychain|- cmd [options]\n", argv[0]);
+       printf("Command:\n");
+       printf("  i  get KC info\n");
+       printf("  k  get key and cert info\n");
+       printf("  l  lock\n");
+       printf("  u  unlock\n");
+       printf("  s  sign and verify\n");
+       printf("Options:\n");
+       printf("  p=passphrase\n");
+       printf("Specifying '-' for keychain means NULL, default\n");
+       exit(1);
+}
+
+static void showError(
+       OSStatus ortn,
+       const char *msg)
+{
+       const char *errStr = NULL;
+       switch(ortn) {
+               case errSecItemNotFound:
+                       errStr = "errSecItemNotFound"; break;
+               case errSecNoSuchKeychain:
+                       errStr = "errSecNoSuchKeychain"; break;
+               case errSecNotAvailable:
+                       errStr = "errSecNotAvailable"; break;
+               /* more? */
+               default:
+                       if(ortn < (CSSM_BASE_ERROR + 
+                                       (CSSM_ERRORCODE_MODULE_EXTENT * 8))) {
+                               /* assume CSSM error */
+                               errStr = cssmErrToStr(ortn);
+                       }
+                       break;
+
+       }
+       if(errStr) {
+               printf("***Error on %s: %s\n", msg, errStr);
+       }
+       else {
+               printf("***Error on %s: %d(d)\n", msg, (int)ortn);
+       }
+}
+
+static void printDataAsHex(
+       const CSSM_DATA *d,
+       unsigned maxToPrint = 0)                // optional, 0 means print it all
+{
+       unsigned i;
+       bool more = false;
+       uint32 len = d->Length;
+       uint8 *cp = d->Data;
+       
+       if((maxToPrint != 0) && (len > maxToPrint)) {
+               len = maxToPrint;
+               more = true;
+       }       
+       for(i=0; i<len; i++) {
+               printf("%02X ", ((unsigned char *)cp)[i]);
+       }
+       if(more) {
+               printf("...\n");
+       }
+       else {
+               printf("\n");
+       }
+}
+
+static void printKeyHeader(
+       const CSSM_KEYHEADER &hdr)
+{
+       printf("   Algorithm       : ");
+       switch(hdr.AlgorithmId) {
+               case CSSM_ALGID_RSA:
+                       printf("RSA\n");
+                       break;
+               case CSSM_ALGID_DSA:
+                       printf("DSA\n");
+                       break;
+               case CSSM_ALGID_FEE:
+                       printf("FEE\n");
+                       break;
+               case CSSM_ALGID_DH:
+                       printf("Diffie-Hellman\n");
+                       break;
+               default:
+                       printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr.AlgorithmId, 
+                               (unsigned)hdr.AlgorithmId);
+       }
+       printf("   Key Size        : %u bits\n", 
+               (unsigned)hdr.LogicalKeySizeInBits);
+       printf("   Key Use         : ");
+       CSSM_KEYUSE usage = hdr.KeyUsage;
+       if(usage & CSSM_KEYUSE_ANY) {
+               printf("CSSM_KEYUSE_ANY ");
+       }
+       if(usage & CSSM_KEYUSE_ENCRYPT) {
+               printf("CSSM_KEYUSE_ENCRYPT ");
+       }
+       if(usage & CSSM_KEYUSE_DECRYPT) {
+               printf("CSSM_KEYUSE_DECRYPT ");
+       }
+       if(usage & CSSM_KEYUSE_SIGN) {
+               printf("CSSM_KEYUSE_SIGN ");
+       }
+       if(usage & CSSM_KEYUSE_VERIFY) {
+               printf("CSSM_KEYUSE_VERIFY ");
+       }
+       if(usage & CSSM_KEYUSE_SIGN_RECOVER) {
+               printf("CSSM_KEYUSE_SIGN_RECOVER ");
+       }
+       if(usage & CSSM_KEYUSE_VERIFY_RECOVER) {
+               printf("CSSM_KEYUSE_VERIFY_RECOVER ");
+       }
+       if(usage & CSSM_KEYUSE_WRAP) {
+               printf("CSSM_KEYUSE_WRAP ");
+       }
+       if(usage & CSSM_KEYUSE_UNWRAP) {
+               printf("CSSM_KEYUSE_UNWRAP ");
+       }
+       if(usage & CSSM_KEYUSE_DERIVE) {
+               printf("CSSM_KEYUSE_DERIVE ");
+       }
+       printf("\n");
+
+}
+
+static OSStatus getIdentity(
+       SecKeychainRef kcRef,
+       CSSM_KEYUSE keyUse,
+       SecIdentityRef &idRef)
+{
+       SecIdentitySearchRef srchRef = nil;
+       OSStatus ortn = SecIdentitySearchCreate(kcRef, keyUse, &srchRef);
+       if(ortn) {
+               showError(ortn, "SecIdentitySearchCreate");
+               return ortn;
+       }
+       ortn = SecIdentitySearchCopyNext(srchRef, &idRef);
+       if(ortn) {
+               showError(ortn, "SecIdentitySearchCopyNext");
+               return ortn;
+       }
+       if(CFGetTypeID(idRef) != SecIdentityGetTypeID()) {
+               printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
+               return paramErr;
+       }
+       return noErr;
+}
+
+static OSStatus getKeyCertInfo(
+       SecCertificateRef certRef,
+       SecKeyRef keyRef,
+       CSSM_KEY_PTR cssmKey,
+       CSSM_CSP_HANDLE cspHand)
+{
+       /* display the private key */
+       if(cssmKey == NULL) {
+               printf("   ***malformed CSSM_KEY\n");
+       }
+       else {
+               printf("Private Key        :\n");
+               printKeyHeader(cssmKey->KeyHeader);
+               printf("   Key Blob        : ");
+               printDataAsHex(&cssmKey->KeyData, 8);
+       }
+
+       /* and the cert */
+       CSSM_DATA certData;
+       OSStatus ortn = SecCertificateGetData(certRef, &certData);
+       if(ortn) {
+               showError(ortn, "SecCertificateGetData");
+               return ortn;
+       }
+       printf("\nCertificate        :\n");
+       printCert((unsigned char *)certData.Data, (unsigned)certData.Length,
+               CSSM_TRUE);
+       return noErr;
+}
+
+#define SIG_ALG                CSSM_ALGID_SHA1WithRSA
+
+static OSStatus signVfy(
+       SecCertificateRef certRef,
+       SecKeyRef keyRef,
+       CSSM_KEY_PTR cssmKey,
+       CSSM_CSP_HANDLE cspHand)
+{
+       uint8 someData[] = {0,1,2,3,4,5,6,7,8};
+       CSSM_DATA ptext = {sizeof(someData), someData};
+       CSSM_DATA sig = {0, NULL};
+       CSSM_RETURN crtn;
+       
+       /* sign with CSPDL */
+       crtn = cspSign(cspHand, SIG_ALG, cssmKey, &ptext, &sig);
+       if(crtn) {
+               printf("Error signing with private key\n");
+               return crtn;
+       }
+       
+       /* attach to CL */
+       CSSM_CL_HANDLE clHand = clStartup();
+       if(clHand == 0) {
+               printf("***Error attaching to CL\n");
+               return ioErr;
+       }
+       
+       /* get the public key from the cert */
+       CSSM_DATA certData;
+       OSStatus ortn = SecCertificateGetData(certRef, &certData);
+       if(ortn) {
+               showError(ortn, "SecCertificateGetData");
+               return ortn;
+       }
+       CSSM_KEY_PTR pubKey = NULL;
+       crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, &pubKey);
+       if(crtn) {
+               printError("CSSM_CL_CertGetKeyInfo", crtn);
+               return crtn;
+       }
+       
+       /* attach to raw CSP */
+       CSSM_CSP_HANDLE rawCspHand = cspStartup();
+       if(rawCspHand == 0) {
+               printf("***Error attaching to raw CSP\n");
+               return ioErr;
+       }
+       
+       /* verify with raw CSP and raw public key */
+       crtn = cspSigVerify(rawCspHand, SIG_ALG, pubKey, &ptext, 
+               &sig, CSSM_OK);
+       if(crtn) {
+               printf("Error verifying with public key\n");
+               return crtn;
+       }
+       
+       /* free everything */
+       CSSM_ModuleDetach(rawCspHand);
+       CSSM_ModuleDetach(clHand);
+       printf("...sign with private key, vfy with cert OK\n");
+       return noErr;
+}
+
+/* get cert and private key (in Sec and CSSM form) from identity */
+static OSStatus getKeyCert(
+       SecIdentityRef          idRef,
+       SecCertificateRef       &certRef,               // RETURNED
+       SecKeyRef                       &keyRef,                // private key, RETURNED
+       CSSM_KEY_PTR            &cssmKey)               // private key, RETURNED
+{
+       OSStatus ortn = SecIdentityCopyCertificate(idRef, &certRef);
+       if(ortn) {
+               showError(ortn, "SecIdentityCopyCertificate");
+               return ortn;
+       }
+       ortn = SecIdentityCopyPrivateKey(idRef, &keyRef);
+       if(ortn) {
+               showError(ortn, "SecIdentityCopyPrivateKey");
+               return ortn;
+       }
+       ortn = SecKeyGetCSSMKey(keyRef, (const CSSM_KEY **)&cssmKey);
+       if(ortn) {
+               showError(ortn, "SecKeyGetCSSMKey");
+       }
+       return ortn;    
+}
+
+int main(int argc, char **argv)
+{
+       SecKeychainRef          kcRef = nil;
+       OSStatus                        ortn;
+       int                                     arg;
+       char                            *argp;
+       
+       /* user-spec'd variables */
+       KcOp                            op = KC_Nop;
+       char                            *pwd = NULL;
+       char                            *kcName;
+       
+       if(argc < 3) {
+               usage(argv);
+       }
+       kcName = argv[1];
+       if(!strcmp("-", kcName)) {
+               /* null - no open */
+               kcName = NULL;
+       }
+       switch(argv[2][0]) {
+               case 'i':
+                       op = KC_GetInfo; break;
+               case 'l':
+                       op = KC_LockKC; break;
+               case 'u':
+                       op = KC_UnlockKC; break;
+               case 's':
+                       op = KC_SignVfy; break;
+               case 'k':
+                       op = KC_KeyCertInfo; break;
+               default:
+                       usage(argv);
+       }
+       for(arg=3; arg<argc; arg++) {
+               argp = argv[arg];
+               switch(argp[0]) {
+                       case 'p':
+                               pwd = &argp[2];
+                               break;
+                       default:
+                               usage(argv);
+               }
+       }
+       
+       if(kcName != NULL) {
+               ortn = SecKeychainOpen(kcName, &kcRef);
+               if(ortn) {
+                       showError(ortn, "SecKeychainOpen");
+                       printf("Cannot open keychain at %s. Aborting.\n", kcName);
+                       exit(1);
+               }
+       }
+       
+       /* handle trivial commands right now */
+       switch(op) {
+               case KC_LockKC:
+                       ortn = SecKeychainLock(kcRef);
+                       if(ortn) {
+                               showError(ortn, "SecKeychainLock");
+                               exit(1);                                
+                       }
+                       printf("...keychain %s locked.\n", argv[1]);
+                       exit(0);
+                       
+               case KC_UnlockKC:
+                       if(pwd == NULL) {
+                               printf("***Warning: unlocking with no password\n");
+                       }
+                       ortn = SecKeychainUnlock(kcRef,
+                               pwd ? strlen(pwd) : 0,
+                               pwd,
+                               pwd ? true : false);            // usePassword
+                       if(ortn) {
+                               showError(ortn, "SecKeychainUnlock");
+                               exit(1);        
+                       }
+                       printf("...keychain %s unlocked.\n", argv[1]);
+                       exit(0);
+
+               case KC_GetInfo:
+               {
+                       SecKeychainStatus kcStat;
+                       ortn = SecKeychainGetStatus(kcRef, &kcStat);
+                       if(ortn) {
+                               showError(ortn, "SecKeychainGetStatus");
+                               exit(1);                                
+                       }
+                       printf("...SecKeychainStatus = %u ( ", (unsigned)kcStat);
+                       if(kcStat & kSecUnlockStateStatus) {
+                               printf("UnlockState ");
+                       }
+                       if(kcStat & kSecReadPermStatus) {
+                               printf("RdPerm ");
+                       }
+                       if(kcStat & kSecWritePermStatus) {
+                               printf("WrPerm ");
+                       }
+                       printf(")\n");
+                       exit(0);
+               }
+               
+               default:
+                       /* more processing below */
+                       break;
+       }
+
+       /* remaining cmds need an identity */
+       SecIdentityRef idRef;
+       ortn = getIdentity(kcRef, CSSM_KEYUSE_SIGN, idRef);
+       if(ortn) {
+               printf("***No identity found in keychain %s. Aborting.\n", kcName);
+               exit(1);
+       }
+       
+       /* and a CSP */
+       CSSM_CSP_HANDLE cspHand;
+       ortn = SecKeychainGetCSPHandle(kcRef, &cspHand);
+       if(ortn) {
+               showError(ortn, "SecKeychainGetCSPHandle");
+               exit(1);
+       }
+
+       /* and the cert and keys */
+       SecCertificateRef certRef = nil;
+       SecKeyRef keyRef = nil;
+       CSSM_KEY_PTR privKey = NULL;
+       ortn = getKeyCert(idRef, certRef, keyRef, privKey);
+       if(ortn) {
+               printf("***Incomplete identity\n");
+               exit(1);
+       }
+       
+       switch(op) {
+               case KC_KeyCertInfo:
+                       ortn = getKeyCertInfo(certRef, keyRef, privKey, cspHand);
+                       break;
+               case KC_SignVfy:
+                       ortn = signVfy(certRef, keyRef, privKey, cspHand);
+                       break;
+               default:
+                       printf("BRRRZAP!\n");
+                       exit(1);
+       }
+       CFRelease(idRef);
+       if(kcRef) {
+               CFRelease(kcRef);
+       }
+       return (int)ortn;
+}