X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp?ds=sidebyside diff --git a/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp b/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp new file mode 100644 index 00000000..8d9bba78 --- /dev/null +++ b/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp @@ -0,0 +1,238 @@ +/* + * genKeyPair.cpp - create a key pair, store in specified keychain + */ +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +static void usage(char **argv) +{ + printf("usage: %s keychain [options]\n", argv[0]); + printf("Options:\n"); + printf(" -l label -- no default\n"); + printf(" -a r|f|d -- algorithm RSA/FEE/DSA, default = RSA\n"); + printf(" -k bits -- key size in bits, default is 1024/128/512 for RSA/FEE/DSA\n"); + exit(1); +} + +/* + * Generate key pair of arbitrary algorithm. + * FEE keys will have random private data. + * Like the cspGenKeyPair() in cspwrap.c except this provides a DLDB handle. + */ +static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDbHand, + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEY_PTR privKey, // mallocd by caller + uint32 privKeyUsage) // CSSM_KEYUSE_DECRYPT, etc. +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + /* pre-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_FEE: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_FEE_KEY_SIZE_DEFAULT; + } + break; + case CSSM_ALGID_RSA: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_RSA_KEY_SIZE_DEFAULT; + } + break; + case CSSM_ALGID_DSA: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_DSA_KEY_SIZE_DEFAULT; + } + break; + default: + printf("cspGenKeyPair: Unknown algorithm\n"); + break; + } + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + /* cook up attribute bits */ + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return crtn; + } + appFreeCssmData(&dummy, CSSM_FALSE); + } + break; + default: + break; + } + + /* add in DL/DB to context */ + crtn = cspAddDlDbToContext(ccHand, dlDbHand.DLHandle, dlDbHand.DBHandle); + if(crtn) { + ocrtn = crtn; + goto abort; + } + + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + +int main(int argc, char **argv) +{ + char *kcName = NULL; + char *label = NULL; + CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; + unsigned keySizeInBits = CSP_KEY_SIZE_DEFAULT; + + if(argc < 2) { + usage(argv); + } + kcName = argv[1]; + + extern char *optarg; + extern int optind; + + optind = 2; + int arg; + while ((arg = getopt(argc, argv, "l:a:k:h")) != -1) { + switch (arg) { + case 'l': + label = optarg; + break; + case 'a': + switch(optarg[0]) { + case 'r': + keyAlg = CSSM_ALGID_RSA; + break; + case 'f': + keyAlg = CSSM_ALGID_FEE; + break; + case 'd': + keyAlg = CSSM_ALGID_DSA; + break; + default: + usage(argv); + } + break; + case 'k': + keySizeInBits = atoi(optarg); + break; + default: + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + SecKeychainRef kcRef = nil; + OSStatus ortn; + + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + + CSSM_CSP_HANDLE cspHand = 0; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + ortn = SecKeychainGetCSPHandle(kcRef, &cspHand); + if(ortn) { + cssmPerror("SecKeychainGetCSPHandle", ortn); + exit(1); + } + ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHand); + if(ortn) { + cssmPerror("SecKeychainGetDLDBHandle", ortn); + exit(1); + } + + CSSM_KEY privKey; + CSSM_KEY pubKey; + CSSM_RETURN crtn; + + crtn = genKeyPair(cspHand, dlDbHand, + keyAlg, + label, (label ? strlen(label) : 0), + keySizeInBits, + &pubKey, + CSSM_KEYUSE_ANY, // may want to parameterize + &privKey, + CSSM_KEYUSE_ANY); // may want to parameterize + if(crtn) { + printf("**Error creating key pair.\n"); + } + else { + printf("...key pair created in keychain %s.\n", kcName); + } + + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + CFRelease(kcRef); + return 0; +}