xref: /freebsd/crypto/openssl/apps/rand.c (revision cbd30a72ca196976c1c700400ecd424baa1b9c16)
1 /* apps/rand.c */
2 /* ====================================================================
3  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55 
56 #include "apps.h"
57 
58 #include <ctype.h>
59 #include <stdio.h>
60 #include <string.h>
61 
62 #include <openssl/bio.h>
63 #include <openssl/err.h>
64 #include <openssl/rand.h>
65 
66 #undef PROG
67 #define PROG rand_main
68 
69 /*-
70  * -out file         - write to file
71  * -rand file:file   - PRNG seed files
72  * -base64           - base64 encode output
73  * -hex              - hex encode output
74  * num               - write 'num' bytes
75  */
76 
77 int MAIN(int, char **);
78 
79 int MAIN(int argc, char **argv)
80 {
81     int i, r, ret = 1;
82     int badopt;
83     char *outfile = NULL;
84     char *inrand = NULL;
85     int base64 = 0;
86     int hex = 0;
87     BIO *out = NULL;
88     int num = -1;
89     ENGINE *e = NULL;
90     char *engine = NULL;
91 
92     apps_startup();
93 
94     if (bio_err == NULL)
95         if ((bio_err = BIO_new(BIO_s_file())) != NULL)
96             BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
97 
98     if (!load_config(bio_err, NULL))
99         goto err;
100 
101     badopt = 0;
102     i = 0;
103     while (!badopt && argv[++i] != NULL) {
104         if (strcmp(argv[i], "-out") == 0) {
105             if ((argv[i + 1] != NULL) && (outfile == NULL))
106                 outfile = argv[++i];
107             else
108                 badopt = 1;
109         }
110 #ifndef OPENSSL_NO_ENGINE
111         else if (strcmp(argv[i], "-engine") == 0) {
112             if ((argv[i + 1] != NULL) && (engine == NULL))
113                 engine = argv[++i];
114             else
115                 badopt = 1;
116         }
117 #endif
118         else if (strcmp(argv[i], "-rand") == 0) {
119             if ((argv[i + 1] != NULL) && (inrand == NULL))
120                 inrand = argv[++i];
121             else
122                 badopt = 1;
123         } else if (strcmp(argv[i], "-base64") == 0) {
124             if (!base64)
125                 base64 = 1;
126             else
127                 badopt = 1;
128         } else if (strcmp(argv[i], "-hex") == 0) {
129             if (!hex)
130                 hex = 1;
131             else
132                 badopt = 1;
133         } else if (isdigit((unsigned char)argv[i][0])) {
134             if (num < 0) {
135                 r = sscanf(argv[i], "%d", &num);
136                 if (r == 0 || num < 0)
137                     badopt = 1;
138             } else
139                 badopt = 1;
140         } else
141             badopt = 1;
142     }
143 
144     if (hex && base64)
145         badopt = 1;
146 
147     if (num < 0)
148         badopt = 1;
149 
150     if (badopt) {
151         BIO_printf(bio_err, "Usage: rand [options] num\n");
152         BIO_printf(bio_err, "where options are\n");
153         BIO_printf(bio_err, "-out file             - write to file\n");
154 #ifndef OPENSSL_NO_ENGINE
155         BIO_printf(bio_err,
156                    "-engine e             - use engine e, possibly a hardware device.\n");
157 #endif
158         BIO_printf(bio_err, "-rand file%cfile%c... - seed PRNG from files\n",
159                    LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
160         BIO_printf(bio_err, "-base64               - base64 encode output\n");
161         BIO_printf(bio_err, "-hex                  - hex encode output\n");
162         goto err;
163     }
164     e = setup_engine(bio_err, engine, 0);
165 
166     app_RAND_load_file(NULL, bio_err, (inrand != NULL));
167     if (inrand != NULL)
168         BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
169                    app_RAND_load_files(inrand));
170 
171     out = BIO_new(BIO_s_file());
172     if (out == NULL)
173         goto err;
174     if (outfile != NULL)
175         r = BIO_write_filename(out, outfile);
176     else {
177         r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
178 #ifdef OPENSSL_SYS_VMS
179         {
180             BIO *tmpbio = BIO_new(BIO_f_linebuffer());
181             out = BIO_push(tmpbio, out);
182         }
183 #endif
184     }
185     if (r <= 0)
186         goto err;
187 
188     if (base64) {
189         BIO *b64 = BIO_new(BIO_f_base64());
190         if (b64 == NULL)
191             goto err;
192         out = BIO_push(b64, out);
193     }
194 
195     while (num > 0) {
196         unsigned char buf[4096];
197         int chunk;
198 
199         chunk = num;
200         if (chunk > (int)sizeof(buf))
201             chunk = sizeof buf;
202         r = RAND_bytes(buf, chunk);
203         if (r <= 0)
204             goto err;
205         if (!hex)
206             BIO_write(out, buf, chunk);
207         else {
208             for (i = 0; i < chunk; i++)
209                 BIO_printf(out, "%02x", buf[i]);
210         }
211         num -= chunk;
212     }
213     if (hex)
214         BIO_puts(out, "\n");
215     (void)BIO_flush(out);
216 
217     app_RAND_write_file(NULL, bio_err);
218     ret = 0;
219 
220  err:
221     ERR_print_errors(bio_err);
222     release_engine(e);
223     if (out)
224         BIO_free_all(out);
225     apps_shutdown();
226     OPENSSL_EXIT(ret);
227 }
228