155714Skris/* crypto/rand/rand_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296465Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <time.h>
61109998Smarkm#include "cryptlib.h"
6255714Skris#include <openssl/rand.h>
63194206Ssimon#include "rand_lcl.h"
64194206Ssimon#ifdef OPENSSL_FIPS
65296465Sdelphij# include <openssl/fips.h>
66296465Sdelphij# include <openssl/fips_rand.h>
67194206Ssimon#endif
68194206Ssimon
69111147Snectar#ifndef OPENSSL_NO_ENGINE
70296465Sdelphij# include <openssl/engine.h>
71111147Snectar#endif
7255714Skris
73194206Ssimonstatic const RAND_METHOD *default_RAND_meth = NULL;
74194206Ssimon
75194206Ssimon#ifdef OPENSSL_FIPS
76194206Ssimon
77194206Ssimonstatic int fips_RAND_set_rand_method(const RAND_METHOD *meth,
78296465Sdelphij                                     const RAND_METHOD **pmeth)
79296465Sdelphij{
80296465Sdelphij    *pmeth = meth;
81296465Sdelphij    return 1;
82296465Sdelphij}
83194206Ssimon
84194206Ssimonstatic const RAND_METHOD *fips_RAND_get_rand_method(const RAND_METHOD **pmeth)
85296465Sdelphij{
86296465Sdelphij    if (!*pmeth) {
87296465Sdelphij        if (FIPS_mode())
88296465Sdelphij            *pmeth = FIPS_rand_method();
89296465Sdelphij        else
90296465Sdelphij            *pmeth = RAND_SSLeay();
91296465Sdelphij    }
92194206Ssimon
93296465Sdelphij    if (FIPS_mode()
94296465Sdelphij        && *pmeth != FIPS_rand_check()) {
95296465Sdelphij        RANDerr(RAND_F_FIPS_RAND_GET_RAND_METHOD, RAND_R_NON_FIPS_METHOD);
96296465Sdelphij        return 0;
97296465Sdelphij    }
98194206Ssimon
99296465Sdelphij    return *pmeth;
100296465Sdelphij}
101194206Ssimon
102296465Sdelphijstatic int (*RAND_set_rand_method_func) (const RAND_METHOD *meth,
103296465Sdelphij                                         const RAND_METHOD **pmeth)
104296465Sdelphij    = fips_RAND_set_rand_method;
105194206Ssimonstatic const RAND_METHOD *(*RAND_get_rand_method_func)
106296465Sdelphij (const RAND_METHOD **pmeth)
107296465Sdelphij    = fips_RAND_get_rand_method;
108194206Ssimon
109296465Sdelphij# ifndef OPENSSL_NO_ENGINE
110296465Sdelphijvoid int_RAND_set_callbacks(int (*set_rand_func) (const RAND_METHOD *meth,
111296465Sdelphij                                                  const RAND_METHOD **pmeth),
112296465Sdelphij                            const RAND_METHOD *(*get_rand_func)
113296465Sdelphij                             (const RAND_METHOD **pmeth))
114296465Sdelphij{
115296465Sdelphij    RAND_set_rand_method_func = set_rand_func;
116296465Sdelphij    RAND_get_rand_method_func = get_rand_func;
117296465Sdelphij}
118296465Sdelphij# endif
119194206Ssimon
120194206Ssimonint RAND_set_rand_method(const RAND_METHOD *meth)
121296465Sdelphij{
122296465Sdelphij    return RAND_set_rand_method_func(meth, &default_RAND_meth);
123296465Sdelphij}
124194206Ssimon
125194206Ssimonconst RAND_METHOD *RAND_get_rand_method(void)
126296465Sdelphij{
127296465Sdelphij    return RAND_get_rand_method_func(&default_RAND_meth);
128296465Sdelphij}
129194206Ssimon
130194206Ssimon#else
131194206Ssimon
132296465Sdelphij# ifndef OPENSSL_NO_ENGINE
133109998Smarkm/* non-NULL if default_RAND_meth is ENGINE-provided */
134296465Sdelphijstatic ENGINE *funct_ref = NULL;
135296465Sdelphij# endif
13655714Skris
137109998Smarkmint RAND_set_rand_method(const RAND_METHOD *meth)
138296465Sdelphij{
139296465Sdelphij# ifndef OPENSSL_NO_ENGINE
140296465Sdelphij    if (funct_ref) {
141296465Sdelphij        ENGINE_finish(funct_ref);
142296465Sdelphij        funct_ref = NULL;
143296465Sdelphij    }
144296465Sdelphij# endif
145296465Sdelphij    default_RAND_meth = meth;
146296465Sdelphij    return 1;
147296465Sdelphij}
14855714Skris
149109998Smarkmconst RAND_METHOD *RAND_get_rand_method(void)
150296465Sdelphij{
151296465Sdelphij    if (!default_RAND_meth) {
152296465Sdelphij# ifndef OPENSSL_NO_ENGINE
153296465Sdelphij        ENGINE *e = ENGINE_get_default_RAND();
154296465Sdelphij        if (e) {
155296465Sdelphij            default_RAND_meth = ENGINE_get_RAND(e);
156296465Sdelphij            if (!default_RAND_meth) {
157296465Sdelphij                ENGINE_finish(e);
158296465Sdelphij                e = NULL;
159296465Sdelphij            }
160296465Sdelphij        }
161296465Sdelphij        if (e)
162296465Sdelphij            funct_ref = e;
163296465Sdelphij        else
164296465Sdelphij# endif
165296465Sdelphij            default_RAND_meth = RAND_SSLeay();
166296465Sdelphij    }
167296465Sdelphij    return default_RAND_meth;
168296465Sdelphij}
16955714Skris
170296465Sdelphij# ifndef OPENSSL_NO_ENGINE
171109998Smarkmint RAND_set_rand_engine(ENGINE *engine)
172296465Sdelphij{
173296465Sdelphij    const RAND_METHOD *tmp_meth = NULL;
174296465Sdelphij    if (engine) {
175296465Sdelphij        if (!ENGINE_init(engine))
176296465Sdelphij            return 0;
177296465Sdelphij        tmp_meth = ENGINE_get_RAND(engine);
178296465Sdelphij        if (!tmp_meth) {
179296465Sdelphij            ENGINE_finish(engine);
180296465Sdelphij            return 0;
181296465Sdelphij        }
182296465Sdelphij    }
183296465Sdelphij    /* This function releases any prior ENGINE so call it first */
184296465Sdelphij    RAND_set_rand_method(tmp_meth);
185296465Sdelphij    funct_ref = engine;
186296465Sdelphij    return 1;
187296465Sdelphij}
188296465Sdelphij# endif
189109998Smarkm
190194206Ssimon#endif
191194206Ssimon
19255714Skrisvoid RAND_cleanup(void)
193296465Sdelphij{
194296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
195296465Sdelphij    if (meth && meth->cleanup)
196296465Sdelphij        meth->cleanup();
197296465Sdelphij    RAND_set_rand_method(NULL);
198296465Sdelphij}
19955714Skris
20055714Skrisvoid RAND_seed(const void *buf, int num)
201296465Sdelphij{
202296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
203296465Sdelphij    if (meth && meth->seed)
204296465Sdelphij        meth->seed(buf, num);
205296465Sdelphij}
20655714Skris
20759191Skrisvoid RAND_add(const void *buf, int num, double entropy)
208296465Sdelphij{
209296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
210296465Sdelphij    if (meth && meth->add)
211296465Sdelphij        meth->add(buf, num, entropy);
212296465Sdelphij}
21355714Skris
21459191Skrisint RAND_bytes(unsigned char *buf, int num)
215296465Sdelphij{
216296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
217296465Sdelphij    if (meth && meth->bytes)
218296465Sdelphij        return meth->bytes(buf, num);
219296465Sdelphij    return (-1);
220296465Sdelphij}
22159191Skris
22259191Skrisint RAND_pseudo_bytes(unsigned char *buf, int num)
223296465Sdelphij{
224296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
225296465Sdelphij    if (meth && meth->pseudorand)
226296465Sdelphij        return meth->pseudorand(buf, num);
227296465Sdelphij    return (-1);
228296465Sdelphij}
22959191Skris
23059191Skrisint RAND_status(void)
231296465Sdelphij{
232296465Sdelphij    const RAND_METHOD *meth = RAND_get_rand_method();
233296465Sdelphij    if (meth && meth->status)
234296465Sdelphij        return meth->status();
235296465Sdelphij    return 0;
236296465Sdelphij}
237