Safe Haskell | None |
---|---|
Language | Haskell2010 |
The sensitive data type internals.
Synopsis
- withSecureMemory :: forall m r. MonadIO m => (WithSecureMemory => m r) -> m r
- type WithSecureMemory = Given SodiumInitialised
- data SodiumInitialised
- data SecureMemoryInitException
- data SensitiveBytes s = SensitiveBytes {}
- allocate :: forall s m. (MonadIO m, WithSecureMemory) => Int -> m (SensitiveBytes s)
- free :: forall s m. (MonadIO m, WithSecureMemory) => SensitiveBytes s -> m ()
- unsafePtr :: SensitiveBytes s -> Ptr ()
- resized :: forall s. Int -> SensitiveBytes s -> SensitiveBytes s
- withSensitiveBytes :: forall s m r. (MonadIO m, MonadMask m, WithSecureMemory) => Int -> (SensitiveBytes s -> m r) -> m r
- data SensitiveBytesAllocException
Documentation
:: forall m r. MonadIO m | |
=> (WithSecureMemory => m r) | Action to perform. |
-> m r |
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
.
type WithSecureMemory = Given SodiumInitialised Source #
A constraint for functions that require access to secure memory.
The only way to satisfy it is to call withSecureMemory
.
data SodiumInitialised Source #
A trivial proof that sodium_init
has been called.
data SecureMemoryInitException Source #
Exception thrown by withSecureMemory
.
Instances
data SensitiveBytes s Source #
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).
Instances
ByteArrayAccess (SensitiveBytes s) Source # | |
Defined in Data.SensitiveBytes.Internal length :: SensitiveBytes s -> Int # withByteArray :: SensitiveBytes s -> (Ptr p -> IO a) -> IO a # copyByteArrayToPtr :: SensitiveBytes s -> Ptr p -> IO () # |
:: forall s m. (MonadIO m, WithSecureMemory) | |
=> Int | Size of the array (in bytes). |
-> m (SensitiveBytes s) |
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
.
free :: forall s m. (MonadIO m, WithSecureMemory) => SensitiveBytes s -> m () Source #
Free bytes previously allocated in a protected memory region.
unsafePtr :: SensitiveBytes s -> Ptr () Source #
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.
:: forall s. Int | New data size. |
-> SensitiveBytes s | What to resize. |
-> SensitiveBytes s |
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.
:: forall s m r. (MonadIO m, MonadMask m, WithSecureMemory) | |
=> Int | Size of the array (in bytes). |
-> (SensitiveBytes s -> m r) | Action to perform with memory allocated. |
-> m r |
Allocate a byte array in a secure memory region.
This function guarantees that:
- The garbage collector will not touch the allocated memory and will not try to copy the sensitive data.
- The memory will be zeroed-out and freed as soon as the computation finishes.
Additionally, it will try its best (subject to the support from the operating system) to do the following:
- Allocate the buffer at the end of a page and make sure that the following page is not mapped, so trying to access past the end of the buffer will crash the program.
- Place a canary immediately before the buffer, check that it was not modified before deallocating the memory, and crash the program otherwise.
mlock
the memory to make sure it will not be paged to the disk.- Ask the operating system not to include this memory in core dumps.
Just as with regular malloc
, allocation can fail, for example,
if there is not enough memory. In this case, the function will throw
SensitiveBytesAllocException
.
data SensitiveBytesAllocException Source #
Exception thrown by withSensitiveBytes
.