xref: /openbsd-src/lib/libkeynote/keynote-keygen.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* $OpenBSD: keynote-keygen.c,v 1.15 2001/07/10 20:26:19 angelos 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 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 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif /* HAVE_CONFIG_H */
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 
32 #if STDC_HEADERS
33 #include <string.h>
34 #endif /* STDC_HEADERS */
35 
36 #if HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif /* HAVE_FCNTL_H */
39 
40 #if HAVE_IO_H
41 #include <io.h>
42 #elif HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif /* HAVE_IO_H */
45 
46 #include "header.h"
47 #include "keynote.h"
48 #include "assertion.h"
49 #include "signature.h"
50 
51 void
52 keygenusage(void)
53 {
54     fprintf(stderr, "Arguments:\n");
55     fprintf(stderr, "\t<AlgorithmName> <keysize> "
56 	    "<PublicKeyFile> <PrivateKeyFile> [<print-offset>] "
57 	    "[<print-length>]\n");
58 }
59 
60 /*
61  * Print the specified number of spaces.
62  */
63 void
64 print_space(FILE *fp, int n)
65 {
66     while (n--)
67       fprintf(fp, " ");
68 }
69 
70 /*
71  * Output a key, properly formatted.
72  */
73 void
74 print_key(FILE *fp, char *algname, char *key, int start, int length)
75 {
76     int i, k;
77 
78     print_space(fp, start);
79     fprintf(fp, "\"%s", algname);
80 
81     for (i = 0, k = strlen(algname) + 2; i < strlen(key); i++, k++)
82     {
83 	if (k == length)
84 	{
85 	    if (i == strlen(key))
86 	    {
87 		fprintf(fp, "\"\n");
88 		return;
89 	    }
90 
91 	    fprintf(fp, "\\\n");
92 	    print_space(fp, start);
93 	    i--;
94 	    k = 0;
95 	}
96 	else
97 	  fprintf(fp, "%c", key[i]);
98     }
99 
100     fprintf(fp, "\"\n");
101 }
102 
103 void
104 keynote_keygen(int argc, char *argv[])
105 {
106     int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH;
107 #if defined(CRYPTO) || defined(PGPLIB)
108     char *foo, *privalgname, seed[SEED_LEN];
109     int alg, enc, ienc, len = 0, counter;
110     struct keynote_deckey dc;
111     unsigned long h;
112     DSA *dsa;
113     RSA *rsa;
114     FILE *fp;
115 #endif /* CRYPTO || PGPLIB */
116     char *algname;
117 
118     if ((argc != 5) && (argc != 6) && (argc != 7))
119     {
120 	keygenusage();
121 	exit(0);
122     }
123 
124     /* Fix algorithm name */
125     if (argv[1][strlen(argv[1]) - 1] != ':')
126     {
127         fprintf(stderr, "Algorithm name [%s] should be terminated with a "
128 		"colon, fixing.\n", argv[1]);
129 	algname = (char *) calloc(strlen(argv[1]) + 2, sizeof(char));
130 	if (algname == (char *) NULL)
131 	{
132 	    perror("calloc()");
133 	    exit(1);
134 	}
135 
136 	strcpy(algname, argv[1]);
137 	algname[strlen(algname)] = ':';
138     }
139     else
140 	algname = argv[1];
141 
142     if (argc > 5)
143     {
144 	begin = atoi(argv[5]);
145 	if (begin <= -1)
146 	{
147 	    fprintf(stderr, "Erroneous value for print-offset parameter.\n");
148 	    exit(1);
149 	}
150     }
151 
152     if (argc > 6)
153     {
154 	prlen = atoi(argv[6]);
155 	if (prlen <= 0)
156 	{
157 	    fprintf(stderr, "Erroneous value for print-length parameter.\n");
158 	    exit(1);
159 	}
160     }
161 
162     if (strlen(algname) + 2 > prlen)
163     {
164 	fprintf(stderr, "Parameter ``print-length'' should be larger "
165 		"than the length of AlgorithmName (%lu)\n",
166 		(unsigned long) strlen(algname));
167 	exit(1);
168     }
169 
170 #if defined(CRYPTO) || defined(PGPLIB)
171     alg = keynote_get_key_algorithm(algname, &enc, &ienc);
172     len = atoi(argv[2]);
173 
174     if (len <= 0)
175     {
176 	fprintf(stderr, "Invalid specified keysize %d\n", len);
177 	exit(1);
178     }
179 
180     if ((alg == KEYNOTE_ALGORITHM_DSA) &&
181 	(ienc == INTERNAL_ENC_ASN1) &&
182 	((enc == ENCODING_HEX) || (enc == ENCODING_BASE64)))
183     {
184         if (RAND_bytes(seed, SEED_LEN) == 0)
185         {
186             fprintf(stderr, "Failed to acquire %d random bytes\n", SEED_LEN);
187             exit(1);
188         }
189 
190 	dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL
191 #if SSLEAY_VERSION_NUMBER >= 0x0900
192 				      , NULL
193 #endif /* SSLEAY_VERSION_NUMBER */
194 				     );
195 
196 	if (dsa == (DSA *) NULL)
197 	{
198 	    ERR_print_errors_fp(stderr);
199 	    exit(1);
200 	}
201 
202 	if (DSA_generate_key(dsa) != 1)
203 	{
204 	    ERR_print_errors_fp(stderr);
205 	    exit(1);
206 	}
207 
208 	dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA;
209 	dc.dec_key = (void *) dsa;
210 
211 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
212 	if (foo == (char *) NULL)
213 	{
214 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
215 	    exit(1);
216 	}
217 
218 	if (!strcmp(argv[3], "-"))
219 	  fp = stdout;
220 	else
221 	{
222 	    fp = fopen(argv[3], "w");
223 	    if (fp == (FILE *) NULL)
224 	    {
225 		perror(argv[3]);
226 		exit(1);
227 	    }
228 	}
229 
230 	print_key(fp, algname, foo, begin, prlen);
231 	free(foo);
232 
233 	if (strcmp(argv[3], "-"))
234 	  fclose(fp);
235 
236 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
237 	if (foo == (char *) NULL)
238 	{
239 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
240 	    exit(1);
241 	}
242 
243 	if (!strcmp(argv[4], "-"))
244 	{
245 	    fp = stdout;
246 	    if (!strcmp(argv[3], "-"))
247 	      printf("===========================\n");
248 	}
249 	else
250 	{
251 	    fp = fopen(argv[4], "w");
252 	    if (fp == (FILE *) NULL)
253 	    {
254 		perror(argv[4]);
255 		exit(1);
256 	    }
257 	}
258 
259 	privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) +
260 				      strlen(foo) + 1, sizeof(char));
261 	if (privalgname == (char *) NULL)
262 	{
263 	    perror("calloc()");
264 	    exit(1);
265 	}
266 	sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
267 	print_key(fp, privalgname, foo, begin, prlen);
268 	free(privalgname);
269 	free(foo);
270 
271 	if (strcmp(argv[4], "-"))
272 	  fclose(fp);
273 
274 	exit(0);
275     }
276 
277     if ((alg == KEYNOTE_ALGORITHM_RSA) &&
278 	(ienc == INTERNAL_ENC_PKCS1) &&
279 	((enc == ENCODING_HEX) || (enc == ENCODING_BASE64)))
280     {
281 	rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL
282 #if SSLEAY_VERSION_NUMBER >= 0x0900
283 			       , NULL
284 #endif /* SSLEAY_VERSION_NUMBER */
285 				     );
286 
287 	if (rsa == (RSA *) NULL)
288 	{
289 	    ERR_print_errors_fp(stderr);
290 	    exit(1);
291 	}
292 
293 	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
294 	dc.dec_key = (void *) rsa;
295 
296 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
297 	if (foo == (char *) NULL)
298 	{
299 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
300 	    exit(1);
301 	}
302 
303 	if (!strcmp(argv[3], "-"))
304 	  fp = stdout;
305 	else
306 	{
307 	    fp = fopen(argv[3], "w");
308 	    if (fp == (FILE *) NULL)
309 	    {
310 		perror(argv[3]);
311 		exit(1);
312 	    }
313 	}
314 
315 	print_key(fp, algname, foo, begin, prlen);
316 	free(foo);
317 
318 	if (strcmp(argv[3], "-"))
319 	  fclose(fp);
320 
321 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
322 	if (foo == (char *) NULL)
323 	{
324 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
325 	    exit(1);
326 	}
327 
328 	if (!strcmp(argv[4], "-"))
329 	{
330 	    fp = stdout;
331 	    if (!strcmp(argv[3], "-"))
332 	      printf("===========================\n");
333 	}
334 	else
335 	{
336 	    fp = fopen(argv[4], "w");
337 	    if (fp == (FILE *) NULL)
338 	    {
339 		perror(argv[4]);
340 		exit(1);
341 	    }
342 	}
343 
344 	privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) +
345 				      strlen(foo) + 1, sizeof(char));
346 	if (privalgname == (char *) NULL)
347 	{
348 	    perror("calloc()");
349 	    exit(1);
350 	}
351 	sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
352 	print_key(fp, privalgname, foo, begin, prlen);
353 	free(privalgname);
354 	free(foo);
355 
356 	if (strcmp(argv[4], "-"))
357 	  fclose(fp);
358 
359 	exit(0);
360     }
361 
362     /* More algorithms here */
363 #endif /* CRYPTO */
364 
365     fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname);
366     exit(1);
367 }
368