rand_lib.c revision 194206
11590Srgrimes/* crypto/rand/rand_lib.c */
21590Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
31590Srgrimes * All rights reserved.
41590Srgrimes *
51590Srgrimes * This package is an SSL implementation written
61590Srgrimes * by Eric Young (eay@cryptsoft.com).
71590Srgrimes * The implementation was written so as to conform with Netscapes SSL.
81590Srgrimes *
91590Srgrimes * This library is free for commercial and non-commercial use as long as
101590Srgrimes * the following conditions are aheared to.  The following conditions
111590Srgrimes * apply to all code found in this distribution, be it the RC4, RSA,
121590Srgrimes * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
131590Srgrimes * included with this distribution is covered by the same copyright terms
141590Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
151590Srgrimes *
161590Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in
171590Srgrimes * the code are not to be removed.
181590Srgrimes * If this package is used in a product, Eric Young should be given attribution
191590Srgrimes * as the author of the parts of the library used.
201590Srgrimes * This can be in the form of a textual message at program startup or
211590Srgrimes * in documentation (online or textual) provided with the package.
221590Srgrimes *
231590Srgrimes * Redistribution and use in source and binary forms, with or without
241590Srgrimes * modification, are permitted provided that the following conditions
251590Srgrimes * are met:
261590Srgrimes * 1. Redistributions of source code must retain the copyright
271590Srgrimes *    notice, this list of conditions and the following disclaimer.
281590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
291590Srgrimes *    notice, this list of conditions and the following disclaimer in the
301590Srgrimes *    documentation and/or other materials provided with the distribution.
311590Srgrimes * 3. All advertising materials mentioning features or use of this software
321590Srgrimes *    must display the following acknowledgement:
331590Srgrimes *    "This product includes cryptographic software written by
341590Srgrimes *     Eric Young (eay@cryptsoft.com)"
351590Srgrimes *    The word 'cryptographic' can be left out if the rouines from the library
361590Srgrimes *    being used are not cryptographic related :-).
3787628Sdwmalone * 4. If you include any Windows specific code (or a derivative thereof) from
3887628Sdwmalone *    the apps directory (application code) you must include an acknowledgement:
3987628Sdwmalone *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4087628Sdwmalone *
4187628Sdwmalone * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4287628Sdwmalone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4387229Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4487229Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4587229Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
461590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47102944Sdwmalone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
481590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4972109Scharnier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
501590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5123693Speter * SUCH DAMAGE.
5272109Scharnier *
5372109Scharnier * The licence and distribution terms for any publically available version or
5472109Scharnier * derivative of this code cannot be changed.  i.e. this code cannot simply be
551590Srgrimes * copied and put under another distribution licence
561590Srgrimes * [including the GNU Public Licence.]
571590Srgrimes */
581590Srgrimes
59201140Sed#include <stdio.h>
60201140Sed#include <time.h>
6172109Scharnier#include "cryptlib.h"
621590Srgrimes#include <openssl/rand.h>
6380649Syar#include "rand_lcl.h"
641590Srgrimes#ifdef OPENSSL_FIPS
6592920Simp#include <openssl/fips.h>
6692920Simp#include <openssl/fips_rand.h>
6792920Simp#endif
681590Srgrimes
691590Srgrimes#ifndef OPENSSL_NO_ENGINE
70102944Sdwmalone#include <openssl/engine.h>
711590Srgrimes#endif
7287229Smarkm
731590Srgrimesstatic const RAND_METHOD *default_RAND_meth = NULL;
741590Srgrimes
751590Srgrimes#ifdef OPENSSL_FIPS
761590Srgrimes
771590Srgrimesstatic int fips_RAND_set_rand_method(const RAND_METHOD *meth,
781590Srgrimes					const RAND_METHOD **pmeth)
791590Srgrimes	{
801590Srgrimes	*pmeth = meth;
811590Srgrimes	return 1;
8250127Simp	}
8350167Simp
841590Srgrimesstatic const RAND_METHOD *fips_RAND_get_rand_method(const RAND_METHOD **pmeth)
851590Srgrimes	{
861590Srgrimes	if (!*pmeth)
871590Srgrimes		{
881590Srgrimes		if(FIPS_mode())
891590Srgrimes			*pmeth=FIPS_rand_method();
901590Srgrimes		else
9150167Simp			*pmeth = RAND_SSLeay();
9250127Simp		}
9350127Simp
9450127Simp	if(FIPS_mode()
9550127Simp		&& *pmeth != FIPS_rand_check())
9650167Simp	    {
9750167Simp	    RANDerr(RAND_F_FIPS_RAND_GET_RAND_METHOD,RAND_R_NON_FIPS_METHOD);
9850127Simp	    return 0;
9950127Simp	    }
1001590Srgrimes
10150127Simp	return *pmeth;
10250127Simp	}
10323693Speter
1041590Srgrimesstatic int (*RAND_set_rand_method_func)(const RAND_METHOD *meth,
1051590Srgrimes						const RAND_METHOD **pmeth)
1061590Srgrimes	= fips_RAND_set_rand_method;
1071590Srgrimesstatic const RAND_METHOD *(*RAND_get_rand_method_func)
1081590Srgrimes						(const RAND_METHOD **pmeth)
1091590Srgrimes	= fips_RAND_get_rand_method;
110102944Sdwmalone
1111590Srgrimes#ifndef OPENSSL_NO_ENGINE
11287229Smarkmvoid int_RAND_set_callbacks(
113201140Sed	int (*set_rand_func)(const RAND_METHOD *meth,
1141590Srgrimes						const RAND_METHOD **pmeth),
1151590Srgrimes	const RAND_METHOD *(*get_rand_func)
116201140Sed						(const RAND_METHOD **pmeth))
117201140Sed	{
1181590Srgrimes	RAND_set_rand_method_func = set_rand_func;
1191590Srgrimes	RAND_get_rand_method_func = get_rand_func;
120201140Sed	}
1211590Srgrimes#endif
1221590Srgrimes
123201140Sedint RAND_set_rand_method(const RAND_METHOD *meth)
124201140Sed	{
1251590Srgrimes	return RAND_set_rand_method_func(meth, &default_RAND_meth);
1261590Srgrimes	}
1271590Srgrimes
1281590Srgrimesconst RAND_METHOD *RAND_get_rand_method(void)
12972109Scharnier	{
1301590Srgrimes	return RAND_get_rand_method_func(&default_RAND_meth);
1311590Srgrimes	}
1321590Srgrimes
133201140Sed#else
1341590Srgrimes
1351590Srgrimes#ifndef OPENSSL_NO_ENGINE
136201140Sed/* non-NULL if default_RAND_meth is ENGINE-provided */
1371590Srgrimesstatic ENGINE *funct_ref =NULL;
1381590Srgrimes#endif
139201140Sed
140201140Sedint RAND_set_rand_method(const RAND_METHOD *meth)
141201140Sed	{
1421590Srgrimes#ifndef OPENSSL_NO_ENGINE
143201140Sed	if(funct_ref)
1441590Srgrimes		{
1451590Srgrimes		ENGINE_finish(funct_ref);
1461590Srgrimes		funct_ref = NULL;
147201140Sed		}
1481590Srgrimes#endif
14987229Smarkm	default_RAND_meth = meth;
1501590Srgrimes	return 1;
1511590Srgrimes	}
1521590Srgrimes
153201140Sedconst RAND_METHOD *RAND_get_rand_method(void)
154201140Sed	{
155201140Sed	if (!default_RAND_meth)
1561590Srgrimes		{
1571590Srgrimes#ifndef OPENSSL_NO_ENGINE
1581590Srgrimes		ENGINE *e = ENGINE_get_default_RAND();
1591590Srgrimes		if(e)
160102944Sdwmalone			{
1611590Srgrimes			default_RAND_meth = ENGINE_get_RAND(e);
1621590Srgrimes			if(!default_RAND_meth)
1631590Srgrimes				{
1641590Srgrimes				ENGINE_finish(e);
1651590Srgrimes				e = NULL;
1661590Srgrimes				}
16723693Speter			}
1681590Srgrimes		if(e)
1691590Srgrimes			funct_ref = e;
1701590Srgrimes		else
1711590Srgrimes#endif
17223693Speter			default_RAND_meth = RAND_SSLeay();
1731590Srgrimes		}
17423693Speter	return default_RAND_meth;
17523693Speter	}
1761590Srgrimes
1771590Srgrimes#ifndef OPENSSL_NO_ENGINE
17823693Speterint RAND_set_rand_engine(ENGINE *engine)
1791590Srgrimes	{
1801590Srgrimes	const RAND_METHOD *tmp_meth = NULL;
1811590Srgrimes	if(engine)
1821590Srgrimes		{
1831590Srgrimes		if(!ENGINE_init(engine))
1841590Srgrimes			return 0;
1851590Srgrimes		tmp_meth = ENGINE_get_RAND(engine);
1861590Srgrimes		if(!tmp_meth)
1871590Srgrimes			{
1881590Srgrimes			ENGINE_finish(engine);
18923693Speter			return 0;
19023693Speter			}
1911590Srgrimes		}
1921590Srgrimes	/* This function releases any prior ENGINE so call it first */
1931590Srgrimes	RAND_set_rand_method(tmp_meth);
1941590Srgrimes	funct_ref = engine;
195201140Sed	return 1;
1961590Srgrimes	}
1975369Sjkh#endif
1985369Sjkh
1991590Srgrimes#endif
20023693Speter
2011590Srgrimesvoid RAND_cleanup(void)
2021590Srgrimes	{
2031590Srgrimes	const RAND_METHOD *meth = RAND_get_rand_method();
2041590Srgrimes	if (meth && meth->cleanup)
2055369Sjkh		meth->cleanup();
2065369Sjkh	RAND_set_rand_method(NULL);
2075369Sjkh	}
208201140Sed
209201140Sedvoid RAND_seed(const void *buf, int num)
2101590Srgrimes	{
21123693Speter	const RAND_METHOD *meth = RAND_get_rand_method();
21223693Speter	if (meth && meth->seed)
21323693Speter		meth->seed(buf,num);
21423693Speter	}
2151590Srgrimes
2161590Srgrimesvoid RAND_add(const void *buf, int num, double entropy)
2171590Srgrimes	{
218102944Sdwmalone	const RAND_METHOD *meth = RAND_get_rand_method();
2191590Srgrimes	if (meth && meth->add)
2201590Srgrimes		meth->add(buf,num,entropy);
2211590Srgrimes	}
22296785Sjmallett
22323693Speterint RAND_bytes(unsigned char *buf, int num)
2241590Srgrimes	{
2251590Srgrimes	const RAND_METHOD *meth = RAND_get_rand_method();
2261590Srgrimes	if (meth && meth->bytes)
2271590Srgrimes		return meth->bytes(buf,num);
228102944Sdwmalone	return(-1);
2291590Srgrimes	}
23087229Smarkm
2311590Srgrimesint RAND_pseudo_bytes(unsigned char *buf, int num)
23296785Sjmallett	{
23323693Speter	const RAND_METHOD *meth = RAND_get_rand_method();
2341590Srgrimes	if (meth && meth->pseudorand)
2351590Srgrimes		return meth->pseudorand(buf,num);
2361590Srgrimes	return(-1);
2371590Srgrimes	}
2381590Srgrimes
2391590Srgrimesint RAND_status(void)
2401590Srgrimes	{
2411590Srgrimes	const RAND_METHOD *meth = RAND_get_rand_method();
2421590Srgrimes	if (meth && meth->status)
2431590Srgrimes		return meth->status();
2441590Srgrimes	return 0;
245102944Sdwmalone	}
2461590Srgrimes