sandbox / mbedtls

Fork of mbedtls by Christopher Haster

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-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_ENTROPY_C)
00029 
00030 #include "mbedtls/entropy.h"
00031 #include "mbedtls/entropy_poll.h"
00032 
00033 #if defined(MBEDTLS_TIMING_C)
00034 #include <string.h>
00035 #include "mbedtls/timing.h"
00036 #endif
00037 #if defined(MBEDTLS_HAVEGE_C)
00038 #include "mbedtls/havege.h"
00039 #endif
00040 
00041 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
00042 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
00043 
00044 #if !defined(_WIN32_WINNT)
00045 #define _WIN32_WINNT 0x0400
00046 #endif
00047 #include <windows.h>
00048 #include <wincrypt.h>
00049 
00050 int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
00051                            size_t *olen )
00052 {
00053     HCRYPTPROV provider;
00054     ((void) data);
00055     *olen = 0;
00056 
00057     if( CryptAcquireContext( &provider, NULL, NULL,
00058                               PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
00059     {
00060         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00061     }
00062 
00063     if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
00064         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00065 
00066     CryptReleaseContext( provider, 0 );
00067     *olen = len;
00068 
00069     return( 0 );
00070 }
00071 #else /* _WIN32 && !EFIX64 && !EFI32 */
00072 
00073 /*
00074  * Test for Linux getrandom() support.
00075  * Since there is no wrapper in the libc yet, use the generic syscall wrapper
00076  * available in GNU libc and compatible libc's (eg uClibc).
00077  */
00078 #if defined(__linux__) && defined(__GLIBC__)
00079 #include <unistd.h>
00080 #include <sys/syscall.h>
00081 #if defined(SYS_getrandom)
00082 #define HAVE_GETRANDOM
00083 
00084 static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
00085 {
00086     /* MemSan cannot understand that the syscall writes to the buffer */
00087 #if defined(__has_feature)
00088 #if __has_feature(memory_sanitizer)
00089     memset( buf, 0, buflen );
00090 #endif
00091 #endif
00092 
00093     return( syscall( SYS_getrandom, buf, buflen, flags ) );
00094 }
00095 
00096 #include <sys/utsname.h>
00097 /* Check if version is at least 3.17.0 */
00098 static int check_version_3_17_plus( void )
00099 {
00100     int minor;
00101     struct utsname un;
00102     const char *ver;
00103 
00104     /* Get version information */
00105     uname(&un);
00106     ver = un.release;
00107 
00108     /* Check major version; assume a single digit */
00109     if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
00110         return( -1 );
00111 
00112     if( ver[0] - '0' > 3 )
00113         return( 0 );
00114 
00115     /* Ok, so now we know major == 3, check minor.
00116      * Assume 1 or 2 digits. */
00117     if( ver[2] < '0' || ver[2] > '9' )
00118         return( -1 );
00119 
00120     minor = ver[2] - '0';
00121 
00122     if( ver[3] >= '0' && ver[3] <= '9' )
00123         minor = 10 * minor + ver[3] - '0';
00124     else if( ver [3] != '.' )
00125         return( -1 );
00126 
00127     if( minor < 17 )
00128         return( -1 );
00129 
00130     return( 0 );
00131 }
00132 static int has_getrandom = -1;
00133 #endif /* SYS_getrandom */
00134 #endif /* __linux__ */
00135 
00136 #include <stdio.h>
00137 
00138 int mbedtls_platform_entropy_poll( void *data,
00139                            unsigned char *output, size_t len, size_t *olen )
00140 {
00141     FILE *file;
00142     size_t read_len;
00143     ((void) data);
00144 
00145 #if defined(HAVE_GETRANDOM)
00146     if( has_getrandom == -1 )
00147         has_getrandom = ( check_version_3_17_plus() == 0 );
00148 
00149     if( has_getrandom )
00150     {
00151         int ret;
00152 
00153         if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
00154             return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00155 
00156         *olen = ret;
00157         return( 0 );
00158     }
00159 #endif /* HAVE_GETRANDOM */
00160 
00161     *olen = 0;
00162 
00163     file = fopen( "/dev/urandom", "rb" );
00164     if( file == NULL )
00165         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00166 
00167     read_len = fread( output, 1, len, file );
00168     if( read_len != len )
00169     {
00170         fclose( file );
00171         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00172     }
00173 
00174     fclose( file );
00175     *olen = len;
00176 
00177     return( 0 );
00178 }
00179 #endif /* _WIN32 && !EFIX64 && !EFI32 */
00180 #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
00181 
00182 #if defined(MBEDTLS_TIMING_C)
00183 int mbedtls_hardclock_poll( void *data,
00184                     unsigned char *output, size_t len, size_t *olen )
00185 {
00186     unsigned long timer = mbedtls_timing_hardclock();
00187     ((void) data);
00188     *olen = 0;
00189 
00190     if( len < sizeof(unsigned long) )
00191         return( 0 );
00192 
00193     memcpy( output, &timer, sizeof(unsigned long) );
00194     *olen = sizeof(unsigned long);
00195 
00196     return( 0 );
00197 }
00198 #endif /* MBEDTLS_TIMING_C */
00199 
00200 #if defined(MBEDTLS_HAVEGE_C)
00201 int mbedtls_havege_poll( void *data,
00202                  unsigned char *output, size_t len, size_t *olen )
00203 {
00204     mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
00205     *olen = 0;
00206 
00207     if( mbedtls_havege_random( hs, output, len ) != 0 )
00208         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00209 
00210     *olen = len;
00211 
00212     return( 0 );
00213 }
00214 #endif /* MBEDTLS_HAVEGE_C */
00215 
00216 #endif /* MBEDTLS_ENTROPY_C */