1{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
3 Maintainer: Thomas.DuBuisson@gmail.com
7 Obtain entropy from system sources or x86 RDRAND when available.
10module System.EntropyWindows
17import Control.Monad (liftM, when)
18import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
19import Foreign (allocaBytes)
20import Data.ByteString as B
21import Data.ByteString.Internal as BI
22import Data.Int (Int32)
24import Data.Word (Word32, Word8)
25import Foreign.C.String (CString, withCString)
27import Foreign.Ptr (Ptr, nullPtr, castPtr)
28import Foreign.Marshal.Alloc (alloca)
29import Foreign.Marshal.Utils (toBool)
30import Foreign.Storable (peek)
32{- C example for windows rng - taken from a blog, can't recall which one but thank you!
37 // DISCLAIMER: Don't forget to check your error codes!!
38 // I am not checking as to make the example simple...
40 HCRYPTPROV hCryptCtx = NULL;
41 BYTE randomArray[128];
43 CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
44 CryptGenRandom(hCryptCtx, 128, randomArray);
45 CryptReleaseContext(hCryptCtx, 0);
50foreign import ccall unsafe "cpu_has_rdrand"
51 c_cpu_has_rdrand :: IO CInt
53foreign import ccall unsafe "get_rand_bytes"
54 c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
56cpuHasRdRand :: IO Bool
57cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
66-- Define the constants we need from WinCrypt.h
68msDefProv = "Microsoft Base Cryptographic Provider v1.0"
71cryptVerifyContext :: Word32
72cryptVerifyContext = fromIntegral 0xF0000000
74-- Declare the required CryptoAPI imports
75foreign import stdcall unsafe "CryptAcquireContextA"
76 c_cryptAcquireCtx :: Ptr Word32 -> CString -> CString -> Word32 -> Word32 -> IO Int32
77foreign import stdcall unsafe "CryptGenRandom"
78 c_cryptGenRandom :: Word32 -> Word32 -> Ptr Word8 -> IO Int32
79foreign import stdcall unsafe "CryptReleaseContext"
80 c_cryptReleaseCtx :: Word32 -> Word32 -> IO Int32
82cryptAcquireCtx :: IO Word32
84 alloca $ \handlePtr ->
85 withCString msDefProv $ \provName -> do
86 stat <- c_cryptAcquireCtx handlePtr nullPtr provName provRSAFull cryptVerifyContext
89 else fail "c_cryptAcquireCtx"
91cryptGenRandom :: Word32 -> Int -> IO B.ByteString
93 BI.create i $ \c_buffer -> do
94 stat <- c_cryptGenRandom h (fromIntegral i) c_buffer
97 else fail "c_cryptGenRandom"
99cryptReleaseCtx :: Word32 -> IO ()
100cryptReleaseCtx h = do
101 stat <- c_cryptReleaseCtx h 0
104 else fail "c_cryptReleaseCtx"
106-- |Open a handle from which random data can be read
107openHandle :: IO CryptHandle
111 if b then UseRdRand `fmap` cryptAcquireCtx
114 CH `fmap` cryptAcquireCtx
116-- |Close the `CryptHandle`
117closeHandle :: CryptHandle -> IO ()
118closeHandle (CH h) = cryptReleaseCtx h
120closeHandle (UseRdRand h) = cryptReleaseCtx h
123-- |Read from `CryptHandle`
124hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
125hGetEntropy (CH h) n = cryptGenRandom h n
127hGetEntropy (UseRdRand h) n =
128 do bsRDRAND <- BI.create n $ \ptr -> do
129 r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
131 (fail "RDRand failed to gather entropy")
132 bsWinCrypt <- cryptGenRandom h n
133 return $ B.pack $ B.zipWith xor bsRDRAND bsWinCrypt
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