xref: /openbsd/lib/libkeynote/keynote-keygen.c (revision 78b63d65)
1 /* $OpenBSD: keynote-keygen.c,v 1.17 2001/09/13 17:55:10 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 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 #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         RAND_bytes(seed, SEED_LEN);
185 
186 	dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL
187 #if SSLEAY_VERSION_NUMBER >= 0x0900
188 				      , NULL
189 #endif /* SSLEAY_VERSION_NUMBER */
190 				     );
191 
192 	if (dsa == (DSA *) NULL)
193 	{
194 	    ERR_print_errors_fp(stderr);
195 	    exit(1);
196 	}
197 
198 	if (DSA_generate_key(dsa) != 1)
199 	{
200 	    ERR_print_errors_fp(stderr);
201 	    exit(1);
202 	}
203 
204 	dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA;
205 	dc.dec_key = (void *) dsa;
206 
207 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
208 	if (foo == (char *) NULL)
209 	{
210 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
211 	    exit(1);
212 	}
213 
214 	if (!strcmp(argv[3], "-"))
215 	  fp = stdout;
216 	else
217 	{
218 	    fp = fopen(argv[3], "w");
219 	    if (fp == (FILE *) NULL)
220 	    {
221 		perror(argv[3]);
222 		exit(1);
223 	    }
224 	}
225 
226 	print_key(fp, algname, foo, begin, prlen);
227 	free(foo);
228 
229 	if (strcmp(argv[3], "-"))
230 	  fclose(fp);
231 
232 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
233 	if (foo == (char *) NULL)
234 	{
235 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
236 	    exit(1);
237 	}
238 
239 	if (!strcmp(argv[4], "-"))
240 	{
241 	    fp = stdout;
242 	    if (!strcmp(argv[3], "-"))
243 	      printf("===========================\n");
244 	}
245 	else
246 	{
247 	    fp = fopen(argv[4], "w");
248 	    if (fp == (FILE *) NULL)
249 	    {
250 		perror(argv[4]);
251 		exit(1);
252 	    }
253 	}
254 
255 	privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) +
256 				      strlen(foo) + 1, sizeof(char));
257 	if (privalgname == (char *) NULL)
258 	{
259 	    perror("calloc()");
260 	    exit(1);
261 	}
262 	sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
263 	print_key(fp, privalgname, foo, begin, prlen);
264 	free(privalgname);
265 	free(foo);
266 
267 	if (strcmp(argv[4], "-"))
268 	  fclose(fp);
269 
270 	exit(0);
271     }
272 
273     if ((alg == KEYNOTE_ALGORITHM_RSA) &&
274 	(ienc == INTERNAL_ENC_PKCS1) &&
275 	((enc == ENCODING_HEX) || (enc == ENCODING_BASE64)))
276     {
277 	rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL
278 #if SSLEAY_VERSION_NUMBER >= 0x0900
279 			       , NULL
280 #endif /* SSLEAY_VERSION_NUMBER */
281 				     );
282 
283 	if (rsa == (RSA *) NULL)
284 	{
285 	    ERR_print_errors_fp(stderr);
286 	    exit(1);
287 	}
288 
289 	dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
290 	dc.dec_key = (void *) rsa;
291 
292 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY);
293 	if (foo == (char *) NULL)
294 	{
295 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
296 	    exit(1);
297 	}
298 
299 	if (!strcmp(argv[3], "-"))
300 	  fp = stdout;
301 	else
302 	{
303 	    fp = fopen(argv[3], "w");
304 	    if (fp == (FILE *) NULL)
305 	    {
306 		perror(argv[3]);
307 		exit(1);
308 	    }
309 	}
310 
311 	print_key(fp, algname, foo, begin, prlen);
312 	free(foo);
313 
314 	if (strcmp(argv[3], "-"))
315 	  fclose(fp);
316 
317 	foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY);
318 	if (foo == (char *) NULL)
319 	{
320 	    fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno);
321 	    exit(1);
322 	}
323 
324 	if (!strcmp(argv[4], "-"))
325 	{
326 	    fp = stdout;
327 	    if (!strcmp(argv[3], "-"))
328 	      printf("===========================\n");
329 	}
330 	else
331 	{
332 	    fp = fopen(argv[4], "w");
333 	    if (fp == (FILE *) NULL)
334 	    {
335 		perror(argv[4]);
336 		exit(1);
337 	    }
338 	}
339 
340 	privalgname = (char *) calloc(strlen(KEYNOTE_PRIVATE_KEY_PREFIX) +
341 				      strlen(foo) + 1, sizeof(char));
342 	if (privalgname == (char *) NULL)
343 	{
344 	    perror("calloc()");
345 	    exit(1);
346 	}
347 	sprintf(privalgname, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname);
348 	print_key(fp, privalgname, foo, begin, prlen);
349 	free(privalgname);
350 	free(foo);
351 
352 	if (strcmp(argv[4], "-"))
353 	  fclose(fp);
354 
355 	exit(0);
356     }
357 
358     /* More algorithms here */
359 #endif /* CRYPTO */
360 
361     fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname);
362     exit(1);
363 }
364