xref: /freebsd/crypto/openssl/apps/rand.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /* apps/rand.c */
2 
3 #include "apps.h"
4 
5 #include <ctype.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #include <openssl/bio.h>
10 #include <openssl/err.h>
11 #include <openssl/rand.h>
12 
13 #undef PROG
14 #define PROG rand_main
15 
16 /* -out file         - write to file
17  * -rand file:file   - PRNG seed files
18  * -base64           - encode output
19  * num               - write 'num' bytes
20  */
21 
22 int MAIN(int, char **);
23 
24 int MAIN(int argc, char **argv)
25 	{
26 	int i, r, ret = 1;
27 	int badopt;
28 	char *outfile = NULL;
29 	char *inrand = NULL;
30 	int base64 = 0;
31 	BIO *out = NULL;
32 	int num = -1;
33 
34 	apps_startup();
35 
36 	if (bio_err == NULL)
37 		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
38 			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
39 
40 	badopt = 0;
41 	i = 0;
42 	while (!badopt && argv[++i] != NULL)
43 		{
44 		if (strcmp(argv[i], "-out") == 0)
45 			{
46 			if ((argv[i+1] != NULL) && (outfile == NULL))
47 				outfile = argv[++i];
48 			else
49 				badopt = 1;
50 			}
51 		else if (strcmp(argv[i], "-rand") == 0)
52 			{
53 			if ((argv[i+1] != NULL) && (inrand == NULL))
54 				inrand = argv[++i];
55 			else
56 				badopt = 1;
57 			}
58 		else if (strcmp(argv[i], "-base64") == 0)
59 			{
60 			if (!base64)
61 				base64 = 1;
62 			else
63 				badopt = 1;
64 			}
65 		else if (isdigit((unsigned char)argv[i][0]))
66 			{
67 			if (num < 0)
68 				{
69 				r = sscanf(argv[i], "%d", &num);
70 				if (r == 0 || num < 0)
71 					badopt = 1;
72 				}
73 			else
74 				badopt = 1;
75 			}
76 		else
77 			badopt = 1;
78 		}
79 
80 	if (num < 0)
81 		badopt = 1;
82 
83 	if (badopt)
84 		{
85 		BIO_printf(bio_err, "Usage: rand [options] num\n");
86 		BIO_printf(bio_err, "where options are\n");
87 		BIO_printf(bio_err, "-out file            - write to file\n");
88 		BIO_printf(bio_err, "-rand file%cfile%c...  - seed PRNG from files\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
89 		BIO_printf(bio_err, "-base64              - encode output\n");
90 		goto err;
91 		}
92 
93 	app_RAND_load_file(NULL, bio_err, (inrand != NULL));
94 	if (inrand != NULL)
95 		BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
96 			app_RAND_load_files(inrand));
97 
98 	out = BIO_new(BIO_s_file());
99 	if (out == NULL)
100 		goto err;
101 	if (outfile != NULL)
102 		r = BIO_write_filename(out, outfile);
103 	else
104 		{
105 		r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
106 #ifdef VMS
107 		{
108 		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
109 		out = BIO_push(tmpbio, out);
110 		}
111 #endif
112 		}
113 	if (r <= 0)
114 		goto err;
115 
116 	if (base64)
117 		{
118 		BIO *b64 = BIO_new(BIO_f_base64());
119 		if (b64 == NULL)
120 			goto err;
121 		out = BIO_push(b64, out);
122 		}
123 
124 	while (num > 0)
125 		{
126 		unsigned char buf[4096];
127 		int chunk;
128 
129 		chunk = num;
130 		if (chunk > sizeof buf)
131 			chunk = sizeof buf;
132 		r = RAND_bytes(buf, chunk);
133 		if (r <= 0)
134 			goto err;
135 		BIO_write(out, buf, chunk);
136 		num -= chunk;
137 		}
138 	BIO_flush(out);
139 
140 	app_RAND_write_file(NULL, bio_err);
141 	ret = 0;
142 
143 err:
144 	ERR_print_errors(bio_err);
145 	if (out)
146 		BIO_free_all(out);
147 	EXIT(ret);
148 	}
149