Browse Source

Add support for reading random data from "bcrypt" on Windows

This fixes #577

Patch inspired by the same, but simplified after reading the docs.

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 2 years ago
parent
commit
bc59fb82b8
6 changed files with 49 additions and 0 deletions
  1. 10 0
      CMakeLists.txt
  2. 1 0
      helper.pl
  3. 15 0
      src/headers/tomcrypt_cfg.h
  4. 3 0
      src/headers/tomcrypt_custom.h
  5. 3 0
      src/misc/crypt/crypt.c
  6. 17 0
      src/prngs/rng_get_bytes.c

+ 10 - 0
CMakeLists.txt

@@ -94,6 +94,16 @@ if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
     list(APPEND LTC_C_FLAGS -no-undefined)
     list(APPEND LTC_C_FLAGS -no-undefined)
 endif()
 endif()
 
 
+if(MSVC)
+    cmake_push_check_state()
+        check_symbol_exists(BCryptGenRandom bcrypt.h BCRYPT_AVAILABLE)
+    cmake_pop_check_state()
+    if (BCRYPT_AVAILABLE)
+        target_link_libraries(${PROJECT_NAME} PRIVATE Bcrypt)
+        list(APPEND LTC_C_FLAGS -DLTC_WIN32_BCRYPT)
+    endif()
+endif()
+
 # If the user set the environment variables at generate-time, append them
 # If the user set the environment variables at generate-time, append them
 # in order to allow overriding our defaults.
 # in order to allow overriding our defaults.
 # ${LTC_CFLAGS} means the user passed it via sth like:
 # ${LTC_CFLAGS} means the user passed it via sth like:

+ 1 - 0
helper.pl

@@ -71,6 +71,7 @@ sub check_source {
         my $n = $1;
         my $n = $1;
         push @{$troubles->{invalid_macro_name}}, "$lineno($n)"
         push @{$troubles->{invalid_macro_name}}, "$lineno($n)"
                 unless ($file eq 'src/headers/tomcrypt_cfg.h' &&  $n eq '__has_builtin') ||
                 unless ($file eq 'src/headers/tomcrypt_cfg.h' &&  $n eq '__has_builtin') ||
+                       ($file eq 'src/headers/tomcrypt_cfg.h' &&  $n eq '_WIN32_WINNT') ||
                        ($file eq 'src/prngs/rng_get_bytes.c' &&  $n eq '_WIN32_WINNT');
                        ($file eq 'src/prngs/rng_get_bytes.c' &&  $n eq '_WIN32_WINNT');
       }
       }
       $lineno++;
       $lineno++;

+ 15 - 0
src/headers/tomcrypt_cfg.h

@@ -300,6 +300,21 @@ typedef unsigned long ltc_mp_digit;
    #define LTC_ALIGN(n)
    #define LTC_ALIGN(n)
 #endif
 #endif
 
 
+/* Choose Windows Vista as minimum Version if we're compiling with at least VS2019
+ * This is done in order to test the bcrypt RNG and can still be overridden by the user. */
+#if defined(_MSC_VER) && _MSC_VER >= 1920
+#   ifndef _WIN32_WINNT
+#      define _WIN32_WINNT 0x0600
+#   endif
+#   ifndef WINVER
+#      define WINVER 0x0600
+#   endif
+#endif
+
+#if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && !defined(LTC_WIN32_BCRYPT)
+#   define LTC_WIN32_BCRYPT
+#endif
+
 /* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code
 /* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code
  * before including `tomcrypt.h` to disable this functionality.
  * before including `tomcrypt.h` to disable this functionality.
  */
  */

+ 3 - 0
src/headers/tomcrypt_custom.h

@@ -333,11 +333,14 @@
 /* Greg's SOBER128 stream cipher based PRNG */
 /* Greg's SOBER128 stream cipher based PRNG */
 #define LTC_SOBER128
 #define LTC_SOBER128
 
 
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
 /* the *nix style /dev/random device */
 /* the *nix style /dev/random device */
 #define LTC_DEVRANDOM
 #define LTC_DEVRANDOM
 /* try /dev/urandom before trying /dev/random
 /* try /dev/urandom before trying /dev/random
  * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */
  * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */
 #define LTC_TRY_URANDOM_FIRST
 #define LTC_TRY_URANDOM_FIRST
+#endif /* not Windows */
+
 /* rng_get_bytes() */
 /* rng_get_bytes() */
 #define LTC_RNG_GET_BYTES
 #define LTC_RNG_GET_BYTES
 /* rng_make_prng() */
 /* rng_make_prng() */

+ 3 - 0
src/misc/crypt/crypt.c

@@ -324,6 +324,9 @@ const char *crypt_build_settings =
 #if defined(LTC_SOBER128)
 #if defined(LTC_SOBER128)
     "   SOBER128\n"
     "   SOBER128\n"
 #endif
 #endif
+#if defined(LTC_WIN32_BCRYPT)
+    "   WIN32_BCRYPT\n"
+#endif
 
 
     "\nPK Crypto:\n"
     "\nPK Crypto:\n"
 #if defined(LTC_MRSA)
 #if defined(LTC_MRSA)

+ 17 - 0
src/prngs/rng_get_bytes.c

@@ -82,6 +82,22 @@ static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len,
 
 
 /* Try the Microsoft CSP */
 /* Try the Microsoft CSP */
 #if defined(_WIN32) || defined(_WIN32_WCE)
 #if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(LTC_WIN32_BCRYPT)
+
+#include <windows.h>
+#include <bcrypt.h>
+#pragma comment(lib, "bcrypt.lib")
+
+static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
+                               void (*callback)(void))
+{
+   LTC_UNUSED_PARAM(callback);
+
+   return BCRYPT_SUCCESS(BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) ? len : 0;
+}
+
+#else
+
 #ifndef _WIN32_WINNT
 #ifndef _WIN32_WINNT
   #define _WIN32_WINNT 0x0501
   #define _WIN32_WINNT 0x0501
 #endif
 #endif
@@ -112,6 +128,7 @@ static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
 
 
    return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0;
    return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0;
 }
 }
+#endif /* Old WIN32 versions */
 #endif /* WIN32 */
 #endif /* WIN32 */
 
 
 /**
 /**