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
10109998Smarkm *    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
6959191Skris/* -out file         - write to file
7059191Skris * -rand file:file   - PRNG seed files
71194206Ssimon * -base64           - base64 encode output
72194206Ssimon * -hex              - hex encode output
7359191Skris * num               - write 'num' bytes
7459191Skris */
7559191Skris
7659191Skrisint MAIN(int, char **);
7759191Skris
7859191Skrisint MAIN(int argc, char **argv)
7959191Skris	{
8059191Skris	int i, r, ret = 1;
8159191Skris	int badopt;
8259191Skris	char *outfile = NULL;
8359191Skris	char *inrand = NULL;
8459191Skris	int base64 = 0;
85194206Ssimon	int hex = 0;
8659191Skris	BIO *out = NULL;
8759191Skris	int num = -1;
88111147Snectar#ifndef OPENSSL_NO_ENGINE
89109998Smarkm	char *engine=NULL;
90111147Snectar#endif
9159191Skris
9259191Skris	apps_startup();
9359191Skris
9459191Skris	if (bio_err == NULL)
9559191Skris		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
9659191Skris			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
9759191Skris
98109998Smarkm	if (!load_config(bio_err, NULL))
99109998Smarkm		goto err;
100109998Smarkm
10159191Skris	badopt = 0;
10259191Skris	i = 0;
10359191Skris	while (!badopt && argv[++i] != NULL)
10459191Skris		{
10559191Skris		if (strcmp(argv[i], "-out") == 0)
10659191Skris			{
10759191Skris			if ((argv[i+1] != NULL) && (outfile == NULL))
10859191Skris				outfile = argv[++i];
10959191Skris			else
11059191Skris				badopt = 1;
11159191Skris			}
112111147Snectar#ifndef OPENSSL_NO_ENGINE
113109998Smarkm		else if (strcmp(argv[i], "-engine") == 0)
114109998Smarkm			{
115109998Smarkm			if ((argv[i+1] != NULL) && (engine == NULL))
116109998Smarkm				engine = argv[++i];
117109998Smarkm			else
118109998Smarkm				badopt = 1;
119109998Smarkm			}
120111147Snectar#endif
12159191Skris		else if (strcmp(argv[i], "-rand") == 0)
12259191Skris			{
12359191Skris			if ((argv[i+1] != NULL) && (inrand == NULL))
12459191Skris				inrand = argv[++i];
12559191Skris			else
12659191Skris				badopt = 1;
12759191Skris			}
12859191Skris		else if (strcmp(argv[i], "-base64") == 0)
12959191Skris			{
13059191Skris			if (!base64)
13159191Skris				base64 = 1;
13259191Skris			else
13359191Skris				badopt = 1;
13459191Skris			}
135194206Ssimon		else if (strcmp(argv[i], "-hex") == 0)
136194206Ssimon			{
137194206Ssimon			if (!hex)
138194206Ssimon				hex = 1;
139194206Ssimon			else
140194206Ssimon				badopt = 1;
141194206Ssimon			}
14268651Skris		else if (isdigit((unsigned char)argv[i][0]))
14359191Skris			{
14459191Skris			if (num < 0)
14559191Skris				{
14659191Skris				r = sscanf(argv[i], "%d", &num);
14759191Skris				if (r == 0 || num < 0)
14859191Skris					badopt = 1;
14959191Skris				}
15059191Skris			else
15159191Skris				badopt = 1;
15259191Skris			}
15359191Skris		else
15459191Skris			badopt = 1;
15559191Skris		}
15659191Skris
157194206Ssimon	if (hex && base64)
158194206Ssimon		badopt = 1;
159194206Ssimon
16059191Skris	if (num < 0)
16159191Skris		badopt = 1;
16259191Skris
16359191Skris	if (badopt)
16459191Skris		{
16559191Skris		BIO_printf(bio_err, "Usage: rand [options] num\n");
16659191Skris		BIO_printf(bio_err, "where options are\n");
167109998Smarkm		BIO_printf(bio_err, "-out file             - write to file\n");
168111147Snectar#ifndef OPENSSL_NO_ENGINE
169109998Smarkm		BIO_printf(bio_err, "-engine e             - use engine e, possibly a hardware device.\n");
170111147Snectar#endif
171109998Smarkm		BIO_printf(bio_err, "-rand file%cfile%c... - seed PRNG from files\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
172194206Ssimon		BIO_printf(bio_err, "-base64               - base64 encode output\n");
173194206Ssimon		BIO_printf(bio_err, "-hex                  - hex encode output\n");
17459191Skris		goto err;
17559191Skris		}
17659191Skris
177111147Snectar#ifndef OPENSSL_NO_ENGINE
178215697Ssimon        setup_engine(bio_err, engine, 0);
179111147Snectar#endif
180109998Smarkm
18159191Skris	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
18259191Skris	if (inrand != NULL)
18359191Skris		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
18459191Skris			app_RAND_load_files(inrand));
18559191Skris
18659191Skris	out = BIO_new(BIO_s_file());
18759191Skris	if (out == NULL)
18859191Skris		goto err;
18959191Skris	if (outfile != NULL)
19059191Skris		r = BIO_write_filename(out, outfile);
19159191Skris	else
19268651Skris		{
19359191Skris		r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
194109998Smarkm#ifdef OPENSSL_SYS_VMS
19568651Skris		{
19668651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
19768651Skris		out = BIO_push(tmpbio, out);
19868651Skris		}
19968651Skris#endif
20068651Skris		}
20159191Skris	if (r <= 0)
20259191Skris		goto err;
20359191Skris
20459191Skris	if (base64)
20559191Skris		{
20659191Skris		BIO *b64 = BIO_new(BIO_f_base64());
20759191Skris		if (b64 == NULL)
20859191Skris			goto err;
20959191Skris		out = BIO_push(b64, out);
21059191Skris		}
21159191Skris
21259191Skris	while (num > 0)
21359191Skris		{
21459191Skris		unsigned char buf[4096];
21559191Skris		int chunk;
21659191Skris
21759191Skris		chunk = num;
218160814Ssimon		if (chunk > (int)sizeof(buf))
21959191Skris			chunk = sizeof buf;
22059191Skris		r = RAND_bytes(buf, chunk);
22159191Skris		if (r <= 0)
22259191Skris			goto err;
223194206Ssimon		if (!hex)
224194206Ssimon			BIO_write(out, buf, chunk);
225194206Ssimon		else
226194206Ssimon			{
227194206Ssimon			for (i = 0; i < chunk; i++)
228194206Ssimon				BIO_printf(out, "%02x", buf[i]);
229194206Ssimon			}
23059191Skris		num -= chunk;
23159191Skris		}
232194206Ssimon	if (hex)
233194206Ssimon		BIO_puts(out, "\n");
234194206Ssimon	(void)BIO_flush(out);
23559191Skris
23659191Skris	app_RAND_write_file(NULL, bio_err);
23759191Skris	ret = 0;
23859191Skris
23959191Skriserr:
24059191Skris	ERR_print_errors(bio_err);
24159191Skris	if (out)
24259191Skris		BIO_free_all(out);
243109998Smarkm	apps_shutdown();
244109998Smarkm	OPENSSL_EXIT(ret);
24559191Skris	}
246