#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <Security/Security.h>
#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);
}
static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand,
CSSM_DL_DB_HANDLE dlDbHand,
uint32 algorithm,
const char *keyLabel,
unsigned keyLabelLen,
uint32 keySize, CSSM_KEY_PTR pubKey, uint32 pubKeyUsage, CSSM_KEY_PTR privKey, uint32 privKeyUsage) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA keyLabelData;
uint32 pubAttr;
uint32 privAttr;
CSSM_RETURN ocrtn = CSSM_OK;
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, NULL, NULL, NULL, NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
ocrtn = crtn;
goto abort;
}
pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
switch(algorithm) {
case CSSM_ALGID_DSA:
{
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;
}
crtn = cspAddDlDbToContext(ccHand, dlDbHand.DLHandle, dlDbHand.DBHandle);
if(crtn) {
ocrtn = crtn;
goto abort;
}
crtn = CSSM_GenerateKeyPair(ccHand,
pubKeyUsage,
pubAttr,
&keyLabelData,
pubKey,
privKeyUsage,
privAttr,
&keyLabelData, NULL, 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, &privKey,
CSSM_KEYUSE_ANY); 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;
}