Annotation of src/usr.bin/openssl/dhparam.c, Revision 1.2
1.2 ! jsing 1: /* $OpenBSD: dhparam.c,v 1.1 2014/08/26 17:47:24 jsing Exp $ */
1.1 jsing 2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3: * All rights reserved.
4: *
5: * This package is an SSL implementation written
6: * by Eric Young (eay@cryptsoft.com).
7: * The implementation was written so as to conform with Netscapes SSL.
8: *
9: * This library is free for commercial and non-commercial use as long as
10: * the following conditions are aheared to. The following conditions
11: * apply to all code found in this distribution, be it the RC4, RSA,
12: * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13: * included with this distribution is covered by the same copyright terms
14: * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15: *
16: * Copyright remains Eric Young's, and as such any Copyright notices in
17: * the code are not to be removed.
18: * If this package is used in a product, Eric Young should be given attribution
19: * as the author of the parts of the library used.
20: * This can be in the form of a textual message at program startup or
21: * in documentation (online or textual) provided with the package.
22: *
23: * Redistribution and use in source and binary forms, with or without
24: * modification, are permitted provided that the following conditions
25: * are met:
26: * 1. Redistributions of source code must retain the copyright
27: * notice, this list of conditions and the following disclaimer.
28: * 2. Redistributions in binary form must reproduce the above copyright
29: * notice, this list of conditions and the following disclaimer in the
30: * documentation and/or other materials provided with the distribution.
31: * 3. All advertising materials mentioning features or use of this software
32: * must display the following acknowledgement:
33: * "This product includes cryptographic software written by
34: * Eric Young (eay@cryptsoft.com)"
35: * The word 'cryptographic' can be left out if the rouines from the library
36: * being used are not cryptographic related :-).
37: * 4. If you include any Windows specific code (or a derivative thereof) from
38: * the apps directory (application code) you must include an acknowledgement:
39: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40: *
41: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51: * SUCH DAMAGE.
52: *
53: * The licence and distribution terms for any publically available version or
54: * derivative of this code cannot be changed. i.e. this code cannot simply be
55: * copied and put under another distribution licence
56: * [including the GNU Public Licence.]
57: */
58: /* ====================================================================
59: * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
60: *
61: * Redistribution and use in source and binary forms, with or without
62: * modification, are permitted provided that the following conditions
63: * are met:
64: *
65: * 1. Redistributions of source code must retain the above copyright
66: * notice, this list of conditions and the following disclaimer.
67: *
68: * 2. Redistributions in binary form must reproduce the above copyright
69: * notice, this list of conditions and the following disclaimer in
70: * the documentation and/or other materials provided with the
71: * distribution.
72: *
73: * 3. All advertising materials mentioning features or use of this
74: * software must display the following acknowledgment:
75: * "This product includes software developed by the OpenSSL Project
76: * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77: *
78: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79: * endorse or promote products derived from this software without
80: * prior written permission. For written permission, please contact
81: * openssl-core@openssl.org.
82: *
83: * 5. Products derived from this software may not be called "OpenSSL"
84: * nor may "OpenSSL" appear in their names without prior written
85: * permission of the OpenSSL Project.
86: *
87: * 6. Redistributions of any form whatsoever must retain the following
88: * acknowledgment:
89: * "This product includes software developed by the OpenSSL Project
90: * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91: *
92: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103: * OF THE POSSIBILITY OF SUCH DAMAGE.
104: * ====================================================================
105: *
106: * This product includes cryptographic software written by Eric Young
107: * (eay@cryptsoft.com). This product includes software written by Tim
108: * Hudson (tjh@cryptsoft.com).
109: *
110: */
111:
112: #include <openssl/opensslconf.h> /* for OPENSSL_NO_DH */
113:
114: #ifndef OPENSSL_NO_DH
115:
116: #include <stdio.h>
117: #include <stdlib.h>
118: #include <string.h>
119: #include <time.h>
120:
121: #include "apps.h"
122:
123: #include <openssl/bio.h>
124: #include <openssl/bn.h>
125: #include <openssl/err.h>
126: #include <openssl/dh.h>
127: #include <openssl/pem.h>
128: #include <openssl/x509.h>
129:
130: #include <openssl/dsa.h>
131:
132: #define DEFBITS 512
133:
134: /* -inform arg - input format - default PEM (DER or PEM)
135: * -outform arg - output format - default PEM
136: * -in arg - input file - default stdin
137: * -out arg - output file - default stdout
138: * -dsaparam - read or generate DSA parameters, convert to DH
139: * -check - check the parameters are ok
140: * -noout
141: * -text
142: * -C
143: */
144:
145: static int dh_cb(int p, int n, BN_GENCB * cb);
146:
147: int dhparam_main(int, char **);
148:
149: int
150: dhparam_main(int argc, char **argv)
151: {
152: DH *dh = NULL;
153: int i, badops = 0, text = 0;
154: int dsaparam = 0;
155: BIO *in = NULL, *out = NULL;
156: int informat, outformat, check = 0, noout = 0, C = 0, ret = 1;
157: char *infile, *outfile, *prog;
158: #ifndef OPENSSL_NO_ENGINE
159: char *engine = NULL;
160: #endif
161: int num = 0, g = 0;
162:
163: infile = NULL;
164: outfile = NULL;
165: informat = FORMAT_PEM;
166: outformat = FORMAT_PEM;
167:
168: prog = argv[0];
169: argc--;
170: argv++;
171: while (argc >= 1) {
172: if (strcmp(*argv, "-inform") == 0) {
173: if (--argc < 1)
174: goto bad;
175: informat = str2fmt(*(++argv));
176: } else if (strcmp(*argv, "-outform") == 0) {
177: if (--argc < 1)
178: goto bad;
179: outformat = str2fmt(*(++argv));
180: } else if (strcmp(*argv, "-in") == 0) {
181: if (--argc < 1)
182: goto bad;
183: infile = *(++argv);
184: } else if (strcmp(*argv, "-out") == 0) {
185: if (--argc < 1)
186: goto bad;
187: outfile = *(++argv);
188: }
189: #ifndef OPENSSL_NO_ENGINE
190: else if (strcmp(*argv, "-engine") == 0) {
191: if (--argc < 1)
192: goto bad;
193: engine = *(++argv);
194: }
195: #endif
196: else if (strcmp(*argv, "-check") == 0)
197: check = 1;
198: else if (strcmp(*argv, "-text") == 0)
199: text = 1;
200: else if (strcmp(*argv, "-dsaparam") == 0)
201: dsaparam = 1;
202: else if (strcmp(*argv, "-C") == 0)
203: C = 1;
204: else if (strcmp(*argv, "-noout") == 0)
205: noout = 1;
206: else if (strcmp(*argv, "-2") == 0)
207: g = 2;
208: else if (strcmp(*argv, "-5") == 0)
209: g = 5;
210: else if (((sscanf(*argv, "%d", &num) == 0) || (num <= 0)))
211: goto bad;
212: argv++;
213: argc--;
214: }
215:
216: if (badops) {
217: bad:
218: BIO_printf(bio_err, "%s [options] [numbits]\n", prog);
219: BIO_printf(bio_err, "where options are\n");
220: BIO_printf(bio_err, " -inform arg input format - one of DER PEM\n");
221: BIO_printf(bio_err, " -outform arg output format - one of DER PEM\n");
222: BIO_printf(bio_err, " -in arg input file\n");
223: BIO_printf(bio_err, " -out arg output file\n");
224: BIO_printf(bio_err, " -dsaparam read or generate DSA parameters, convert to DH\n");
225: BIO_printf(bio_err, " -check check the DH parameters\n");
226: BIO_printf(bio_err, " -text print a text form of the DH parameters\n");
227: BIO_printf(bio_err, " -C Output C code\n");
228: BIO_printf(bio_err, " -2 generate parameters using 2 as the generator value\n");
229: BIO_printf(bio_err, " -5 generate parameters using 5 as the generator value\n");
230: BIO_printf(bio_err, " numbits number of bits in to generate (default 512)\n");
231: #ifndef OPENSSL_NO_ENGINE
232: BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n");
233: #endif
234: BIO_printf(bio_err, " -noout no output\n");
235: goto end;
236: }
237:
238: #ifndef OPENSSL_NO_ENGINE
239: setup_engine(bio_err, engine, 0);
240: #endif
241:
242: if (g && !num)
243: num = DEFBITS;
244:
245: if (dsaparam) {
246: if (g) {
247: BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n");
248: goto end;
249: }
250: } else
251: {
252: /* DH parameters */
253: if (num && !g)
254: g = 2;
255: }
256:
257: if (num) {
258:
259: BN_GENCB cb;
260: BN_GENCB_set(&cb, dh_cb, bio_err);
261: if (dsaparam) {
262: DSA *dsa = DSA_new();
263:
264: BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num);
265: if (!dsa || !DSA_generate_parameters_ex(dsa, num,
266: NULL, 0, NULL, NULL, &cb)) {
267: if (dsa)
268: DSA_free(dsa);
269: ERR_print_errors(bio_err);
270: goto end;
271: }
272: dh = DSA_dup_DH(dsa);
273: DSA_free(dsa);
274: if (dh == NULL) {
275: ERR_print_errors(bio_err);
276: goto end;
277: }
278: } else
279: {
280: dh = DH_new();
281: BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, g);
282: BIO_printf(bio_err, "This is going to take a long time\n");
283: if (!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) {
284: ERR_print_errors(bio_err);
285: goto end;
286: }
287: }
288: } else {
289:
290: in = BIO_new(BIO_s_file());
291: if (in == NULL) {
292: ERR_print_errors(bio_err);
293: goto end;
294: }
295: if (infile == NULL)
296: BIO_set_fp(in, stdin, BIO_NOCLOSE);
297: else {
298: if (BIO_read_filename(in, infile) <= 0) {
299: perror(infile);
300: goto end;
301: }
302: }
303:
304: if (informat != FORMAT_ASN1 && informat != FORMAT_PEM) {
305: BIO_printf(bio_err, "bad input format specified\n");
306: goto end;
307: }
308: if (dsaparam) {
309: DSA *dsa;
310:
311: if (informat == FORMAT_ASN1)
312: dsa = d2i_DSAparams_bio(in, NULL);
313: else /* informat == FORMAT_PEM */
314: dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);
315:
316: if (dsa == NULL) {
317: BIO_printf(bio_err, "unable to load DSA parameters\n");
318: ERR_print_errors(bio_err);
319: goto end;
320: }
321: dh = DSA_dup_DH(dsa);
322: DSA_free(dsa);
323: if (dh == NULL) {
324: ERR_print_errors(bio_err);
325: goto end;
326: }
327: } else
328: {
329: if (informat == FORMAT_ASN1)
330: dh = d2i_DHparams_bio(in, NULL);
331: else /* informat == FORMAT_PEM */
332: dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
333:
334: if (dh == NULL) {
335: BIO_printf(bio_err, "unable to load DH parameters\n");
336: ERR_print_errors(bio_err);
337: goto end;
338: }
339: }
340:
341: /* dh != NULL */
342: }
343:
344: out = BIO_new(BIO_s_file());
345: if (out == NULL) {
346: ERR_print_errors(bio_err);
347: goto end;
348: }
349: if (outfile == NULL) {
350: BIO_set_fp(out, stdout, BIO_NOCLOSE);
351: } else {
352: if (BIO_write_filename(out, outfile) <= 0) {
353: perror(outfile);
354: goto end;
355: }
356: }
357:
358:
359: if (text) {
360: DHparams_print(out, dh);
361: }
362: if (check) {
363: if (!DH_check(dh, &i)) {
364: ERR_print_errors(bio_err);
365: goto end;
366: }
367: if (i & DH_CHECK_P_NOT_PRIME)
368: printf("p value is not prime\n");
369: if (i & DH_CHECK_P_NOT_SAFE_PRIME)
370: printf("p value is not a safe prime\n");
371: if (i & DH_UNABLE_TO_CHECK_GENERATOR)
372: printf("unable to check the generator value\n");
373: if (i & DH_NOT_SUITABLE_GENERATOR)
374: printf("the g value is not a generator\n");
375: if (i == 0)
376: printf("DH parameters appear to be ok.\n");
377: }
378: if (C) {
379: unsigned char *data;
380: int len, l, bits;
381:
382: len = BN_num_bytes(dh->p);
383: bits = BN_num_bits(dh->p);
384: data = malloc(len);
385: if (data == NULL) {
386: perror("malloc");
387: goto end;
388: }
389: printf("#ifndef HEADER_DH_H\n"
390: "#include <openssl/dh.h>\n"
391: "#endif\n");
392: printf("DH *get_dh%d()\n\t{\n", bits);
393:
394: l = BN_bn2bin(dh->p, data);
395: printf("\tstatic unsigned char dh%d_p[] = {", bits);
396: for (i = 0; i < l; i++) {
397: if ((i % 12) == 0)
398: printf("\n\t\t");
399: printf("0x%02X, ", data[i]);
400: }
401: printf("\n\t\t};\n");
402:
403: l = BN_bn2bin(dh->g, data);
404: printf("\tstatic unsigned char dh%d_g[] = {", bits);
405: for (i = 0; i < l; i++) {
406: if ((i % 12) == 0)
407: printf("\n\t\t");
408: printf("0x%02X, ", data[i]);
409: }
410: printf("\n\t\t};\n");
411:
412: printf("\tDH *dh;\n\n");
413: printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n");
414: printf("\tdh->p = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n",
415: bits, bits);
416: printf("\tdh->g = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n",
417: bits, bits);
418: printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
419: printf("\t\t{ DH_free(dh); return(NULL); }\n");
420: if (dh->length)
421: printf("\tdh->length = %ld;\n", dh->length);
422: printf("\treturn(dh);\n\t}\n");
423: free(data);
424: }
425: if (!noout) {
426: if (outformat == FORMAT_ASN1)
427: i = i2d_DHparams_bio(out, dh);
428: else if (outformat == FORMAT_PEM)
429: i = PEM_write_bio_DHparams(out, dh);
430: else {
431: BIO_printf(bio_err, "bad output format specified for outfile\n");
432: goto end;
433: }
434: if (!i) {
435: BIO_printf(bio_err, "unable to write DH parameters\n");
436: ERR_print_errors(bio_err);
437: goto end;
438: }
439: }
440: ret = 0;
441:
442: end:
443: BIO_free(in);
444: if (out != NULL)
445: BIO_free_all(out);
446: if (dh != NULL)
447: DH_free(dh);
448:
449: return (ret);
450: }
451:
452: /* dh_cb is identical to dsa_cb in apps/dsaparam.c */
453: static int
454: dh_cb(int p, int n, BN_GENCB * cb)
455: {
456: char c = '*';
457:
458: if (p == 0)
459: c = '.';
460: if (p == 1)
461: c = '+';
462: if (p == 2)
463: c = '*';
464: if (p == 3)
465: c = '\n';
466: BIO_write(cb->arg, &c, 1);
467: (void) BIO_flush(cb->arg);
468: return 1;
469: }
470:
471: #endif