1/* 2 * genKeyPair.cpp - create a key pair, store in specified keychain 3 */ 4#include <stdlib.h> 5#include <stdio.h> 6#include <time.h> 7#include <string.h> 8#include <unistd.h> 9#include <Security/Security.h> 10#include "cspwrap.h" 11#include "common.h" 12 13static void usage(char **argv) 14{ 15 printf("usage: %s keychain [options]\n", argv[0]); 16 printf("Options:\n"); 17 printf(" -l label -- no default\n"); 18 printf(" -a r|f|d -- algorithm RSA/FEE/DSA, default = RSA\n"); 19 printf(" -k bits -- key size in bits, default is 1024/128/512 for RSA/FEE/DSA\n"); 20 exit(1); 21} 22 23/* 24 * Generate key pair of arbitrary algorithm. 25 * FEE keys will have random private data. 26 * Like the cspGenKeyPair() in cspwrap.c except this provides a DLDB handle. 27 */ 28static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand, 29 CSSM_DL_DB_HANDLE dlDbHand, 30 uint32 algorithm, 31 const char *keyLabel, 32 unsigned keyLabelLen, 33 uint32 keySize, // in bits 34 CSSM_KEY_PTR pubKey, // mallocd by caller 35 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. 36 CSSM_KEY_PTR privKey, // mallocd by caller 37 uint32 privKeyUsage) // CSSM_KEYUSE_DECRYPT, etc. 38{ 39 CSSM_RETURN crtn; 40 CSSM_CC_HANDLE ccHand; 41 CSSM_DATA keyLabelData; 42 uint32 pubAttr; 43 uint32 privAttr; 44 CSSM_RETURN ocrtn = CSSM_OK; 45 46 /* pre-context-create algorithm-specific stuff */ 47 switch(algorithm) { 48 case CSSM_ALGID_FEE: 49 if(keySize == CSP_KEY_SIZE_DEFAULT) { 50 keySize = CSP_FEE_KEY_SIZE_DEFAULT; 51 } 52 break; 53 case CSSM_ALGID_RSA: 54 if(keySize == CSP_KEY_SIZE_DEFAULT) { 55 keySize = CSP_RSA_KEY_SIZE_DEFAULT; 56 } 57 break; 58 case CSSM_ALGID_DSA: 59 if(keySize == CSP_KEY_SIZE_DEFAULT) { 60 keySize = CSP_DSA_KEY_SIZE_DEFAULT; 61 } 62 break; 63 default: 64 printf("cspGenKeyPair: Unknown algorithm\n"); 65 break; 66 } 67 keyLabelData.Data = (uint8 *)keyLabel, 68 keyLabelData.Length = keyLabelLen; 69 memset(pubKey, 0, sizeof(CSSM_KEY)); 70 memset(privKey, 0, sizeof(CSSM_KEY)); 71 72 crtn = CSSM_CSP_CreateKeyGenContext(cspHand, 73 algorithm, 74 keySize, 75 NULL, // Seed 76 NULL, // Salt 77 NULL, // StartDate 78 NULL, // EndDate 79 NULL, // Params 80 &ccHand); 81 if(crtn) { 82 printError("CSSM_CSP_CreateKeyGenContext", crtn); 83 ocrtn = crtn; 84 goto abort; 85 } 86 /* cook up attribute bits */ 87 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; 88 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; 89 90 /* post-context-create algorithm-specific stuff */ 91 switch(algorithm) { 92 case CSSM_ALGID_DSA: 93 /* 94 * extra step - generate params - this just adds some 95 * info to the context 96 */ 97 { 98 CSSM_DATA dummy = {0, NULL}; 99 crtn = CSSM_GenerateAlgorithmParams(ccHand, 100 keySize, &dummy); 101 if(crtn) { 102 printError("CSSM_GenerateAlgorithmParams", crtn); 103 return crtn; 104 } 105 appFreeCssmData(&dummy, CSSM_FALSE); 106 } 107 break; 108 default: 109 break; 110 } 111 112 /* add in DL/DB to context */ 113 crtn = cspAddDlDbToContext(ccHand, dlDbHand.DLHandle, dlDbHand.DBHandle); 114 if(crtn) { 115 ocrtn = crtn; 116 goto abort; 117 } 118 119 crtn = CSSM_GenerateKeyPair(ccHand, 120 pubKeyUsage, 121 pubAttr, 122 &keyLabelData, 123 pubKey, 124 privKeyUsage, 125 privAttr, 126 &keyLabelData, // same labels 127 NULL, // CredAndAclEntry 128 privKey); 129 if(crtn) { 130 printError("CSSM_GenerateKeyPair", crtn); 131 ocrtn = crtn; 132 goto abort; 133 } 134abort: 135 if(ccHand != 0) { 136 crtn = CSSM_DeleteContext(ccHand); 137 if(crtn) { 138 printError("CSSM_DeleteContext", crtn); 139 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; 140 } 141 } 142 return ocrtn; 143} 144 145int main(int argc, char **argv) 146{ 147 char *kcName = NULL; 148 char *label = NULL; 149 CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; 150 unsigned keySizeInBits = CSP_KEY_SIZE_DEFAULT; 151 152 if(argc < 2) { 153 usage(argv); 154 } 155 kcName = argv[1]; 156 157 extern char *optarg; 158 extern int optind; 159 160 optind = 2; 161 int arg; 162 while ((arg = getopt(argc, argv, "l:a:k:h")) != -1) { 163 switch (arg) { 164 case 'l': 165 label = optarg; 166 break; 167 case 'a': 168 switch(optarg[0]) { 169 case 'r': 170 keyAlg = CSSM_ALGID_RSA; 171 break; 172 case 'f': 173 keyAlg = CSSM_ALGID_FEE; 174 break; 175 case 'd': 176 keyAlg = CSSM_ALGID_DSA; 177 break; 178 default: 179 usage(argv); 180 } 181 break; 182 case 'k': 183 keySizeInBits = atoi(optarg); 184 break; 185 default: 186 usage(argv); 187 } 188 } 189 if(optind != argc) { 190 usage(argv); 191 } 192 193 SecKeychainRef kcRef = nil; 194 OSStatus ortn; 195 196 ortn = SecKeychainOpen(kcName, &kcRef); 197 if(ortn) { 198 cssmPerror("SecKeychainOpen", ortn); 199 exit(1); 200 } 201 202 CSSM_CSP_HANDLE cspHand = 0; 203 CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; 204 ortn = SecKeychainGetCSPHandle(kcRef, &cspHand); 205 if(ortn) { 206 cssmPerror("SecKeychainGetCSPHandle", ortn); 207 exit(1); 208 } 209 ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHand); 210 if(ortn) { 211 cssmPerror("SecKeychainGetDLDBHandle", ortn); 212 exit(1); 213 } 214 215 CSSM_KEY privKey; 216 CSSM_KEY pubKey; 217 CSSM_RETURN crtn; 218 219 crtn = genKeyPair(cspHand, dlDbHand, 220 keyAlg, 221 label, (label ? strlen(label) : 0), 222 keySizeInBits, 223 &pubKey, 224 CSSM_KEYUSE_ANY, // may want to parameterize 225 &privKey, 226 CSSM_KEYUSE_ANY); // may want to parameterize 227 if(crtn) { 228 printf("**Error creating key pair.\n"); 229 } 230 else { 231 printf("...key pair created in keychain %s.\n", kcName); 232 } 233 234 cspFreeKey(cspHand, &privKey); 235 cspFreeKey(cspHand, &pubKey); 236 CFRelease(kcRef); 237 return 0; 238} 239