1*eb6d9f76Stb /* $OpenBSD: keynote-keygen.c,v 1.23 2024/02/07 17:22:01 tb Exp $ */
2983e9580Sangelos /*
3983e9580Sangelos * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
4983e9580Sangelos *
5983e9580Sangelos * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
6983e9580Sangelos * in April-May 1998
7983e9580Sangelos *
8983e9580Sangelos * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
9983e9580Sangelos *
105e4ac158Sderaadt * Permission to use, copy, and modify this software with or without fee
11983e9580Sangelos * is hereby granted, provided that this entire notice is included in
12983e9580Sangelos * all copies of any software which is or includes a copy or
13983e9580Sangelos * modification of this software.
14983e9580Sangelos *
15983e9580Sangelos * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
16983e9580Sangelos * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
17983e9580Sangelos * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
18983e9580Sangelos * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
19983e9580Sangelos * PURPOSE.
20983e9580Sangelos */
21983e9580Sangelos
22983e9580Sangelos #include <sys/types.h>
23983e9580Sangelos #include <sys/stat.h>
24e0758482Smsf
25983e9580Sangelos #include <ctype.h>
269186b70cSangelos #include <fcntl.h>
2785616838Smsf #include <regex.h>
28e0758482Smsf #include <stdio.h>
29e0758482Smsf #include <stdlib.h>
30e0758482Smsf #include <string.h>
31983e9580Sangelos #include <unistd.h>
32983e9580Sangelos
3385616838Smsf #include <openssl/dsa.h>
3485616838Smsf #include <openssl/err.h>
3585616838Smsf #include <openssl/rand.h>
3685616838Smsf #include <openssl/rsa.h>
3785616838Smsf
381c338448Sangelos #include "header.h"
39a8a6ad51Sangelos #include "keynote.h"
40a8a6ad51Sangelos #include "assertion.h"
41983e9580Sangelos #include "signature.h"
42983e9580Sangelos
43aa31cba2Sderaadt void keygenusage(void);
44aa31cba2Sderaadt
45983e9580Sangelos void
keygenusage(void)46e482c692Sangelos keygenusage(void)
47983e9580Sangelos {
48983e9580Sangelos fprintf(stderr, "Arguments:\n");
49983e9580Sangelos fprintf(stderr, "\t<AlgorithmName> <keysize> "
50a1d1ca57Sangelos "<PublicKeyFile> <PrivateKeyFile> [<print-offset>] "
51a1d1ca57Sangelos "[<print-length>]\n");
52983e9580Sangelos }
53983e9580Sangelos
54983e9580Sangelos /*
55983e9580Sangelos * Print the specified number of spaces.
56983e9580Sangelos */
57983e9580Sangelos void
print_space(FILE * fp,int n)58983e9580Sangelos print_space(FILE *fp, int n)
59983e9580Sangelos {
60983e9580Sangelos while (n--)
61983e9580Sangelos fprintf(fp, " ");
62983e9580Sangelos }
63983e9580Sangelos
64983e9580Sangelos /*
65983e9580Sangelos * Output a key, properly formatted.
66983e9580Sangelos */
67983e9580Sangelos void
print_key(FILE * fp,char * algname,char * key,int start,int length)68983e9580Sangelos print_key(FILE *fp, char *algname, char *key, int start, int length)
69983e9580Sangelos {
70983e9580Sangelos int i, k;
71983e9580Sangelos
72983e9580Sangelos print_space(fp, start);
73983e9580Sangelos fprintf(fp, "\"%s", algname);
74983e9580Sangelos
75983e9580Sangelos for (i = 0, k = strlen(algname) + 2; i < strlen(key); i++, k++)
76983e9580Sangelos {
77983e9580Sangelos if (k == length)
78983e9580Sangelos {
79983e9580Sangelos if (i == strlen(key))
80983e9580Sangelos {
81983e9580Sangelos fprintf(fp, "\"\n");
82983e9580Sangelos return;
83983e9580Sangelos }
84983e9580Sangelos
85983e9580Sangelos fprintf(fp, "\\\n");
86983e9580Sangelos print_space(fp, start);
87983e9580Sangelos i--;
88983e9580Sangelos k = 0;
89983e9580Sangelos }
90983e9580Sangelos else
91983e9580Sangelos fprintf(fp, "%c", key[i]);
92983e9580Sangelos }
93983e9580Sangelos
94983e9580Sangelos fprintf(fp, "\"\n");
95983e9580Sangelos }
96983e9580Sangelos
97983e9580Sangelos void
keynote_keygen(int argc,char * argv[])98e482c692Sangelos keynote_keygen(int argc, char *argv[])
99983e9580Sangelos {
100983e9580Sangelos int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH;
101983e9580Sangelos char *foo, *privalgname, seed[SEED_LEN];
102983e9580Sangelos int alg, enc, ienc, len = 0, counter;
103983e9580Sangelos struct keynote_deckey dc;
104983e9580Sangelos unsigned long h;
105983e9580Sangelos DSA *dsa;
106983e9580Sangelos RSA *rsa;
107983e9580Sangelos FILE *fp;
108983e9580Sangelos char *algname;
109983e9580Sangelos
110983e9580Sangelos if ((argc != 5) && (argc != 6) && (argc != 7))
111983e9580Sangelos {
112e482c692Sangelos keygenusage();
113983e9580Sangelos exit(0);
114983e9580Sangelos }
115983e9580Sangelos
116983e9580Sangelos /* Fix algorithm name */
117983e9580Sangelos if (argv[1][strlen(argv[1]) - 1] != ':')
118983e9580Sangelos {
119f91597c4Sderaadt int len = strlen(argv[1]) + 2;
120f91597c4Sderaadt
121983e9580Sangelos fprintf(stderr, "Algorithm name [%s] should be terminated with a "
122983e9580Sangelos "colon, fixing.\n", argv[1]);
123313d0fe7Smmcc algname = calloc(len, sizeof(char));
124313d0fe7Smmcc if (algname == NULL)
125983e9580Sangelos {
126983e9580Sangelos perror("calloc()");
1273cb7a939Sangelos exit(1);
128983e9580Sangelos }
129983e9580Sangelos
130f91597c4Sderaadt strlcpy(algname, argv[1], len);
131983e9580Sangelos algname[strlen(algname)] = ':';
132983e9580Sangelos }
133983e9580Sangelos else
134983e9580Sangelos algname = argv[1];
135983e9580Sangelos
136983e9580Sangelos if (argc > 5)
137983e9580Sangelos {
138983e9580Sangelos begin = atoi(argv[5]);
139983e9580Sangelos if (begin <= -1)
140983e9580Sangelos {
141983e9580Sangelos fprintf(stderr, "Erroneous value for print-offset parameter.\n");
1423cb7a939Sangelos exit(1);
143983e9580Sangelos }
144983e9580Sangelos }
145983e9580Sangelos
146983e9580Sangelos if (argc > 6)
147983e9580Sangelos {
148983e9580Sangelos prlen = atoi(argv[6]);
149983e9580Sangelos if (prlen <= 0)
150983e9580Sangelos {
151983e9580Sangelos fprintf(stderr, "Erroneous value for print-length parameter.\n");
1523cb7a939Sangelos exit(1);
153983e9580Sangelos }
154983e9580Sangelos }
155983e9580Sangelos
156983e9580Sangelos if (strlen(algname) + 2 > prlen)
157983e9580Sangelos {
158983e9580Sangelos fprintf(stderr, "Parameter ``print-length'' should be larger "
1597b79fe91Sderaadt "than the length of AlgorithmName (%lu)\n",
1607b79fe91Sderaadt (unsigned long) strlen(algname));
1613cb7a939Sangelos exit(1);
162983e9580Sangelos }
163983e9580Sangelos
164983e9580Sangelos alg = keynote_get_key_algorithm(algname, &enc, &ienc);
165983e9580Sangelos len = atoi(argv[2]);
166983e9580Sangelos
167983e9580Sangelos if (len <= 0)
168983e9580Sangelos {
169983e9580Sangelos fprintf(stderr, "Invalid specified keysize %d\n", len);
1703cb7a939Sangelos exit(1);
171983e9580Sangelos }
172983e9580Sangelos
173983e9580Sangelos if ((alg == KEYNOTE_ALGORITHM_DSA) &&
174983e9580Sangelos (ienc == INTERNAL_ENC_ASN1) &&
175983e9580Sangelos ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64)))
176983e9580Sangelos {
177685148fcSangelos RAND_bytes(seed, SEED_LEN);
178d13090a4Sangelos
179*eb6d9f76Stb dsa = DSA_new();
180983e9580Sangelos
181313d0fe7Smmcc if (dsa == NULL)
182983e9580Sangelos {
183983e9580Sangelos ERR_print_errors_fp(stderr);
1843cb7a939Sangelos exit(1);
185983e9580Sangelos }
186983e9580Sangelos
187*eb6d9f76Stb if (DSA_generate_parameters_ex(dsa, len, seed, SEED_LEN,
188*eb6d9f76Stb &counter, &h, NULL) != 1)
189*eb6d9f76Stb {
190*eb6d9f76Stb ERR_print_errors_fp(stderr);
191*eb6d9f76Stb exit(1);
192*eb6d9f76Stb }
193*eb6d9f76Stb
194983e9580Sangelos if (DSA_generate_key(dsa) != 1)
195983e9580Sangelos {
196983e9580Sangelos ERR_print_errors_fp(stderr);
1973cb7a939Sangelos exit(1);
198983e9580Sangelos }
199983e9580Sangelos
200983e9580Sangelos dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA;
201983e9580Sangelos dc.dec_key = (void *) dsa;
202983e9580Sangelos
203983e9580Sangelos foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
204313d0fe7Smmcc if (foo == NULL)
205983e9580Sangelos {
206983e9580Sangelos fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
2073cb7a939Sangelos exit(1);
208983e9580Sangelos }
209983e9580Sangelos
210983e9580Sangelos if (!strcmp(argv[3], "-"))
211983e9580Sangelos fp = stdout;
212983e9580Sangelos else
213983e9580Sangelos {
214983e9580Sangelos fp = fopen(argv[3], "w");
215313d0fe7Smmcc if (fp == NULL)
216983e9580Sangelos {
217ca0ac210Sangelos perror(argv[3]);
2183cb7a939Sangelos exit(1);
219983e9580Sangelos }
220983e9580Sangelos }
221983e9580Sangelos
222983e9580Sangelos print_key(fp, algname, foo, begin, prlen);
223983e9580Sangelos free(foo);
224983e9580Sangelos
225983e9580Sangelos if (strcmp(argv[3], "-"))
226983e9580Sangelos fclose(fp);
227983e9580Sangelos
228983e9580Sangelos foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
229313d0fe7Smmcc if (foo == NULL)
230983e9580Sangelos {
231983e9580Sangelos fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
2323cb7a939Sangelos exit(1);
233983e9580Sangelos }
234983e9580Sangelos
235983e9580Sangelos if (!strcmp(argv[4], "-"))
236983e9580Sangelos {
237983e9580Sangelos fp = stdout;
238983e9580Sangelos if (!strcmp(argv[3], "-"))
239983e9580Sangelos printf("===========================\n");
240983e9580Sangelos }
241983e9580Sangelos else
242983e9580Sangelos {
243983e9580Sangelos fp = fopen(argv[4], "w");
244313d0fe7Smmcc if (fp == NULL)
245983e9580Sangelos {
246ca0ac210Sangelos perror(argv[4]);
2473cb7a939Sangelos exit(1);
248983e9580Sangelos }
249983e9580Sangelos }
250983e9580Sangelos
251f91597c4Sderaadt len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1;
252313d0fe7Smmcc privalgname = calloc(len, sizeof(char));
253313d0fe7Smmcc if (privalgname == NULL)
254983e9580Sangelos {
255983e9580Sangelos perror("calloc()");
2563cb7a939Sangelos exit(1);
257983e9580Sangelos }
258f91597c4Sderaadt snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
259983e9580Sangelos print_key(fp, privalgname, foo, begin, prlen);
260983e9580Sangelos free(privalgname);
261983e9580Sangelos free(foo);
262983e9580Sangelos
263983e9580Sangelos if (strcmp(argv[4], "-"))
264983e9580Sangelos fclose(fp);
265983e9580Sangelos
266983e9580Sangelos exit(0);
267983e9580Sangelos }
268983e9580Sangelos
269983e9580Sangelos if ((alg == KEYNOTE_ALGORITHM_RSA) &&
270983e9580Sangelos (ienc == INTERNAL_ENC_PKCS1) &&
271983e9580Sangelos ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64)))
272983e9580Sangelos {
273e0758482Smsf rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL, NULL);
274983e9580Sangelos
275313d0fe7Smmcc if (rsa == NULL)
276983e9580Sangelos {
277983e9580Sangelos ERR_print_errors_fp(stderr);
2783cb7a939Sangelos exit(1);
279983e9580Sangelos }
280983e9580Sangelos
281983e9580Sangelos dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
282983e9580Sangelos dc.dec_key = (void *) rsa;
283983e9580Sangelos
284983e9580Sangelos foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
285313d0fe7Smmcc if (foo == NULL)
286983e9580Sangelos {
287983e9580Sangelos fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
2883cb7a939Sangelos exit(1);
289983e9580Sangelos }
290983e9580Sangelos
291983e9580Sangelos if (!strcmp(argv[3], "-"))
292983e9580Sangelos fp = stdout;
293983e9580Sangelos else
294983e9580Sangelos {
295983e9580Sangelos fp = fopen(argv[3], "w");
296313d0fe7Smmcc if (fp == NULL)
297983e9580Sangelos {
298ca0ac210Sangelos perror(argv[3]);
2993cb7a939Sangelos exit(1);
300983e9580Sangelos }
301983e9580Sangelos }
302983e9580Sangelos
303983e9580Sangelos print_key(fp, algname, foo, begin, prlen);
304983e9580Sangelos free(foo);
305983e9580Sangelos
306983e9580Sangelos if (strcmp(argv[3], "-"))
307983e9580Sangelos fclose(fp);
308983e9580Sangelos
309983e9580Sangelos foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
310313d0fe7Smmcc if (foo == NULL)
311983e9580Sangelos {
312983e9580Sangelos fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
3133cb7a939Sangelos exit(1);
314983e9580Sangelos }
315983e9580Sangelos
316983e9580Sangelos if (!strcmp(argv[4], "-"))
317983e9580Sangelos {
318983e9580Sangelos fp = stdout;
319983e9580Sangelos if (!strcmp(argv[3], "-"))
320983e9580Sangelos printf("===========================\n");
321983e9580Sangelos }
322983e9580Sangelos else
323983e9580Sangelos {
324983e9580Sangelos fp = fopen(argv[4], "w");
325313d0fe7Smmcc if (fp == NULL)
326983e9580Sangelos {
327ca0ac210Sangelos perror(argv[4]);
3283cb7a939Sangelos exit(1);
329983e9580Sangelos }
330983e9580Sangelos }
331983e9580Sangelos
332f91597c4Sderaadt len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1;
333313d0fe7Smmcc privalgname = calloc(len, sizeof(char));
334313d0fe7Smmcc if (privalgname == NULL)
335983e9580Sangelos {
336983e9580Sangelos perror("calloc()");
3373cb7a939Sangelos exit(1);
338983e9580Sangelos }
339f91597c4Sderaadt snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
340983e9580Sangelos print_key(fp, privalgname, foo, begin, prlen);
341983e9580Sangelos free(privalgname);
342983e9580Sangelos free(foo);
343983e9580Sangelos
344983e9580Sangelos if (strcmp(argv[4], "-"))
345983e9580Sangelos fclose(fp);
346983e9580Sangelos
347983e9580Sangelos exit(0);
348983e9580Sangelos }
349983e9580Sangelos
350983e9580Sangelos /* More algorithms here */
351983e9580Sangelos
352983e9580Sangelos fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname);
3533cb7a939Sangelos exit(1);
354983e9580Sangelos }
355