-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Securely allocated and deallocated memory. -- -- Securely allocated and deallocated memory. -- -- When handling sensitive data in your program, you want to be extra -- careful and make sure that it is gone as soon as you are done working -- with it. In a garbage-collected language like Haskell this is not so -- easy, since the garbage collector can move your bytes around and -- create copies of it. In addition to that, even if the memory gets -- eventually deallocated, it is not guaranteed that the data will -- actually be zeroed-out or overriden. -- -- To make matters even worse, if the operating system runs out of RAM -- while your sensitive data remains in the memory, the page that -- contains your data can get swapped out and, thus, end up on the disk, -- which you, of course, absolutely want to never happen. -- -- This library provides a (relatively) easy to use interface for working -- with data allocated in a secure memory location that is guaranteed to -- never end up on the disk and that will be zeroed-out as soon as you -- finish using it. @package secure-memory @version 0.0.0.1 -- | Internal utilities for reading passwords. module Data.SensitiveBytes.IO.Internal.Password -- | Flush stdout, disable echo, and read user input from stdin. readPassword :: Handle -> Handle -> Text -> Ptr () -> Int -> IO Int -- | The sensitive data type internals. module Data.SensitiveBytes.Internal -- | This function performs the initialisation steps required for -- allocating data in secure memory regions. -- -- The basic usage is to call this function and provide to it a block of -- code that will be allocating memory for sensitive data. The type of -- withSensitiveBytes is such that it can only be called withing -- such a code block. -- -- Ideally, you should call withSecureMemory only once and deal -- with all your sensitive data within this single code block, however it -- is not a requirement – you can call it as many times as you wish and -- the only downside to doing so is that it will incur a tiny performance -- penalty. -- -- In some rare circumstances this function secure memory initialisation -- may fail, in which case this function will throw -- SecureMemoryInitException. withSecureMemory :: forall m r. MonadIO m => (WithSecureMemory => m r) -> m r -- | A constraint for functions that require access to secure memory. The -- only way to satisfy it is to call withSecureMemory. type WithSecureMemory = Given SodiumInitialised -- | A trivial proof that sodium_init has been called. data SodiumInitialised -- | Exception thrown by withSecureMemory. data SecureMemoryInitException -- | Bytes that will be allocated in a secure memory location such that -- they will never be moved by the garbage collector and, hopefully, -- never swapped out to the disk (if the operating system supports this -- kind of protection). data SensitiveBytes s SensitiveBytes :: Int -> Int -> Ptr () -> SensitiveBytes s -- | Size of the allocated buffer. [allocSize] :: SensitiveBytes s -> Int -- | Size of the actual data stored. [dataSize] :: SensitiveBytes s -> Int -- | Buffer pointer. [bufPtr] :: SensitiveBytes s -> Ptr () -- | Allocate bytes in a protected memory region. -- -- Just as regular malloc, this function can fail, for example, -- if there is not enough memory. In this case, it will throw -- SensitiveBytesAllocException. allocate :: forall s m. (MonadIO m, WithSecureMemory) => Int -> m (SensitiveBytes s) -- | Free bytes previously allocated in a protected memory region. free :: forall s m. (MonadIO m, WithSecureMemory) => SensitiveBytes s -> m () -- | Get the underlying data pointer. -- -- This function is unsafe, because it discards the second-order context -- and thus can allow the pointer to escape its scope and be used after -- free. unsafePtr :: SensitiveBytes s -> Ptr () -- | Rewrite the recorded size of the data. -- -- This is a very dangerous internal-only function. It is essentially a -- hack that allows other functions exported from this library to -- efficiently read data of unknown size by first allocating a large -- buffer and then tweaking the ByteArrayAccess instance to return -- the size that is smaller than what was actually allocated. resized :: forall s. () => Int -> SensitiveBytes s -> SensitiveBytes s -- | Allocate a byte array in a secure memory region. -- -- This function guarantees that: -- --
-- import Data.SensitiveBytes (SensitiveBytes, withSecureMemory, withSensitiveBytes)
--
-- your_function = withSecureMemory $ do
-- {- some optional initialisation -}
-- withSensitiveBytes 128 $ sb -> do
-- {- work with sb using its ByteArrayAccess instance -}
--
--
-- Note that withSensitiveBytes can only be called withing a code
-- block passed to withSecureMemory and its type will prevent your
-- from doing otherwise.
--
-- You will typically read sensitive data into SensitiveBytes
-- using functions in Data.SensitiveBytes.IO and then pass to some
-- other function that will work with it using the ByteArrayAccess
-- instance. Just make sure the function you pass it to does not copy the
-- data and does not convert it to some other insecure byte-array-like
-- type.
module Data.SensitiveBytes
-- | This function performs the initialisation steps required for
-- allocating data in secure memory regions.
--
-- The basic usage is to call this function and provide to it a block of
-- code that will be allocating memory for sensitive data. The type of
-- withSensitiveBytes is such that it can only be called withing
-- such a code block.
--
-- Ideally, you should call withSecureMemory only once and deal
-- with all your sensitive data within this single code block, however it
-- is not a requirement – you can call it as many times as you wish and
-- the only downside to doing so is that it will incur a tiny performance
-- penalty.
--
-- In some rare circumstances this function secure memory initialisation
-- may fail, in which case this function will throw
-- SecureMemoryInitException.
withSecureMemory :: forall m r. MonadIO m => (WithSecureMemory => m r) -> m r
-- | A constraint for functions that require access to secure memory. The
-- only way to satisfy it is to call withSecureMemory.
type WithSecureMemory = Given SodiumInitialised
-- | Exception thrown by withSecureMemory.
data SecureMemoryInitException
-- | Bytes that will be allocated in a secure memory location such that
-- they will never be moved by the garbage collector and, hopefully,
-- never swapped out to the disk (if the operating system supports this
-- kind of protection).
data SensitiveBytes s
-- | Allocate a byte array in a secure memory region.
--
-- This function guarantees that:
--
--
-- withSecureMemory $
-- withUserPassword 128 (Just "Enter your password: ") $ pw -> do
-- {- hash the pw or do something else with it -}
--
withUserPassword :: forall m s r. (MonadIO m, MonadMask m, WithSecureMemory) => Int -> Maybe Text -> (SensitiveBytes s -> m r) -> m r