1 /* $OpenBSD: keynote-keygen.c,v 1.15 2001/07/10 20:26:19 angelos 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 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 #if HAVE_CONFIG_H 23 #include "config.h" 24 #endif /* HAVE_CONFIG_H */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <stdlib.h> 29 #include <stdio.h> 30 #include <ctype.h> 31 32 #if STDC_HEADERS 33 #include <string.h> 34 #endif /* STDC_HEADERS */ 35 36 #if HAVE_FCNTL_H 37 #include <fcntl.h> 38 #endif /* HAVE_FCNTL_H */ 39 40 #if HAVE_IO_H 41 #include <io.h> 42 #elif HAVE_UNISTD_H 43 #include <unistd.h> 44 #endif /* HAVE_IO_H */ 45 46 #include "header.h" 47 #include "keynote.h" 48 #include "assertion.h" 49 #include "signature.h" 50 51 void 52 keygenusage(void) 53 { 54 fprintf(stderr, "Arguments:\n"); 55 fprintf(stderr, "\t<AlgorithmName> <keysize> " 56 "<PublicKeyFile> <PrivateKeyFile> [<print-offset>] " 57 "[<print-length>]\n"); 58 } 59 60 /* 61 * Print the specified number of spaces. 62 */ 63 void 64 print_space(FILE *fp, int n) 65 { 66 while (n--) 67 fprintf(fp, " "); 68 } 69 70 /* 71 * Output a key, properly formatted. 72 */ 73 void 74 print_key(FILE *fp, char *algname, char *key, int start, int length) 75 { 76 int i, k; 77 78 print_space(fp, start); 79 fprintf(fp, "\"%s", algname); 80 81 for (i = 0, k = strlen(algname) + 2; i < strlen(key); i++, k++) 82 { 83 if (k == length) 84 { 85 if (i == strlen(key)) 86 { 87 fprintf(fp, "\"\n"); 88 return; 89 } 90 91 fprintf(fp, "\\\n"); 92 print_space(fp, start); 93 i--; 94 k = 0; 95 } 96 else 97 fprintf(fp, "%c", key[i]); 98 } 99 100 fprintf(fp, "\"\n"); 101 } 102 103 void 104 keynote_keygen(int argc, char *argv[]) 105 { 106 int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH; 107 #if defined(CRYPTO) || defined(PGPLIB) 108 char *foo, *privalgname, seed[SEED_LEN]; 109 int alg, enc, ienc, len = 0, counter; 110 struct keynote_deckey dc; 111 unsigned long h; 112 DSA *dsa; 113 RSA *rsa; 114 FILE *fp; 115 #endif /* CRYPTO || PGPLIB */ 116 char *algname; 117 118 if ((argc != 5) && (argc != 6) && (argc != 7)) 119 { 120 keygenusage(); 121 exit(0); 122 } 123 124 /* Fix algorithm name */ 125 if (argv[1][strlen(argv[1]) - 1] != ':') 126 { 127 fprintf(stderr, "Algorithm name [%s] should be terminated with a " 128 "colon, fixing.\n", argv[1]); 129 algname = (char *) calloc(strlen(argv[1]) + 2, sizeof(char)); 130 if (algname == (char *) NULL) 131 { 132 perror("calloc()"); 133 exit(1); 134 } 135 136 strcpy(algname, argv[1]); 137 algname[strlen(algname)] = ':'; 138 } 139 else 140 algname = argv[1]; 141 142 if (argc > 5) 143 { 144 begin = atoi(argv[5]); 145 if (begin <= -1) 146 { 147 fprintf(stderr, "Erroneous value for print-offset parameter.\n"); 148 exit(1); 149 } 150 } 151 152 if (argc > 6) 153 { 154 prlen = atoi(argv[6]); 155 if (prlen <= 0) 156 { 157 fprintf(stderr, "Erroneous value for print-length parameter.\n"); 158 exit(1); 159 } 160 } 161 162 if (strlen(algname) + 2 > prlen) 163 { 164 fprintf(stderr, "Parameter ``print-length'' should be larger " 165 "than the length of AlgorithmName (%lu)\n", 166 (unsigned long) strlen(algname)); 167 exit(1); 168 } 169 170 #if defined(CRYPTO) || defined(PGPLIB) 171 alg = keynote_get_key_algorithm(algname, &enc, &ienc); 172 len = atoi(argv[2]); 173 174 if (len <= 0) 175 { 176 fprintf(stderr, "Invalid specified keysize %d\n", len); 177 exit(1); 178 } 179 180 if ((alg == KEYNOTE_ALGORITHM_DSA) && 181 (ienc == INTERNAL_ENC_ASN1) && 182 ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) 183 { 184 if (RAND_bytes(seed, SEED_LEN) == 0) 185 { 186 fprintf(stderr, "Failed to acquire %d random bytes\n", SEED_LEN); 187 exit(1); 188 } 189 190 dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL 191 #if SSLEAY_VERSION_NUMBER >= 0x0900 192 , NULL 193 #endif /* SSLEAY_VERSION_NUMBER */ 194 ); 195 196 if (dsa == (DSA *) NULL) 197 { 198 ERR_print_errors_fp(stderr); 199 exit(1); 200 } 201 202 if (DSA_generate_key(dsa) != 1) 203 { 204 ERR_print_errors_fp(stderr); 205 exit(1); 206 } 207 208 dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA; 209 dc.dec_key = (void *) dsa; 210 211 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 212 if (foo == (char *) NULL) 213 { 214 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 215 exit(1); 216 } 217 218 if (!strcmp(argv[3], "-")) 219 fp = stdout; 220 else 221 { 222 fp = fopen(argv[3], "w"); 223 if (fp == (FILE *) NULL) 224 { 225 perror(argv[3]); 226 exit(1); 227 } 228 } 229 230 print_key(fp, algname, foo, begin, prlen); 231 free(foo); 232 233 if (strcmp(argv[3], "-")) 234 fclose(fp); 235 236 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 237 if (foo == (char *) NULL) 238 { 239 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 240 exit(1); 241 } 242 243 if (!strcmp(argv[4], "-")) 244 { 245 fp = stdout; 246 if (!strcmp(argv[3], "-")) 247 printf("===========================\n"); 248 } 249 else 250 { 251 fp = fopen(argv[4], "w"); 252 if (fp == (FILE *) NULL) 253 { 254 perror(argv[4]); 255 exit(1); 256 } 257 } 258 259 privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + 260 strlen(foo) + 1, sizeof(char)); 261 if (privalgname == (char *) NULL) 262 { 263 perror("calloc()"); 264 exit(1); 265 } 266 sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 267 print_key(fp, privalgname, foo, begin, prlen); 268 free(privalgname); 269 free(foo); 270 271 if (strcmp(argv[4], "-")) 272 fclose(fp); 273 274 exit(0); 275 } 276 277 if ((alg == KEYNOTE_ALGORITHM_RSA) && 278 (ienc == INTERNAL_ENC_PKCS1) && 279 ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) 280 { 281 rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL 282 #if SSLEAY_VERSION_NUMBER >= 0x0900 283 , NULL 284 #endif /* SSLEAY_VERSION_NUMBER */ 285 ); 286 287 if (rsa == (RSA *) NULL) 288 { 289 ERR_print_errors_fp(stderr); 290 exit(1); 291 } 292 293 dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; 294 dc.dec_key = (void *) rsa; 295 296 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 297 if (foo == (char *) NULL) 298 { 299 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 300 exit(1); 301 } 302 303 if (!strcmp(argv[3], "-")) 304 fp = stdout; 305 else 306 { 307 fp = fopen(argv[3], "w"); 308 if (fp == (FILE *) NULL) 309 { 310 perror(argv[3]); 311 exit(1); 312 } 313 } 314 315 print_key(fp, algname, foo, begin, prlen); 316 free(foo); 317 318 if (strcmp(argv[3], "-")) 319 fclose(fp); 320 321 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 322 if (foo == (char *) NULL) 323 { 324 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 325 exit(1); 326 } 327 328 if (!strcmp(argv[4], "-")) 329 { 330 fp = stdout; 331 if (!strcmp(argv[3], "-")) 332 printf("===========================\n"); 333 } 334 else 335 { 336 fp = fopen(argv[4], "w"); 337 if (fp == (FILE *) NULL) 338 { 339 perror(argv[4]); 340 exit(1); 341 } 342 } 343 344 privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + 345 strlen(foo) + 1, sizeof(char)); 346 if (privalgname == (char *) NULL) 347 { 348 perror("calloc()"); 349 exit(1); 350 } 351 sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 352 print_key(fp, privalgname, foo, begin, prlen); 353 free(privalgname); 354 free(foo); 355 356 if (strcmp(argv[4], "-")) 357 fclose(fp); 358 359 exit(0); 360 } 361 362 /* More algorithms here */ 363 #endif /* CRYPTO */ 364 365 fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname); 366 exit(1); 367 } 368