{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI #-}
module OpenSSL.Random
(
randBytes
, prandBytes
, add
) where
import Foreign
import Foreign.C.Types
import qualified Data.ByteString as BS
import OpenSSL.Utils
foreign import capi unsafe "openssl/rand.h RAND_bytes"
_RAND_bytes :: Ptr CChar -> CInt -> IO CInt
foreign import capi unsafe "openssl/rand.h RAND_pseudo_bytes"
_RAND_pseudo_bytes :: Ptr CChar -> CInt -> IO ()
foreign import capi unsafe "openssl/rand.h RAND_add"
_RAND_add :: Ptr CChar -> CInt -> CInt -> IO ()
randBytes :: Int
-> IO BS.ByteString
randBytes :: Int -> IO ByteString
randBytes Int
n =
Int -> (Ptr CChar -> IO ByteString) -> IO ByteString
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
n ((Ptr CChar -> IO ByteString) -> IO ByteString)
-> (Ptr CChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
bufPtr ->
do Ptr CChar -> CInt -> IO CInt
_RAND_bytes Ptr CChar
bufPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) IO CInt -> (CInt -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
CStringLen -> IO ByteString
BS.packCStringLen (Ptr CChar
bufPtr, Int
n)
prandBytes :: Int
-> IO BS.ByteString
prandBytes :: Int -> IO ByteString
prandBytes Int
n =
Int -> (Ptr CChar -> IO ByteString) -> IO ByteString
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray Int
n ((Ptr CChar -> IO ByteString) -> IO ByteString)
-> (Ptr CChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
bufPtr ->
do Ptr CChar -> CInt -> IO ()
_RAND_pseudo_bytes Ptr CChar
bufPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
CStringLen -> IO ByteString
BS.packCStringLen (Ptr CChar
bufPtr, Int
n)
add :: BS.ByteString
-> Int
-> IO ()
add :: ByteString -> Int -> IO ()
add ByteString
bs Int
entropy =
ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
bs ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
ptr, Int
len) ->
Ptr CChar -> CInt -> CInt -> IO ()
_RAND_add Ptr CChar
ptr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
entropy)