2005-07-11 01:16:55 +00:00
/*
2008-10-27 11:35:07 +01:00
* Copyright ( c ) 2006 - 2007 Kungliga Tekniska Högskolan
* ( Royal Institute of Technology , Stockholm , Sweden ) .
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
2005-07-11 01:16:55 +00:00
*/
2006-11-07 06:59:56 +00:00
# include <config.h>
# include <stdio.h>
# include <stdlib.h>
# include <rand.h>
2007-06-13 05:44:24 +00:00
# include <randi.h>
2005-07-11 01:16:55 +00:00
# include <roken.h>
2007-06-13 05:44:24 +00:00
# ifndef O_BINARY
# define O_BINARY 0
# endif
2008-08-01 07:08:51 +02:00
/**
* @ page page_rand RAND - random number
*
* See the library functions here : @ ref hcrypto_rand
*/
2007-06-13 05:44:24 +00:00
const static RAND_METHOD * selected_meth = NULL ;
2008-08-01 07:08:51 +02:00
static ENGINE * selected_engine = NULL ;
2007-06-13 05:44:24 +00:00
static void
init_method ( void )
{
if ( selected_meth ! = NULL )
return ;
2009-06-08 19:06:16 +10:00
# ifdef __APPLE__
selected_meth = & hc_rand_unix_method ;
# else
2007-07-03 08:00:08 +00:00
selected_meth = & hc_rand_fortuna_method ;
2009-06-08 19:06:16 +10:00
# endif
2007-06-13 05:44:24 +00:00
}
2006-11-07 06:59:56 +00:00
2008-08-01 07:08:51 +02:00
/**
* Seed that random number generator . Secret material can securely be
* feed into the function , they will never be returned .
*
* @ param indata seed data
* @ param size length seed data
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
void
RAND_seed ( const void * indata , size_t size )
{
2007-06-13 05:44:24 +00:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
( * selected_meth - > seed ) ( indata , size ) ;
}
2008-08-01 07:08:51 +02:00
/**
* Get a random block from the random generator , can be used for key material .
*
* @ param outdata random data
* @ param size length random data
*
* @ return 1 on success , 0 on failure .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_bytes ( void * outdata , size_t size )
{
2007-06-13 05:44:24 +00:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
return ( * selected_meth - > bytes ) ( outdata , size ) ;
}
2008-08-01 07:08:51 +02:00
/**
* Reset and free memory used by the random generator .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
void
RAND_cleanup ( void )
{
2008-08-01 07:08:51 +02:00
const RAND_METHOD * meth = selected_meth ;
ENGINE * engine = selected_engine ;
selected_meth = NULL ;
selected_engine = NULL ;
if ( meth )
( * meth - > cleanup ) ( ) ;
if ( engine )
ENGINE_finish ( engine ) ;
2006-11-07 06:59:56 +00:00
}
2008-08-01 07:08:51 +02:00
/**
* Seed that random number generator . Secret material can securely be
* feed into the function , they will never be returned .
*
* @ param indata the input data .
* @ param size size of in data .
* @ param entropi entropi in data .
2008-10-27 11:35:07 +01:00
*
2008-08-01 07:08:51 +02:00
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
void
RAND_add ( const void * indata , size_t size , double entropi )
{
2007-06-13 05:44:24 +00:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
( * selected_meth - > add ) ( indata , size , entropi ) ;
}
2008-08-01 07:08:51 +02:00
/**
* Get a random block from the random generator , should NOT be used for key material .
*
* @ param outdata random data
* @ param size length random data
*
* @ return 1 on success , 0 on failure .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_pseudo_bytes ( void * outdata , size_t size )
{
2007-06-13 05:44:24 +00:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
return ( * selected_meth - > pseudorand ) ( outdata , size ) ;
}
2008-08-01 07:08:51 +02:00
/**
* Return status of the random generator
*
* @ return 1 if the random generator can deliver random data .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_status ( void )
{
2007-06-13 05:44:24 +00:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
return ( * selected_meth - > status ) ( ) ;
}
2008-08-01 07:08:51 +02:00
/**
* Set the default random method .
*
* @ param meth set the new default method .
*
* @ return 1 on success .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_set_rand_method ( const RAND_METHOD * meth )
{
2008-08-01 07:08:51 +02:00
const RAND_METHOD * old = selected_meth ;
2006-11-07 06:59:56 +00:00
selected_meth = meth ;
2008-08-01 07:08:51 +02:00
if ( old )
( * old - > cleanup ) ( ) ;
if ( selected_engine ) {
ENGINE_finish ( selected_engine ) ;
selected_engine = NULL ;
}
2006-11-07 06:59:56 +00:00
return 1 ;
}
2008-08-01 07:08:51 +02:00
/**
* Get the default random method .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
const RAND_METHOD *
RAND_get_rand_method ( void )
{
2008-08-01 07:08:51 +02:00
init_method ( ) ;
2006-11-07 06:59:56 +00:00
return selected_meth ;
}
2008-08-01 07:08:51 +02:00
/**
* Set the default random method from engine .
*
* @ param engine use engine , if NULL is passed it , old method and engine is cleared .
*
* @ return 1 on success , 0 on failure .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_set_rand_engine ( ENGINE * engine )
{
2008-08-01 07:08:51 +02:00
const RAND_METHOD * meth , * old = selected_meth ;
if ( engine ) {
ENGINE_up_ref ( engine ) ;
meth = ENGINE_get_RAND ( engine ) ;
if ( meth = = NULL ) {
ENGINE_finish ( engine ) ;
return 0 ;
}
} else {
meth = NULL ;
}
if ( old )
( * old - > cleanup ) ( ) ;
if ( selected_engine )
ENGINE_finish ( selected_engine ) ;
selected_engine = engine ;
selected_meth = meth ;
2006-11-07 06:59:56 +00:00
return 1 ;
}
2007-06-13 05:44:24 +00:00
# define RAND_FILE_SIZE 1024
2008-08-01 07:08:51 +02:00
/**
* Load a a file and feed it into RAND_seed ( ) .
*
* @ param filename name of file to read .
* @ param size minimum size to read .
*
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_load_file ( const char * filename , size_t size )
{
2007-06-13 05:44:24 +00:00
unsigned char buf [ 128 ] ;
size_t len ;
ssize_t slen ;
int fd ;
fd = open ( filename , O_RDONLY | O_BINARY , 0600 ) ;
if ( fd < 0 )
return 0 ;
2008-08-01 07:08:51 +02:00
rk_cloexec ( fd ) ;
2007-06-13 05:44:24 +00:00
len = 0 ;
while ( len < size ) {
slen = read ( fd , buf , sizeof ( buf ) ) ;
if ( slen < = 0 )
break ;
RAND_seed ( buf , slen ) ;
len + = slen ;
}
close ( fd ) ;
return len ? 1 : 0 ;
2006-11-07 06:59:56 +00:00
}
2008-08-01 07:08:51 +02:00
/**
* Write of random numbers to a file to store for later initiation with RAND_load_file ( ) .
*
* @ param filename name of file to write .
*
* @ return 1 on success and non - one on failure .
* @ ingroup hcrypto_rand
*/
2006-11-07 06:59:56 +00:00
int
RAND_write_file ( const char * filename )
{
2007-06-13 05:44:24 +00:00
unsigned char buf [ 128 ] ;
size_t len ;
int res = 0 , fd ;
fd = open ( filename , O_WRONLY | O_CREAT | O_BINARY , 0600 ) ;
if ( fd < 0 )
return 0 ;
2008-08-01 07:08:51 +02:00
rk_cloexec ( fd ) ;
2007-06-13 05:44:24 +00:00
len = 0 ;
while ( len < RAND_FILE_SIZE ) {
res = RAND_bytes ( buf , sizeof ( buf ) ) ;
if ( res ! = 1 )
break ;
if ( write ( fd , buf , sizeof ( buf ) ) ! = sizeof ( buf ) ) {
res = 0 ;
break ;
}
len + = sizeof ( buf ) ;
}
close ( fd ) ;
return res ;
2006-11-07 06:59:56 +00:00
}
2008-08-01 07:08:51 +02:00
/**
* Return the default random state filename for a user to use for
* RAND_load_file ( ) , and RAND_write_file ( ) .
*
* @ param filename buffer to hold file name .
* @ param size size of buffer filename .
*
* @ return the buffer filename or NULL on failure .
*
* @ ingroup hcrypto_rand
*/
2007-06-13 05:44:24 +00:00
const char *
RAND_file_name ( char * filename , size_t size )
2005-07-11 01:16:55 +00:00
{
2007-06-13 05:44:24 +00:00
const char * e = NULL ;
int pathp = 0 , ret ;
if ( ! issuid ( ) ) {
e = getenv ( " RANDFILE " ) ;
if ( e = = NULL ) {
e = getenv ( " HOME " ) ;
if ( e )
pathp = 1 ;
}
}
2008-10-27 11:35:07 +01:00
/*
2008-03-19 10:17:42 +11:00
* Here we really want to call getpwuid ( getuid ( ) ) but this will
* cause recursive lookups if the nss library uses
* gssapi / krb5 / hcrypto to authenticate to the ldap servers .
*/
2007-06-13 05:44:24 +00:00
if ( e = = NULL )
return NULL ;
if ( pathp )
ret = snprintf ( filename , size , " %s/.rnd " , e ) ;
else
ret = snprintf ( filename , size , " %s " , e ) ;
if ( ret < = 0 | | ret > = size )
return NULL ;
return filename ;
2005-07-11 01:16:55 +00:00
}