1 /* $OpenBSD: keynote-keygen.c,v 1.23 2024/02/07 17:22:01 tb 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 = calloc(len, sizeof(char)); 124 if (algname == 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_new(); 180 181 if (dsa == NULL) 182 { 183 ERR_print_errors_fp(stderr); 184 exit(1); 185 } 186 187 if (DSA_generate_parameters_ex(dsa, len, seed, SEED_LEN, 188 &counter, &h, NULL) != 1) 189 { 190 ERR_print_errors_fp(stderr); 191 exit(1); 192 } 193 194 if (DSA_generate_key(dsa) != 1) 195 { 196 ERR_print_errors_fp(stderr); 197 exit(1); 198 } 199 200 dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA; 201 dc.dec_key = (void *) dsa; 202 203 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 204 if (foo == NULL) 205 { 206 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 207 exit(1); 208 } 209 210 if (!strcmp(argv[3], "-")) 211 fp = stdout; 212 else 213 { 214 fp = fopen(argv[3], "w"); 215 if (fp == NULL) 216 { 217 perror(argv[3]); 218 exit(1); 219 } 220 } 221 222 print_key(fp, algname, foo, begin, prlen); 223 free(foo); 224 225 if (strcmp(argv[3], "-")) 226 fclose(fp); 227 228 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 229 if (foo == NULL) 230 { 231 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 232 exit(1); 233 } 234 235 if (!strcmp(argv[4], "-")) 236 { 237 fp = stdout; 238 if (!strcmp(argv[3], "-")) 239 printf("===========================\n"); 240 } 241 else 242 { 243 fp = fopen(argv[4], "w"); 244 if (fp == NULL) 245 { 246 perror(argv[4]); 247 exit(1); 248 } 249 } 250 251 len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; 252 privalgname = calloc(len, sizeof(char)); 253 if (privalgname == NULL) 254 { 255 perror("calloc()"); 256 exit(1); 257 } 258 snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 259 print_key(fp, privalgname, foo, begin, prlen); 260 free(privalgname); 261 free(foo); 262 263 if (strcmp(argv[4], "-")) 264 fclose(fp); 265 266 exit(0); 267 } 268 269 if ((alg == KEYNOTE_ALGORITHM_RSA) && 270 (ienc == INTERNAL_ENC_PKCS1) && 271 ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) 272 { 273 rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL, NULL); 274 275 if (rsa == NULL) 276 { 277 ERR_print_errors_fp(stderr); 278 exit(1); 279 } 280 281 dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; 282 dc.dec_key = (void *) rsa; 283 284 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); 285 if (foo == NULL) 286 { 287 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 288 exit(1); 289 } 290 291 if (!strcmp(argv[3], "-")) 292 fp = stdout; 293 else 294 { 295 fp = fopen(argv[3], "w"); 296 if (fp == NULL) 297 { 298 perror(argv[3]); 299 exit(1); 300 } 301 } 302 303 print_key(fp, algname, foo, begin, prlen); 304 free(foo); 305 306 if (strcmp(argv[3], "-")) 307 fclose(fp); 308 309 foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); 310 if (foo == NULL) 311 { 312 fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); 313 exit(1); 314 } 315 316 if (!strcmp(argv[4], "-")) 317 { 318 fp = stdout; 319 if (!strcmp(argv[3], "-")) 320 printf("===========================\n"); 321 } 322 else 323 { 324 fp = fopen(argv[4], "w"); 325 if (fp == NULL) 326 { 327 perror(argv[4]); 328 exit(1); 329 } 330 } 331 332 len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; 333 privalgname = calloc(len, sizeof(char)); 334 if (privalgname == NULL) 335 { 336 perror("calloc()"); 337 exit(1); 338 } 339 snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); 340 print_key(fp, privalgname, foo, begin, prlen); 341 free(privalgname); 342 free(foo); 343 344 if (strcmp(argv[4], "-")) 345 fclose(fp); 346 347 exit(0); 348 } 349 350 /* More algorithms here */ 351 352 fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname); 353 exit(1); 354 } 355