Copyright | (c) Piyush P Kurur 2019 |
---|---|
License | Apache-2.0 OR BSD-3-Clause |
Maintainer | Piyush P Kurur <ppk@iitpkd.ac.in> |
Stability | experimental |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Synopsis
- data BlockCount p
- class Equality a where
- (===) :: Equality a => a -> a -> Bool
- data Result
- data LE w
- data BE w
- class Storable w => EndianStore w where
- copyFromBytes :: EndianStore w => Dest (Ptr w) -> Src (Ptr Word8) -> Int -> IO ()
- copyToBytes :: EndianStore w => Dest (Ptr Word8) -> Src (Ptr w) -> Int -> IO ()
- littleEndian :: w -> LE w
- bigEndian :: w -> BE w
- storeAt :: (EndianStore w, LengthUnit offset) => Ptr w -> offset -> w -> IO ()
- storeAtIndex :: EndianStore w => Ptr w -> Int -> w -> IO ()
- loadFrom :: (EndianStore w, LengthUnit offset) => Ptr w -> offset -> IO w
- loadFromIndex :: EndianStore w => Ptr w -> Int -> IO w
- data Ptr a
- class Pointer (ptr :: Type -> Type) where
- castPointer :: ptr a -> ptr b
- allocaPointer :: BYTES Int -> (ptr a -> IO b) -> IO b
- unsafeRawPtr :: ptr a -> Ptr a
- data AlignedPtr (n :: Nat) a
- data BYTES a
- class (Enum u, Monoid u) => LengthUnit u where
- sizeOf :: Storable a => Proxy a -> BYTES Int
- alignPtr :: Storable a => Ptr a -> Alignment -> Ptr a
- alignment :: Storable a => Proxy a -> Alignment
- memcpy :: (LengthUnit l, Pointer ptrS, Pointer ptrD) => Dest (ptrD dest) -> Src (ptrS src) -> l -> IO ()
- atMost :: (LengthUnit src, LengthUnit dest) => src -> dest
- memset :: (LengthUnit l, Pointer ptr) => ptr a -> Word8 -> l -> IO ()
- movePtr :: LengthUnit l => Ptr a -> l -> Ptr a
- hFillBuf :: (LengthUnit bufSize, Pointer ptr) => Handle -> ptr a -> bufSize -> IO (BYTES Int)
- unsafeWithPointer :: Pointer ptr => (Ptr a -> b) -> ptr a -> b
- atLeast :: (LengthUnit src, LengthUnit dest) => src -> dest
- atLeastAligned :: LengthUnit l => l -> Alignment -> BYTES Int
- alignedSizeOf :: Storable a => Proxy a -> BYTES Int
- nextLocation :: Storable a => Ptr a -> Ptr a
- peekAligned :: Storable a => Ptr a -> IO a
- pokeAligned :: Storable a => Ptr a -> a -> IO ()
- unsafeWithPointerCast :: Pointer ptr => (Ptr a -> b) -> ptr something -> b
- ptrAlignment :: KnownNat n => Proxy (AlignedPtr n a) -> Alignment
- nextAlignedPtr :: (Storable a, KnownNat n) => Ptr a -> AlignedPtr n a
- allocaBuffer :: (LengthUnit l, Pointer ptr) => l -> (ptr something -> IO b) -> IO b
- allocaSecure :: (LengthUnit l, Pointer ptr) => l -> (ptr a -> IO b) -> IO b
- wipeMemory :: (LengthUnit l, Pointer ptr) => ptr a -> l -> IO ()
- data Tuple (dim :: Nat) a
- type Dimension (dim :: Nat) = KnownNat dim
- zipWith :: (Unbox a, Unbox b, Unbox c) => (a -> b -> c) -> Tuple dim a -> Tuple dim b -> Tuple dim c
- unsafeFromList :: (Unbox a, Dimension dim) => [a] -> Tuple dim a
- dimension :: Dimension dim => Tuple dim a -> Int
- dimension' :: Dimension dim => Proxy (Tuple dim a) -> Int
- initial :: (Unbox a, Dimension dim0) => Tuple dim1 a -> Tuple dim0 a
- diagonal :: (Unbox a, Dimension dim) => a -> Tuple dim a
- repeatM :: (Monad m, Unbox a, Dimension dim) => m a -> m (Tuple dim a)
- generateIO :: (Dimension dim, Unbox a) => IO a -> IO (Tuple dim a)
- unsafeFromVector :: Vector a -> Tuple dim a
- unsafeToVector :: Tuple dim a -> Vector a
- data Src a
- data Dest a
- source :: a -> Src a
- destination :: a -> Dest a
Overview.
WARNING: If you are just a user of this library, it is unlikely that you will need to import this module. It is only required if you are a developer and want to define a new cryptographic data type.
A lot of cryptographic code is low level and involves quite a bit of boilerplate and are therefore fertile grounds for bugs. This module describes types specific to raaz that are designed to catch bugs in such low level code. The three principles that we follow in the design are:
- Define distinct types for semantically different objects. For
example, distinguish between buffer length/pointer offset in
bytes versus other units (see
LengthUnit
) or make endian aware variants of standard word types (seeBE
andLE
) etc. - Make sure that the low level functions are sensitive to these
types. For example, the function
sizeOf
exposed here returns
instead of justBYTES
Int
Int
and functions likeallocaBuffer
are generic enough to work with any length units. - Provide obvious instances for some basic type and have and idiom/design pattern to build such interfaces for user defined types. For example, we have a very specific way to build timing safe equality functions for arbitrary types. Most of the time, in our case it just amounts to handling product types.
Role of Monoids.
Monoids play an important role in facilitating the top down
approach to type safety that we mentioned above. Some types
described here have a natural monoid semantics. For example, when
dealing with pointer offsets and buffer sizes, we use type safe
length units like BYTES
. These length units are instances of
monoids where the underlying operation is addition. On the other
hand, when it comes to pointer alignment which is captured by the
type Alignment
, the monoid operation is taking the lowest common
multiple.
data BlockCount p Source #
Type safe message length in units of blocks of the primitive.
When dealing with buffer lengths for a primitive, it is often
better to use the type safe units BlockCount
. Functions in the raaz
package that take lengths usually allow any type safe length as
long as they can be converted to bytes. This can avoid a lot of
tedious and error prone length calculations.
Instances
Timing safe equality checking.
Many cryptographic setting require comparing two secrets and such
comparisons should be timing safe, i.e. the time taken to make the
comparison should not depend on the actual values that are
compared. Unfortunately, the equality comparison of may Haskell
types like ByteString
, provided via the class Eq
is not
timing safe. In raaz we take special care in defining the Eq
instance of all cryptographically sensitive types which make them
timing safe . For example, if we compare two digests dgst1 ==
dgst2
, the Eq
instance is defined in such a way that the time
taken is constant irrespective of the actual values. We also give a
mechanism to build timing safe equality for more complicated types
that user might need to define in her use cases as we now describe.
The starting point of defining such timing safe equality is the
class Equality
which plays the role Eq
. The member function
eq
playing the role of (==
) with an important difference. The
comparison function eq
returns the type type Result
instead of
Bool
and it is timing safe. The Eq
instance is then defined by
making use of the operator (===
). Thus a user of the library can
stick to the familiar Eq
class and get the benefits of timing
safe comparison
Building timing safe equality for Custom types.
For basic types like Word32
, Word64
this module defines
instances of Equality
. The Tuple
type inherits the Equality
instance from its base type. As a developer, new crypto-primitives
or protocols often need to define timing safe equality for types
other than those exported here. This is done in two stages.
data SomeSensitiveType = ... instance Equality SomeSensitiveType where eq a b = ... instance Eq SomeSensitiveType where (==) a b = a === b
Combining multiple comparisons using Monoid operations
The Result
type is an opaque type and does not allow inspection
via a pattern match or conversion to Bool
. However, while
defining the Equality
instance, we often need to perform an AND
of multiple comparison (think of comparing a tuple). This is where
the monoid instance of Result
is useful. If r1
and r2
are the
results of two comparisons then r1
essentially takes
the AND of these results. However, unlike in the case of AND-ing in
mappend
r2Bool
, mappend
on the Result
type does not short-circuit. In
fact, the whole point of using Result
type instead of Bool
is
to avoid this short circuiting.
To illustrate, we have the following code fragment
data Foo = Foo Word32 Word64 instance Equality Foo where eq (Foo a b) (Foo c d) = eq a c `mapped` eq b d instance Eq Foo where (=) = (===)
Automatic deriving of Equality
instances.
We often find ourselves wrapping existing types in new types keeping in line with the philosophy of distinguishing sematically distinct data with their types. It would be tedious to repeat the above process for each such type. Often, we can get away by just deriving these instances thereby saving a lot of boilerplate. For example, consider a data type that needs to keep a 128-byte secret. A simple deriving class would work in such cases.
newtype Secret = Secret (Tuple 128 Word8) deriving (Equality, Eq)
The Eq
instance here would be timing safe because it is
essentially the Eq
instance of tuples. The deriving Equality
is
not strictly required here. However, we suggest keeping it so that
on can define timing safe equality for other types that contain a
component of type Secret
.
Beware: deriving clause can be dangerous
The deriving clause that we defined above while convenient, hides a danger when not used properly. For example, consider the following definitions.
data Bad = Bad Bar Biz deriving Eq newtype BadAgain = BadAgain (Bar, Biz) deriving (Eq, Equality)
The comparison for the elements of the type Bad
would leak some
timing information even when Bar
and Biz
are instances of
Equality
and thus have timing safe equalities themselves. This is
because the automatic derivation of Eq
instances in the above two
cases performs a component by component comparison and combines the
result using
. Due to boolean short circuiting, this
will lead to timing information being leaked.and
For product types, we can safely derive the Equality
instance and use
it to define the Eq
instance as follows
newtype Okey2 = Okey (Foo, Bar) deriving Equality instance Eq Okey2 where (=) = (===)
class Equality a where Source #
All types that support timing safe equality are instances of this class.
Instances
The result of a comparison. This is an opaque type and the monoid instance essentially takes AND of two comparisons in a timing safe way.
Instances
Little endian version of the word type w
Instances
Big endian version of the word type w
Instances
class Storable w => EndianStore w where Source #
This class captures types which provides an endian agnostic way
of loading from and storing to data buffers. Any multi-byte type
that is meant to be serialised to the outside world should be an
instance of this class. When defining the load
, store
,
adjustEndian
member functions, care should be taken to ensure
proper endian conversion.
The action store ptr w
stores w
at the location pointed by
ptr
. Endianness of the type w
is taken care of when storing.
For example, irrespective of the endianness of the machine,
store ptr (0x01020304 :: BE Word32)
will store the bytes
0x01
, 0x02
, 0x03
, 0x04
respectively at locations ptr
,
ptr +1
, ptr+2
and ptr+3
. On the other hand store ptr
(0x01020304 :: LE Word32)
would store 0x04
, 0x03
, 0x02
,
0x01
at the above locations.
load :: Ptr w -> IO w Source #
The action load ptr
loads the value stored at the ptr
. Like
store, it takes care of the endianness of the data type. For
example, if ptr
points to a buffer containing the bytes 0x01
,
0x02
, 0x03
, 0x04
, irrespective of the endianness of the
machine, load ptr :: IO (BE Word32)
will load the vale
0x01020304
of type BE Word32
and load ptr :: IO (LE Word32)
will load 0x04030201
of type LE Word32
.
The action adjustEndian ptr n
adjusts the encoding of bytes
stored at the location ptr
to conform with the endianness of
the underlying data type. For example, assume that ptr
points
to a buffer containing the bytes 0x01 0x02 0x03 0x04
, and we
are on a big endian machine, then adjustEndian (ptr :: Ptr (LE
Word32)) 1
will result in ptr
pointing to the sequence 0x04
0x03 0x02 0x01
. On the other hand if we were on a little endian
machine, the sequence should remain the same. In particular, the
following equalities should hold.
store ptr w = poke ptr w >> adjustEndian ptr 1
Similarly the value loaded by load ptr
should be same as the
value returned by adjustEndian ptr 1 >> peak ptr
, although the
former does not change the contents stored at ptr
where as the
latter might does modify the contents pointed by ptr
if the
endianness of the machine and the time do not agree.
The action adjustEndian ptr n >> adjustEndian ptr n
should be
equivalent to return ()
.
Instances
EndianStore Word8 Source # | |
EndianStore Poly1305 Source # | |
EndianStore R Source # | |
EndianStore S Source # | |
EndianStore () Source # | |
EndianStore (Key ChaCha20) Source # | |
EndianStore (Key XChaCha20) Source # | |
EndianStore (Nounce ChaCha20) Source # | |
EndianStore (Nounce XChaCha20) Source # | |
EndianStore (BE Word32) Source # | |
EndianStore (BE Word64) Source # | |
EndianStore (LE Word32) Source # | |
EndianStore (LE Word64) Source # | |
EndianStore w => EndianStore (BYTES w) Source # | |
EndianStore prim => EndianStore (Keyed prim) Source # | |
(Unbox a, EndianStore a, Dimension dim) => EndianStore (Tuple dim a) Source # | |
For the type w
, the action copyFromBytes dest src n
copies n
-elements from
src
to dest
. Copy performed by this combinator accounts for the
endianness of the data in dest
and is therefore not a mere copy
of n * sizeOf(w)
bytes. This action does not modify the src
pointer in any way.
copyToBytes :: EndianStore w => Dest (Ptr Word8) -> Src (Ptr w) -> Int -> IO () Source #
Similar to copyFromBytes
but the transfer is done in the other direction. The copy takes
care of performing the appropriate endian encoding.
littleEndian :: w -> LE w Source #
Convert to the little endian variant.
:: (EndianStore w, LengthUnit offset) | |
=> Ptr w | the pointer |
-> offset | the absolute offset in type safe length units. |
-> w | value to store |
-> IO () |
Store the given value at an offset from the crypto pointer. The offset is given in type safe units.
:: EndianStore w | |
=> Ptr w | the pointer to the first element of the array |
-> Int | the index of the array |
-> w | the value to store |
-> IO () |
Store the given value as the n
-th element of the array
pointed by the crypto pointer.
:: (EndianStore w, LengthUnit offset) | |
=> Ptr w | the pointer |
-> offset | the offset |
-> IO w |
Load from a given offset. The offset is given in type safe units.
:: EndianStore w | |
=> Ptr w | the pointer to the first element of the array |
-> Int | the index of the array |
-> IO w |
Load the n
-th value of an array pointed by the crypto pointer.
A value of type
represents a pointer to an object, or an
array of objects, which may be marshalled to or from Haskell values
of type Ptr
aa
.
The type a
will often be an instance of class
Storable
which provides the marshalling operations.
However this is not essential, and you can provide your own operations
to access the pointer. For example you might write small foreign
functions to get or set the fields of a C struct
.
Instances
IsString WriteTo Source # | |
Defined in Raaz.Core.Transfer.Unsafe fromString :: String -> WriteTo # | |
NFData1 Ptr | Since: deepseq-1.4.3.0 |
Defined in Control.DeepSeq | |
Encodable WriteTo Source # | |
Defined in Raaz.Core.Transfer.Unsafe toByteString :: WriteTo -> ByteString Source # fromByteString :: ByteString -> Maybe WriteTo Source # | |
Pointer Ptr Source # | |
Defined in Raaz.Core.Types.Pointer | |
Generic1 (URec (Ptr ()) :: k -> Type) | |
Data a => Data (Ptr a) | Since: base-4.8.0.0 |
Defined in Data.Data gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Ptr a -> c (Ptr a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Ptr a) # dataTypeOf :: Ptr a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Ptr a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Ptr a)) # gmapT :: (forall b. Data b => b -> b) -> Ptr a -> Ptr a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Ptr a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Ptr a -> r # gmapQ :: (forall d. Data d => d -> u) -> Ptr a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Ptr a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Ptr a -> m (Ptr a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Ptr a -> m (Ptr a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Ptr a -> m (Ptr a) # | |
Foldable (UAddr :: Type -> Type) | Since: base-4.9.0.0 |
Defined in Data.Foldable fold :: Monoid m => UAddr m -> m # foldMap :: Monoid m => (a -> m) -> UAddr a -> m # foldMap' :: Monoid m => (a -> m) -> UAddr a -> m # foldr :: (a -> b -> b) -> b -> UAddr a -> b # foldr' :: (a -> b -> b) -> b -> UAddr a -> b # foldl :: (b -> a -> b) -> b -> UAddr a -> b # foldl' :: (b -> a -> b) -> b -> UAddr a -> b # foldr1 :: (a -> a -> a) -> UAddr a -> a # foldl1 :: (a -> a -> a) -> UAddr a -> a # elem :: Eq a => a -> UAddr a -> Bool # maximum :: Ord a => UAddr a -> a # minimum :: Ord a => UAddr a -> a # | |
Traversable (UAddr :: Type -> Type) | Since: base-4.9.0.0 |
Storable (Ptr a) | Since: base-2.1 |
Show (Ptr a) | Since: base-2.1 |
NFData (Ptr a) | Since: deepseq-1.4.2.0 |
Defined in Control.DeepSeq | |
Eq (Ptr a) | Since: base-2.1 |
Ord (Ptr a) | Since: base-2.1 |
Prim (Ptr a) | |
Defined in Data.Primitive.Types sizeOfType# :: Proxy (Ptr a) -> Int# # alignmentOfType# :: Proxy (Ptr a) -> Int# # alignment# :: Ptr a -> Int# # indexByteArray# :: ByteArray# -> Int# -> Ptr a # readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Ptr a #) # writeByteArray# :: MutableByteArray# s -> Int# -> Ptr a -> State# s -> State# s # setByteArray# :: MutableByteArray# s -> Int# -> Int# -> Ptr a -> State# s -> State# s # indexOffAddr# :: Addr# -> Int# -> Ptr a # readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, Ptr a #) # writeOffAddr# :: Addr# -> Int# -> Ptr a -> State# s -> State# s # setOffAddr# :: Addr# -> Int# -> Int# -> Ptr a -> State# s -> State# s # | |
Functor (URec (Ptr ()) :: Type -> Type) | Since: base-4.9.0.0 |
Generic (URec (Ptr ()) p) | |
Eq (URec (Ptr ()) p) | Since: base-4.9.0.0 |
Ord (URec (Ptr ()) p) | Since: base-4.9.0.0 |
Defined in GHC.Generics compare :: URec (Ptr ()) p -> URec (Ptr ()) p -> Ordering # (<) :: URec (Ptr ()) p -> URec (Ptr ()) p -> Bool # (<=) :: URec (Ptr ()) p -> URec (Ptr ()) p -> Bool # (>) :: URec (Ptr ()) p -> URec (Ptr ()) p -> Bool # (>=) :: URec (Ptr ()) p -> URec (Ptr ()) p -> Bool # max :: URec (Ptr ()) p -> URec (Ptr ()) p -> URec (Ptr ()) p # min :: URec (Ptr ()) p -> URec (Ptr ()) p -> URec (Ptr ()) p # | |
data URec (Ptr ()) (p :: k) | Used for marking occurrences of Since: base-4.9.0.0 |
type Rep1 (URec (Ptr ()) :: k -> Type) | Since: base-4.9.0.0 |
Defined in GHC.Generics | |
type Rep (URec (Ptr ()) p) | Since: base-4.9.0.0 |
Defined in GHC.Generics |
class Pointer (ptr :: Type -> Type) where Source #
Depending on the constraints of various pointers, raaz expose a variety of pointer types. This type class capturing such types. The main operation of interest to use is casting and allocation. All of these types have an underlying pointer which you can also be accessed.
castPointer :: ptr a -> ptr b Source #
Convert pointers of one type to another.
allocaPointer :: BYTES Int -> (ptr a -> IO b) -> IO b Source #
The alloca
variant for this pointer type. The action
allocaPointer l action
allocates a buffer of size l
and
passes it on to action
. No explicit de-allocation is required
just like in the case of alloca
unsafeRawPtr :: ptr a -> Ptr a Source #
Recover the underlying raw pointer.
Instances
Pointer Ptr Source # | |
Defined in Raaz.Core.Types.Pointer | |
KnownNat n => Pointer (AlignedPtr n) Source # | |
Defined in Raaz.Core.Types.Pointer castPointer :: AlignedPtr n a -> AlignedPtr n b Source # allocaPointer :: BYTES Int -> (AlignedPtr n a -> IO b) -> IO b Source # unsafeRawPtr :: AlignedPtr n a -> Ptr a Source # |
data AlignedPtr (n :: Nat) a Source #
The type AlignedPtr n
that captures pointers that are aligned
to n
byte boundary.
Instances
KnownNat n => Pointer (AlignedPtr n) Source # | |
Defined in Raaz.Core.Types.Pointer castPointer :: AlignedPtr n a -> AlignedPtr n b Source # allocaPointer :: BYTES Int -> (AlignedPtr n a -> IO b) -> IO b Source # unsafeRawPtr :: AlignedPtr n a -> Ptr a Source # |
Type safe lengths/offsets in units of bytes.
Instances
class (Enum u, Monoid u) => LengthUnit u where Source #
In cryptographic settings, we need to measure pointer offsets and
buffer sizes. The smallest of length/offset that we have is bytes
measured using the type BYTES
. In various other circumstances, it
would be more natural to measure these in multiples of bytes. For
example, when allocating buffer to use encrypt using a block cipher
it makes sense to measure the buffer size in multiples of block of
the cipher. Explicit conversion between these length units, while
allocating or moving pointers, involves a lot of low level scaling
that is also error prone. To avoid these errors due to unit
conversions, we distinguish between different length units at the
type level. This type class capturing all such types, i.e. types
that stand of length units. Allocation functions and pointer
arithmetic are generalised to these length units.
All instances of a LengthUnit
are required to be instances of
Monoid
where the monoid operation gives these types the natural
size/offset addition semantics: i.e. shifting a pointer by offset
a
is same as shifting it by mappend
ba
and then by b
.
Instances
Primitive p => LengthUnit (BlockCount p) Source # | |
Defined in Raaz.Core.Primitive | |
LengthUnit (BYTES Int) Source # | |
alignment :: Storable a => Proxy a -> Alignment Source #
Compute the alignment for a storable object.
:: (LengthUnit l, Pointer ptrS, Pointer ptrD) | |
=> Dest (ptrD dest) | destination |
-> Src (ptrS src) | src |
-> l | Number of Bytes to copy |
-> IO () |
Copy between pointers.
atMost :: (LengthUnit src, LengthUnit dest) => src -> dest Source #
Express length unit src
in terms of length unit dest
rounding
downwards.
:: (LengthUnit l, Pointer ptr) | |
=> ptr a | Target |
-> Word8 | Value byte to set |
-> l | Number of bytes to set |
-> IO () |
Sets the given number of Bytes to the specified value.
movePtr :: LengthUnit l => Ptr a -> l -> Ptr a Source #
Move the given pointer with a specific offset.
hFillBuf :: (LengthUnit bufSize, Pointer ptr) => Handle -> ptr a -> bufSize -> IO (BYTES Int) Source #
A version of hGetBuf
which works for any type safe length units.
unsafeWithPointer :: Pointer ptr => (Ptr a -> b) -> ptr a -> b Source #
Lifts raw pointer actions to the given pointer type.
atLeast :: (LengthUnit src, LengthUnit dest) => src -> dest Source #
Express length unit src
in terms of length unit dest
rounding
upwards.
atLeastAligned :: LengthUnit l => l -> Alignment -> BYTES Int Source #
Often we want to allocate a buffer of size l
. We also want to
make sure that the buffer starts at an alignment boundary
a
. However, the standard word allocation functions might return a
pointer that is not aligned as desired. The atLeastAligned l a
returns a length n
such the length n
is big enough to ensure
that there is at least l
length of valid buffer starting at the
next pointer aligned at boundary a
. If the alignment required in
a
then allocating l + a
should do the trick.
NOTE: Let us say that the next allocation happens at a pointer ptr whose address is r mod a. Then if we allocate a buffer of size s, the buffer will be spanning the address ptr, ptr + 1, ... ptr + s -1. Assume that r ≠ 0, then the next address at which our buffer can start is at ptr + a - r. Therefore the size of the buffer available at this location is (ptr + s - 1) - (ptr + a - r ) + 1 = s - a + r, which should at least l. Therefore, we have s - a - r = l, which means s >= l + a - r. This is maximised when r = 1. This analysis means that we need to allocate only l + a - 1 bytes but that seems to be creating problems for our copy. May be it is a memcpy vs memmove problem.
alignedSizeOf :: Storable a => Proxy a -> BYTES Int Source #
Size of the buffer to be allocated to store an element of type
a
so as to guarantee that there exist enough space to store the
element after aligning the pointer.
nextLocation :: Storable a => Ptr a -> Ptr a Source #
Compute the next aligned pointer starting from the given pointer location.
pokeAligned :: Storable a => Ptr a -> a -> IO () Source #
Poke the element from the next aligned location.
unsafeWithPointerCast :: Pointer ptr => (Ptr a -> b) -> ptr something -> b Source #
Lifts raw pointer actions to a pointer action of a different type.
ptrAlignment :: KnownNat n => Proxy (AlignedPtr n a) -> Alignment Source #
Compute the alignment restriction.
nextAlignedPtr :: (Storable a, KnownNat n) => Ptr a -> AlignedPtr n a Source #
Given a raw pointer (i.e. element of type Ptr
), returns the
next pointer aligned to n
-bytes boundary.
:: (LengthUnit l, Pointer ptr) | |
=> l | buffer length |
-> (ptr something -> IO b) | the action to run |
-> IO b |
Allocate a buffer for an action that expects a generic pointer. Length can be specified in any length units.
allocaSecure :: (LengthUnit l, Pointer ptr) => l -> (ptr a -> IO b) -> IO b Source #
Variant of allocaBuffer
that allocates a locked buffer of a
given size and runs the action. The associated memory (1) exists
for the duration of the action (2) will not be swapped during the
action as guaranteed by the memlock function of the operating
system and (3) will be wiped clean and deallocated when the action
terminates either directly or indirectly via errors. While this is
mostly secure, there are still edge cases in multi-threaded
applications where the memory will not be cleaned. For example, if
you run a crypto-sensitive action inside a child thread and the
main thread gets exists, then the child thread is killed (due to
the demonic nature of threads in GHC haskell) immediately and might
not give it chance to wipe the memory clean. See
https://ghc.haskell.org/trac/ghc/ticket/13891 on this problem and
possible workarounds.
:: (LengthUnit l, Pointer ptr) | |
=> ptr a | buffer to wipe |
-> l | buffer length |
-> IO () |
Cleanup the given pointer of any sensitive data. This is a tricky function to write as compilers are known to optimise this away. In our case we try to use the platform specific one if it exists.
data Tuple (dim :: Nat) a Source #
Tuples that encode their length in their types. For tuples, we call the length its dimension.
Instances
(Unbox a, Storable a, Dimension dim) => Storable (Tuple dim a) Source # | |
Defined in Raaz.Core.Types.Tuple sizeOf :: Tuple dim a -> Int # alignment :: Tuple dim a -> Int # peekElemOff :: Ptr (Tuple dim a) -> Int -> IO (Tuple dim a) # pokeElemOff :: Ptr (Tuple dim a) -> Int -> Tuple dim a -> IO () # peekByteOff :: Ptr b -> Int -> IO (Tuple dim a) # pokeByteOff :: Ptr b -> Int -> Tuple dim a -> IO () # | |
(Show a, Unbox a) => Show (Tuple dim a) Source # | |
(Unbox a, Equality a) => Eq (Tuple dim a) Source # | Equality checking is timing safe. |
(Unbox a, EndianStore a, Dimension dim) => EndianStore (Tuple dim a) Source # | |
(Unbox a, Equality a) => Equality (Tuple dim a) Source # | |
type Dimension (dim :: Nat) = KnownNat dim Source #
The constaint on the dimension of the tuple (since base 4.7.0)
zipWith :: (Unbox a, Unbox b, Unbox c) => (a -> b -> c) -> Tuple dim a -> Tuple dim b -> Tuple dim c Source #
A zipwith function for tuples
unsafeFromList :: (Unbox a, Dimension dim) => [a] -> Tuple dim a Source #
Construct a tuple out of the list. This function is unsafe and will result in run time error if the list is not of the correct dimension.
dimension :: Dimension dim => Tuple dim a -> Int Source #
Function that returns the dimension of the tuple. The dimension
is calculated without inspecting the tuple and hence the term
will evaluate to 5.dimension
(undefined :: Tuple 5 Int)
dimension' :: Dimension dim => Proxy (Tuple dim a) -> Int Source #
Function that returns the dimension from the proxy of the tuple. This is useful when we only have a proxy of the tuple at hand. This is clearly possible because the dimension calculation works at the type level and does not require looking at the value of the tuple.
initial :: (Unbox a, Dimension dim0) => Tuple dim1 a -> Tuple dim0 a Source #
Computes the initial fragment of a tuple. No length needs to be given as it is infered from the types.
diagonal :: (Unbox a, Dimension dim) => a -> Tuple dim a Source #
The diagonal a
gives a tuple, all of whose entries is a
.
repeatM :: (Monad m, Unbox a, Dimension dim) => m a -> m (Tuple dim a) Source #
Construct a tuple by repeating a monadic action.
generateIO :: (Dimension dim, Unbox a) => IO a -> IO (Tuple dim a) Source #
Generate using the given action.
unsafeFromVector :: Vector a -> Tuple dim a Source #
Convert vector to tuple. This function is unsafe because it does not check whether length of the vector matches with the tuple dimension.
unsafeToVector :: Tuple dim a -> Vector a Source #
Convert the tuple to vector.
The source of a copy operation. Besides the source
smart
constructor, the functor instance allows to transform the internal
type using the fmap
(e.g. given an sptr :: Src (Ptr Word8)
shift it by an offset).
For FFI use: One can use this type directly in FFI interface by importing Raaz.Core.Types.Internal to get access to the constructor.
The destination of a copy operation. Besides the destination
smart constructor, the functor instance allows to transform the
internal type using the fmap
(e.g. given an dptr :: Dest (Ptr
Word8)
shift it by an offset).
For FFI use: One can use this type directly in FFI interface by importing Raaz.Core.Types.Internal to get access to the constructor.
destination :: a -> Dest a Source #
Smart constructor for Dest
.