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
keygenusage(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
print_space(FILE * fp,int n)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
print_key(FILE * fp,char * algname,char * key,int start,int length)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
keynote_keygen(int argc,char * argv[])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