1193645Ssimon/* crypto/rand/rand_lib.c */
2193645Ssimon/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3193645Ssimon * All rights reserved.
4193645Ssimon *
5193645Ssimon * This package is an SSL implementation written
6193645Ssimon * by Eric Young (eay@cryptsoft.com).
7193645Ssimon * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
9193645Ssimon * This library is free for commercial and non-commercial use as long as
10193645Ssimon * the following conditions are aheared to.  The following conditions
11193645Ssimon * apply to all code found in this distribution, be it the RC4, RSA,
12193645Ssimon * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13193645Ssimon * included with this distribution is covered by the same copyright terms
14193645Ssimon * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
16193645Ssimon * Copyright remains Eric Young's, and as such any Copyright notices in
17193645Ssimon * the code are not to be removed.
18193645Ssimon * If this package is used in a product, Eric Young should be given attribution
19193645Ssimon * as the author of the parts of the library used.
20193645Ssimon * This can be in the form of a textual message at program startup or
21193645Ssimon * in documentation (online or textual) provided with the package.
22296465Sdelphij *
23193645Ssimon * Redistribution and use in source and binary forms, with or without
24193645Ssimon * modification, are permitted provided that the following conditions
25193645Ssimon * are met:
26193645Ssimon * 1. Redistributions of source code must retain the copyright
27193645Ssimon *    notice, this list of conditions and the following disclaimer.
28193645Ssimon * 2. Redistributions in binary form must reproduce the above copyright
29193645Ssimon *    notice, this list of conditions and the following disclaimer in the
30193645Ssimon *    documentation and/or other materials provided with the distribution.
31193645Ssimon * 3. All advertising materials mentioning features or use of this software
32193645Ssimon *    must display the following acknowledgement:
33193645Ssimon *    "This product includes cryptographic software written by
34193645Ssimon *     Eric Young (eay@cryptsoft.com)"
35193645Ssimon *    The word 'cryptographic' can be left out if the rouines from the library
36193645Ssimon *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
38193645Ssimon *    the apps directory (application code) you must include an acknowledgement:
39193645Ssimon *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
41193645Ssimon * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42193645Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43193645Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44193645Ssimon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45193645Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46193645Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47193645Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48193645Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49193645Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50193645Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51193645Ssimon * SUCH DAMAGE.
52296465Sdelphij *
53193645Ssimon * The licence and distribution terms for any publically available version or
54193645Ssimon * derivative of this code cannot be changed.  i.e. this code cannot simply be
55193645Ssimon * copied and put under another distribution licence
56193645Ssimon * [including the GNU Public Licence.]
57193645Ssimon */
58193645Ssimon
59193645Ssimon#include <stdio.h>
60193645Ssimon#include <time.h>
61193645Ssimon#include "cryptlib.h"
62193645Ssimon#include "rand_lcl.h"
63193645Ssimon#include <openssl/rand.h>
64193645Ssimon#ifdef OPENSSL_FIPS
65296465Sdelphij# include <openssl/fips.h>
66296465Sdelphij# include <openssl/fips_rand.h>
67193645Ssimon#endif
68193645Ssimon
69193645Ssimon#ifndef OPENSSL_NO_ENGINE
70296465Sdelphij# include <openssl/engine.h>
71193645Ssimon#endif
72193645Ssimon
73193645Ssimon#if defined(OPENSSL_FIPS) && !defined(OPENSSL_NO_ENGINE)
74193645Ssimon
75193645Ssimon/* non-NULL if default_RAND_meth is ENGINE-provided */
76296465Sdelphijstatic ENGINE *funct_ref = NULL;
77193645Ssimon
78296465Sdelphijint eng_RAND_set_rand_method(const RAND_METHOD *meth,
79296465Sdelphij                             const RAND_METHOD **pmeth)
80296465Sdelphij{
81296465Sdelphij    if (funct_ref) {
82296465Sdelphij        ENGINE_finish(funct_ref);
83296465Sdelphij        funct_ref = NULL;
84296465Sdelphij    }
85296465Sdelphij    *pmeth = meth;
86296465Sdelphij    return 1;
87296465Sdelphij}
88193645Ssimon
89193645Ssimonconst RAND_METHOD *eng_RAND_get_rand_method(const RAND_METHOD **pmeth)
90296465Sdelphij{
91296465Sdelphij    if (!*pmeth) {
92296465Sdelphij        ENGINE *e = ENGINE_get_default_RAND();
93296465Sdelphij        if (e) {
94296465Sdelphij            *pmeth = ENGINE_get_RAND(e);
95296465Sdelphij            if (!*pmeth) {
96296465Sdelphij                ENGINE_finish(e);
97296465Sdelphij                e = NULL;
98296465Sdelphij            }
99296465Sdelphij        }
100296465Sdelphij        if (e)
101296465Sdelphij            funct_ref = e;
102296465Sdelphij        else if (FIPS_mode())
103296465Sdelphij            *pmeth = FIPS_rand_method();
104296465Sdelphij        else
105296465Sdelphij            *pmeth = RAND_SSLeay();
106296465Sdelphij    }
107193645Ssimon
108296465Sdelphij    if (FIPS_mode()
109296465Sdelphij        && *pmeth != FIPS_rand_check()) {
110296465Sdelphij        RANDerr(RAND_F_ENG_RAND_GET_RAND_METHOD, RAND_R_NON_FIPS_METHOD);
111296465Sdelphij        return 0;
112296465Sdelphij    }
113193645Ssimon
114296465Sdelphij    return *pmeth;
115296465Sdelphij}
116193645Ssimon
117193645Ssimonint RAND_set_rand_engine(ENGINE *engine)
118296465Sdelphij{
119296465Sdelphij    const RAND_METHOD *tmp_meth = NULL;
120296465Sdelphij    if (engine) {
121296465Sdelphij        if (!ENGINE_init(engine))
122296465Sdelphij            return 0;
123296465Sdelphij        tmp_meth = ENGINE_get_RAND(engine);
124296465Sdelphij        if (!tmp_meth) {
125296465Sdelphij            ENGINE_finish(engine);
126296465Sdelphij            return 0;
127296465Sdelphij        }
128296465Sdelphij    }
129296465Sdelphij    /* This function releases any prior ENGINE so call it first */
130296465Sdelphij    RAND_set_rand_method(tmp_meth);
131296465Sdelphij    funct_ref = engine;
132296465Sdelphij    return 1;
133296465Sdelphij}
134193645Ssimon
135193645Ssimonvoid int_RAND_init_engine_callbacks(void)
136296465Sdelphij{
137296465Sdelphij    static int done = 0;
138296465Sdelphij    if (done)
139296465Sdelphij        return;
140296465Sdelphij    int_RAND_set_callbacks(eng_RAND_set_rand_method,
141296465Sdelphij                           eng_RAND_get_rand_method);
142296465Sdelphij    done = 1;
143296465Sdelphij}
144193645Ssimon
145193645Ssimon#endif
146