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