159191Skris/* apps/rand.c */
2109998Smarkm/* ====================================================================
3109998Smarkm * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4109998Smarkm *
5109998Smarkm * Redistribution and use in source and binary forms, with or without
6109998Smarkm * modification, are permitted provided that the following conditions
7109998Smarkm * are met:
8109998Smarkm *
9109998Smarkm * 1. Redistributions of source code must retain the above copyright
10280304Sjkim *    notice, this list of conditions and the following disclaimer.
11109998Smarkm *
12109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
13109998Smarkm *    notice, this list of conditions and the following disclaimer in
14109998Smarkm *    the documentation and/or other materials provided with the
15109998Smarkm *    distribution.
16109998Smarkm *
17109998Smarkm * 3. All advertising materials mentioning features or use of this
18109998Smarkm *    software must display the following acknowledgment:
19109998Smarkm *    "This product includes software developed by the OpenSSL Project
20109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21109998Smarkm *
22109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23109998Smarkm *    endorse or promote products derived from this software without
24109998Smarkm *    prior written permission. For written permission, please contact
25109998Smarkm *    openssl-core@openssl.org.
26109998Smarkm *
27109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
28109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
29109998Smarkm *    permission of the OpenSSL Project.
30109998Smarkm *
31109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
32109998Smarkm *    acknowledgment:
33109998Smarkm *    "This product includes software developed by the OpenSSL Project
34109998Smarkm *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35109998Smarkm *
36109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
48109998Smarkm * ====================================================================
49109998Smarkm *
50109998Smarkm * This product includes cryptographic software written by Eric Young
51109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
52109998Smarkm * Hudson (tjh@cryptsoft.com).
53109998Smarkm *
54109998Smarkm */
5559191Skris
5659191Skris#include "apps.h"
5759191Skris
5859191Skris#include <ctype.h>
5959191Skris#include <stdio.h>
6059191Skris#include <string.h>
6159191Skris
6259191Skris#include <openssl/bio.h>
6359191Skris#include <openssl/err.h>
6459191Skris#include <openssl/rand.h>
6559191Skris
6659191Skris#undef PROG
6759191Skris#define PROG rand_main
6859191Skris
69280304Sjkim/*-
70280304Sjkim * -out file         - write to file
7159191Skris * -rand file:file   - PRNG seed files
72194206Ssimon * -base64           - base64 encode output
73194206Ssimon * -hex              - hex encode output
7459191Skris * num               - write 'num' bytes
7559191Skris */
7659191Skris
7759191Skrisint MAIN(int, char **);
7859191Skris
7959191Skrisint MAIN(int argc, char **argv)
80280304Sjkim{
81280304Sjkim    int i, r, ret = 1;
82280304Sjkim    int badopt;
83280304Sjkim    char *outfile = NULL;
84280304Sjkim    char *inrand = NULL;
85280304Sjkim    int base64 = 0;
86280304Sjkim    int hex = 0;
87280304Sjkim    BIO *out = NULL;
88280304Sjkim    int num = -1;
89111147Snectar#ifndef OPENSSL_NO_ENGINE
90280304Sjkim    char *engine = NULL;
91111147Snectar#endif
9259191Skris
93280304Sjkim    apps_startup();
9459191Skris
95280304Sjkim    if (bio_err == NULL)
96280304Sjkim        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
97280304Sjkim            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
9859191Skris
99280304Sjkim    if (!load_config(bio_err, NULL))
100280304Sjkim        goto err;
101109998Smarkm
102280304Sjkim    badopt = 0;
103280304Sjkim    i = 0;
104280304Sjkim    while (!badopt && argv[++i] != NULL) {
105280304Sjkim        if (strcmp(argv[i], "-out") == 0) {
106280304Sjkim            if ((argv[i + 1] != NULL) && (outfile == NULL))
107280304Sjkim                outfile = argv[++i];
108280304Sjkim            else
109280304Sjkim                badopt = 1;
110280304Sjkim        }
111111147Snectar#ifndef OPENSSL_NO_ENGINE
112280304Sjkim        else if (strcmp(argv[i], "-engine") == 0) {
113280304Sjkim            if ((argv[i + 1] != NULL) && (engine == NULL))
114280304Sjkim                engine = argv[++i];
115280304Sjkim            else
116280304Sjkim                badopt = 1;
117280304Sjkim        }
118111147Snectar#endif
119280304Sjkim        else if (strcmp(argv[i], "-rand") == 0) {
120280304Sjkim            if ((argv[i + 1] != NULL) && (inrand == NULL))
121280304Sjkim                inrand = argv[++i];
122280304Sjkim            else
123280304Sjkim                badopt = 1;
124280304Sjkim        } else if (strcmp(argv[i], "-base64") == 0) {
125280304Sjkim            if (!base64)
126280304Sjkim                base64 = 1;
127280304Sjkim            else
128280304Sjkim                badopt = 1;
129280304Sjkim        } else if (strcmp(argv[i], "-hex") == 0) {
130280304Sjkim            if (!hex)
131280304Sjkim                hex = 1;
132280304Sjkim            else
133280304Sjkim                badopt = 1;
134280304Sjkim        } else if (isdigit((unsigned char)argv[i][0])) {
135280304Sjkim            if (num < 0) {
136280304Sjkim                r = sscanf(argv[i], "%d", &num);
137280304Sjkim                if (r == 0 || num < 0)
138280304Sjkim                    badopt = 1;
139280304Sjkim            } else
140280304Sjkim                badopt = 1;
141280304Sjkim        } else
142280304Sjkim            badopt = 1;
143280304Sjkim    }
14459191Skris
145280304Sjkim    if (hex && base64)
146280304Sjkim        badopt = 1;
147194206Ssimon
148280304Sjkim    if (num < 0)
149280304Sjkim        badopt = 1;
150280304Sjkim
151280304Sjkim    if (badopt) {
152280304Sjkim        BIO_printf(bio_err, "Usage: rand [options] num\n");
153280304Sjkim        BIO_printf(bio_err, "where options are\n");
154280304Sjkim        BIO_printf(bio_err, "-out file             - write to file\n");
155111147Snectar#ifndef OPENSSL_NO_ENGINE
156280304Sjkim        BIO_printf(bio_err,
157280304Sjkim                   "-engine e             - use engine e, possibly a hardware device.\n");
158111147Snectar#endif
159280304Sjkim        BIO_printf(bio_err, "-rand file%cfile%c... - seed PRNG from files\n",
160280304Sjkim                   LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
161280304Sjkim        BIO_printf(bio_err, "-base64               - base64 encode output\n");
162280304Sjkim        BIO_printf(bio_err, "-hex                  - hex encode output\n");
163280304Sjkim        goto err;
164280304Sjkim    }
165111147Snectar#ifndef OPENSSL_NO_ENGINE
166280304Sjkim    setup_engine(bio_err, engine, 0);
167111147Snectar#endif
168109998Smarkm
169280304Sjkim    app_RAND_load_file(NULL, bio_err, (inrand != NULL));
170280304Sjkim    if (inrand != NULL)
171280304Sjkim        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
172280304Sjkim                   app_RAND_load_files(inrand));
17359191Skris
174280304Sjkim    out = BIO_new(BIO_s_file());
175280304Sjkim    if (out == NULL)
176280304Sjkim        goto err;
177280304Sjkim    if (outfile != NULL)
178280304Sjkim        r = BIO_write_filename(out, outfile);
179280304Sjkim    else {
180280304Sjkim        r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
181109998Smarkm#ifdef OPENSSL_SYS_VMS
182280304Sjkim        {
183280304Sjkim            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
184280304Sjkim            out = BIO_push(tmpbio, out);
185280304Sjkim        }
18668651Skris#endif
187280304Sjkim    }
188280304Sjkim    if (r <= 0)
189280304Sjkim        goto err;
19059191Skris
191280304Sjkim    if (base64) {
192280304Sjkim        BIO *b64 = BIO_new(BIO_f_base64());
193280304Sjkim        if (b64 == NULL)
194280304Sjkim            goto err;
195280304Sjkim        out = BIO_push(b64, out);
196280304Sjkim    }
19759191Skris
198280304Sjkim    while (num > 0) {
199280304Sjkim        unsigned char buf[4096];
200280304Sjkim        int chunk;
20159191Skris
202280304Sjkim        chunk = num;
203280304Sjkim        if (chunk > (int)sizeof(buf))
204280304Sjkim            chunk = sizeof buf;
205280304Sjkim        r = RAND_bytes(buf, chunk);
206280304Sjkim        if (r <= 0)
207280304Sjkim            goto err;
208280304Sjkim        if (!hex)
209280304Sjkim            BIO_write(out, buf, chunk);
210280304Sjkim        else {
211280304Sjkim            for (i = 0; i < chunk; i++)
212280304Sjkim                BIO_printf(out, "%02x", buf[i]);
213280304Sjkim        }
214280304Sjkim        num -= chunk;
215280304Sjkim    }
216280304Sjkim    if (hex)
217280304Sjkim        BIO_puts(out, "\n");
218280304Sjkim    (void)BIO_flush(out);
219280304Sjkim
220280304Sjkim    app_RAND_write_file(NULL, bio_err);
221280304Sjkim    ret = 0;
222280304Sjkim
223280304Sjkim err:
224280304Sjkim    ERR_print_errors(bio_err);
225280304Sjkim    if (out)
226280304Sjkim        BIO_free_all(out);
227280304Sjkim    apps_shutdown();
228280304Sjkim    OPENSSL_EXIT(ret);
229280304Sjkim}
230