xref: /openbsd-src/lib/libkeynote/keynote-keygen.c (revision eb6d9f7654ad683266b1b120f59afcd3403c19b3)
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