1 /* $OpenBSD: keynote-keygen.c,v 1.21 2004/06/29 11:35:56 msf Exp $ */ 2 /* 3 * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu) 4 * 5 * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA, 6 * in April-May 1998 7 * 8 * Copyright (C) 1998, 1999 by Angelos D. Keromytis. 9 * 10 * Permission to use, copy, and modify this software with or without fee 11 * is hereby granted, provided that this entire notice is included in 12 * all copies of any software which is or includes a copy or 13 * modification of this software. 14 * 15 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO 17 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 18 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 19 * PURPOSE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 25 #include <ctype.h> 26 #include <fcntl.h> 27 #include <regex.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 #include <openssl/dsa.h> 34 #include <openssl/err.h> 35 #include <openssl/rand.h> 36 #include <openssl/rsa.h> 37 38 #include "header.h" 39 #include "keynote.h" 40 #include "assertion.h" 41 #include "signature.h" 42 43 void keygenusage(void); 44 45 void 46 keygenusage(void) 47 { 48 fprintf(stderr, "Arguments:\n"); 49 fprintf(stderr, "\t<AlgorithmName> <keysize> " 50 "<PublicKeyFile> <PrivateKeyFile> [<print-offset>] " 51 "[<print-length>]\n"); 52 } 53 54 /* 55 * Print the specified number of spaces. 56 */ 57 void 58 print_space(FILE *fp, int n) 59 { 60 while (n--) 61 fprintf(fp, " "); 62 } 63 64 /* 65 * Output a key, properly formatted. 66 */ 67 void 68 print_key(FILE *fp, char *algname, char *key, int start, int length) 69 { 70 int i, k; 71 72 print_space(fp, start); 73 fprintf(fp, "\"%s", algname); 74 75 for (i = 0, k = strlen(algname) + 2; i < strlen(key); i++, k++) 76 { 77 if (k == length) 78 { 79 if (i == strlen(key)) 80 { 81 fprintf(fp, "\"\n"); 82 return; 83 } 84 85 fprintf(fp, "\\\n"); 86 print_space(fp, start); 87 i--; 88 k = 0; 89 } 90 else 91 fprintf(fp, "%c", key[i]); 92 } 93 94 fprintf(fp, "\"\n"); 95 } 96 97 void 98 keynote_keygen(int argc, char *argv[]) 99 { 100 int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH; 101 char *foo, *privalgname, seed[SEED_LEN]; 102 int alg, enc, ienc, len = 0, counter; 103 struct keynote_deckey dc; 104 unsigned long h; 105 DSA *dsa; 106 RSA *rsa; 107 FILE *fp; 108 char *algname; 109 110 if ((argc != 5) && (argc != 6) && (argc != 7)) 111 { 112 keygenusage(); 113 exit(0); 114 } 115 116 /* Fix algorithm name */ 117 if (argv[1][strlen(argv[1]) - 1] != ':') 118 { 119 int len = strlen(argv[1]) + 2; 120 121 fprintf(stderr, "Algorithm name [%s] should be terminated with a " 122 "colon, fixing.\n", argv[1]); 123 algname = (char *) calloc(len, sizeof(char)); 124 if (algname == (char *) NULL) 125 { 126 perror("calloc()"); 127 exit(1); 128 } 129 130 strlcpy(algname, argv[1], len); 131 algname[strlen(algname)] = ':'; 132 } 133 else 134 algname = argv[1]; 135 136 if (argc > 5) 137 { 138 begin = atoi(argv[5]); 139 if (begin <= -1) 140 { 141 fprintf(stderr, "Erroneous value for print-offset parameter.\n"); 142 exit(1); 143 } 144 } 145 146 if (argc > 6) 147 { 148 prlen = atoi(argv[6]); 149 if (prlen <= 0) 150 { 151 fprintf(stderr, "Erroneous value for print-length parameter.\n"); 152 exit(1); 153 } 154 } 155 156 if (strlen(algname) + 2 > prlen) 157 { 158 fprintf(stderr, "Parameter ``print-length'' should be larger " 159 "than the length of AlgorithmName (%lu)\n", 160 (unsigned long) strlen(algname)); 161 exit(1); 162 } 163 164 alg = keynote_get_key_algorithm(algname, &enc, &ienc); 165 len = atoi(argv[2]); 166 167 if (len <= 0) 168 { 169 fprintf(stderr, "Invalid specified keysize %d\n", len); 170 exit(1); 171 } 172 173 if ((alg == KEYNOTE_ALGORITHM_DSA) && 174 (ienc == INTERNAL_ENC_ASN1) && 175 ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) 176 { 177 RAND_bytes(seed, SEED_LEN); 178 179 dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL 180 , NULL); 181 182 if (dsa == (DSA *) NULL) 183 { 184 ERR_print_errors_fp(stderr); 185 exit(1); 186 } 187 188 if (DSA_generate_key(dsa) != 1) 189 { 190 ERR_print_errors_fp(stderr); 191 exit(1); 192 } 193 194 dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA; 195 dc.dec_key = (void *) dsa; 196 197 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 198 if (foo == (char *) NULL) 199 { 200 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 201 exit(1); 202 } 203 204 if (!strcmp(argv[3], "-")) 205 fp = stdout; 206 else 207 { 208 fp = fopen(argv[3], "w"); 209 if (fp == (FILE *) NULL) 210 { 211 perror(argv[3]); 212 exit(1); 213 } 214 } 215 216 print_key(fp, algname, foo, begin, prlen); 217 free(foo); 218 219 if (strcmp(argv[3], "-")) 220 fclose(fp); 221 222 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 223 if (foo == (char *) NULL) 224 { 225 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 226 exit(1); 227 } 228 229 if (!strcmp(argv[4], "-")) 230 { 231 fp = stdout; 232 if (!strcmp(argv[3], "-")) 233 printf("===========================\n"); 234 } 235 else 236 { 237 fp = fopen(argv[4], "w"); 238 if (fp == (FILE *) NULL) 239 { 240 perror(argv[4]); 241 exit(1); 242 } 243 } 244 245 len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; 246 privalgname = (char *) calloc(len, sizeof(char)); 247 if (privalgname == (char *) NULL) 248 { 249 perror("calloc()"); 250 exit(1); 251 } 252 snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 253 print_key(fp, privalgname, foo, begin, prlen); 254 free(privalgname); 255 free(foo); 256 257 if (strcmp(argv[4], "-")) 258 fclose(fp); 259 260 exit(0); 261 } 262 263 if ((alg == KEYNOTE_ALGORITHM_RSA) && 264 (ienc == INTERNAL_ENC_PKCS1) && 265 ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) 266 { 267 rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL, NULL); 268 269 if (rsa == (RSA *) NULL) 270 { 271 ERR_print_errors_fp(stderr); 272 exit(1); 273 } 274 275 dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; 276 dc.dec_key = (void *) rsa; 277 278 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 279 if (foo == (char *) NULL) 280 { 281 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 282 exit(1); 283 } 284 285 if (!strcmp(argv[3], "-")) 286 fp = stdout; 287 else 288 { 289 fp = fopen(argv[3], "w"); 290 if (fp == (FILE *) NULL) 291 { 292 perror(argv[3]); 293 exit(1); 294 } 295 } 296 297 print_key(fp, algname, foo, begin, prlen); 298 free(foo); 299 300 if (strcmp(argv[3], "-")) 301 fclose(fp); 302 303 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 304 if (foo == (char *) NULL) 305 { 306 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 307 exit(1); 308 } 309 310 if (!strcmp(argv[4], "-")) 311 { 312 fp = stdout; 313 if (!strcmp(argv[3], "-")) 314 printf("===========================\n"); 315 } 316 else 317 { 318 fp = fopen(argv[4], "w"); 319 if (fp == (FILE *) NULL) 320 { 321 perror(argv[4]); 322 exit(1); 323 } 324 } 325 326 len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; 327 privalgname = (char *) calloc(len, sizeof(char)); 328 if (privalgname == (char *) NULL) 329 { 330 perror("calloc()"); 331 exit(1); 332 } 333 snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 334 print_key(fp, privalgname, foo, begin, prlen); 335 free(privalgname); 336 free(foo); 337 338 if (strcmp(argv[4], "-")) 339 fclose(fp); 340 341 exit(0); 342 } 343 344 /* More algorithms here */ 345 346 fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname); 347 exit(1); 348 } 349