mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers entropy_poll.c Source File

entropy_poll.c

00001 /*
00002  *  Platform-specific and custom entropy polling functions
00003  *
00004  *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
00005  *
00006  *  This file is part of mbed TLS (https://tls.mbed.org)
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License along
00019  *  with this program; if not, write to the Free Software Foundation, Inc.,
00020  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  */
00022 
00023 #if !defined(POLARSSL_CONFIG_FILE)
00024 #include "polarssl/config.h"
00025 #else
00026 #include POLARSSL_CONFIG_FILE
00027 #endif
00028 
00029 #if defined(POLARSSL_ENTROPY_C)
00030 
00031 #include "polarssl/entropy.h"
00032 #include "polarssl/entropy_poll.h"
00033 
00034 #if defined(POLARSSL_TIMING_C)
00035 #include <string.h>
00036 #include "polarssl/timing.h"
00037 #endif
00038 #if defined(POLARSSL_HAVEGE_C)
00039 #include "polarssl/havege.h"
00040 #endif
00041 
00042 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
00043 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
00044 
00045 #if !defined(_WIN32_WINNT)
00046 #define _WIN32_WINNT 0x0400
00047 #endif
00048 #include <windows.h>
00049 #include <wincrypt.h>
00050 
00051 int platform_entropy_poll( void *data, unsigned char *output, size_t len,
00052                            size_t *olen )
00053 {
00054     HCRYPTPROV provider;
00055     ((void) data);
00056     *olen = 0;
00057 
00058     if( CryptAcquireContext( &provider, NULL, NULL,
00059                               PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
00060     {
00061         return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00062     }
00063 
00064     if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
00065         return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00066 
00067     CryptReleaseContext( provider, 0 );
00068     *olen = len;
00069 
00070     return( 0 );
00071 }
00072 #else /* _WIN32 && !EFIX64 && !EFI32 */
00073 
00074 /*
00075  * Test for Linux getrandom() support.
00076  * Since there is no wrapper in the libc yet, use the generic syscall wrapper
00077  * available in GNU libc and compatible libc's (eg uClibc).
00078  */
00079 #if defined(__linux__) && defined(__GLIBC__)
00080 #include <linux/version.h>
00081 #include <unistd.h>
00082 #include <sys/syscall.h>
00083 #if defined(SYS_getrandom)
00084 #define HAVE_GETRANDOM
00085 static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
00086 {
00087     return( syscall( SYS_getrandom, buf, buflen, flags ) );
00088 }
00089 
00090 #include <sys/utsname.h>
00091 /* Check if version is at least 3.17.0 */
00092 static int check_version_3_17_plus( void )
00093 {
00094     int minor;
00095     struct utsname un;
00096     const char *ver;
00097 
00098     /* Get version information */
00099     uname(&un);
00100     ver = un.release;
00101 
00102     /* Check major version; assume a single digit */
00103     if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
00104         return( -1 );
00105 
00106     if( ver[0] - '0' > 3 )
00107         return( 0 );
00108 
00109     /* Ok, so now we know major == 3, check minor.
00110      * Assume 1 or 2 digits. */
00111     if( ver[2] < '0' || ver[2] > '9' )
00112         return( -1 );
00113 
00114     minor = ver[2] - '0';
00115 
00116     if( ver[3] >= '0' && ver[3] <= '9' )
00117         minor = 10 * minor + ver[3] - '0';
00118     else if( ver [3] != '.' )
00119         return( -1 );
00120 
00121     if( minor < 17 )
00122         return( -1 );
00123 
00124     return( 0 );
00125 }
00126 static int has_getrandom = -1;
00127 #endif /* SYS_getrandom */
00128 #endif /* __linux__ */
00129 
00130 #include <stdio.h>
00131 
00132 int platform_entropy_poll( void *data,
00133                            unsigned char *output, size_t len, size_t *olen )
00134 {
00135     FILE *file;
00136     size_t ret;
00137     ((void) data);
00138 
00139 #if defined(HAVE_GETRANDOM)
00140     if( has_getrandom == -1 )
00141         has_getrandom = ( check_version_3_17_plus() == 0 );
00142 
00143     if( has_getrandom )
00144     {
00145         int ret;
00146 
00147         if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
00148             return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00149 
00150         *olen = ret;
00151         return( 0 );
00152     }
00153 #endif /* HAVE_GETRANDOM */
00154 
00155     *olen = 0;
00156 
00157     file = fopen( "/dev/urandom", "rb" );
00158     if( file == NULL )
00159         return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00160 
00161     ret = fread( output, 1, len, file );
00162     if( ret != len )
00163     {
00164         fclose( file );
00165         return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00166     }
00167 
00168     fclose( file );
00169     *olen = len;
00170 
00171     return( 0 );
00172 }
00173 #endif /* _WIN32 && !EFIX64 && !EFI32 */
00174 #endif /* !POLARSSL_NO_PLATFORM_ENTROPY */
00175 
00176 #if defined(POLARSSL_TIMING_C)
00177 int hardclock_poll( void *data,
00178                     unsigned char *output, size_t len, size_t *olen )
00179 {
00180     unsigned long timer = hardclock();
00181     ((void) data);
00182     *olen = 0;
00183 
00184     if( len < sizeof(unsigned long) )
00185         return( 0 );
00186 
00187     memcpy( output, &timer, sizeof(unsigned long) );
00188     *olen = sizeof(unsigned long);
00189 
00190     return( 0 );
00191 }
00192 #endif /* POLARSSL_TIMING_C */
00193 
00194 #if defined(POLARSSL_HAVEGE_C)
00195 int havege_poll( void *data,
00196                  unsigned char *output, size_t len, size_t *olen )
00197 {
00198     havege_state *hs = (havege_state *) data;
00199     *olen = 0;
00200 
00201     if( havege_random( hs, output, len ) != 0 )
00202         return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00203 
00204     *olen = len;
00205 
00206     return( 0 );
00207 }
00208 #endif /* POLARSSL_HAVEGE_C */
00209 
00210 #endif /* POLARSSL_ENTROPY_C */
00211