1{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
3 Maintainer: Thomas.DuBuisson@gmail.com
7 Obtain entropy from system sources.
10module System.EntropyWindows
18import Control.Monad (liftM, when)
19import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
20import System.Win32.Types (ULONG_PTR, errorWin)
21import Foreign (allocaBytes)
22import Data.ByteString as B
23import Data.ByteString.Internal as BI
24import Data.Int (Int32)
26import Data.Word (Word32, Word8)
27import Foreign.C.String (CString, withCString)
29import Foreign.Ptr (Ptr, nullPtr, castPtr)
30import Foreign.Marshal.Alloc (alloca)
31import Foreign.Marshal.Utils (toBool)
32import Foreign.Storable (peek)
34{- C example for windows rng - taken from a blog, can't recall which one but thank you!
39 // DISCLAIMER: Don't forget to check your error codes!!
40 // I am not checking as to make the example simple...
42 HCRYPTPROV hCryptCtx = NULL;
43 BYTE randomArray[128];
45 CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
46 CryptGenRandom(hCryptCtx, 128, randomArray);
47 CryptReleaseContext(hCryptCtx, 0);
52-- See .cabal wrt GCC 4.8.2 asm compilation bug
57foreign import ccall unsafe "cpu_has_rdrand"
58 c_cpu_has_rdrand :: IO CInt
60foreign import ccall unsafe "get_rand_bytes"
61 c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
63cpuHasRdRand :: IO Bool
64cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
67type HCRYPTPROV = ULONG_PTR
72-- | Get random values from the hardware RNG or return Nothing if no
73-- supported hardware RNG is available.
78hardwareRandom :: Int -> IO (Maybe B.ByteString)
83 then Just <$> BI.create n (\ptr ->
84 do r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
85 when (r /= 0) (fail "RDRand failed to gather entropy"))
88hardwareRandom _ = pure Nothing
91-- Define the constants we need from WinCrypt.h
93msDefProv = "Microsoft Base Cryptographic Provider v1.0"
96cryptVerifyContext :: Word32
97cryptVerifyContext = fromIntegral 0xF0000000
99-- Declare the required CryptoAPI imports
100foreign import stdcall unsafe "CryptAcquireContextA"
101 c_cryptAcquireCtx :: Ptr HCRYPTPROV -> CString -> CString -> Word32 -> Word32 -> IO Int32
102foreign import stdcall unsafe "CryptGenRandom"
103 c_cryptGenRandom :: HCRYPTPROV -> Word32 -> Ptr Word8 -> IO Int32
104foreign import stdcall unsafe "CryptReleaseContext"
105 c_cryptReleaseCtx :: HCRYPTPROV -> Word32 -> IO Int32
107cryptAcquireCtx :: IO HCRYPTPROV
109 alloca $ \handlePtr ->
110 withCString msDefProv $ \provName -> do
111 stat <- c_cryptAcquireCtx handlePtr nullPtr provName provRSAFull cryptVerifyContext
114 else errorWin "c_cryptAcquireCtx"
116cryptGenRandom :: HCRYPTPROV -> Int -> IO B.ByteString
118 BI.create i $ \c_buffer -> do
119 stat <- c_cryptGenRandom h (fromIntegral i) c_buffer
122 else errorWin "c_cryptGenRandom"
124cryptReleaseCtx :: HCRYPTPROV -> IO ()
125cryptReleaseCtx h = do
126 stat <- c_cryptReleaseCtx h 0
129 else errorWin "c_cryptReleaseCtx"
131-- |Open a handle from which random data can be read
132openHandle :: IO CryptHandle
133openHandle = CH `fmap` cryptAcquireCtx
135-- |Close the `CryptHandle`
136closeHandle :: CryptHandle -> IO ()
137closeHandle (CH h) = cryptReleaseCtx h
139-- |Read from `CryptHandle`
140hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
141hGetEntropy (CH h) n = cryptGenRandom h n
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list