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