{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls, ViewPatterns #-}
module Crypto.Cipher.AES128.Internal
        ( AESKey128(..), AESKey192(..), AESKey256(..), RawKey128(..), RawKey192(..), RawKey256(..), GCM(..), GCMpc
        , generateKey128, generateKey192, generateKey256
        , generateGCM, precomputeGCMdata
        , encryptECB
        , decryptECB
        , encryptCTR
        , decryptCTR
        , encryptGCM, decryptGCM
        -- * Piece-meal functions
        , cipherOnlyGCM
        , decipherOnlyGCM
        , finishGCM, aadGCM
        -- * Internal, will not be exported in a near-future release.
        , GetExpanded
        ) where

import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
import Foreign.Marshal.Alloc
import Data.Word
import Data.Bits (shiftL, (.|.))
import System.IO.Unsafe

-- AES Bindings
data AESKeyStruct
type AESKeyPtr = Ptr AESKeyStruct

data RawKey128 = RKey128 { RawKey128 -> Word64
lowK128,RawKey128 -> Word64
highK128 :: {-# UNPACK #-} !Word64 }
data AESKey128 = AESKey128 { AESKey128 -> RawKey128
rawKey128      :: !RawKey128
                           , AESKey128 -> ForeignPtr AESKeyStruct
expandedKey128 :: ForeignPtr AESKeyStruct }

data RawKey192 = RKey192 { RawKey192 -> Word64
lowK192,RawKey192 -> Word64
midK192,RawKey192 -> Word64
highK192 :: {-# UNPACK #-} !Word64 }
data AESKey192 = AESKey192 { AESKey192 -> RawKey192
rawKey192      :: !RawKey192
                           , AESKey192 -> ForeignPtr AESKeyStruct
expandedKey192 :: ForeignPtr AESKeyStruct }

data RawKey256 = RKey256 { RawKey256 -> Word64
aK256,RawKey256 -> Word64
bK256,RawKey256 -> Word64
cK256,RawKey256 -> Word64
dK256 :: {-# UNPACK #-} !Word64 }
data AESKey256 = AESKey256 { AESKey256 -> RawKey256
rawKey256      :: !RawKey256
                           , AESKey256 -> ForeignPtr AESKeyStruct
expandedKey256 :: ForeignPtr AESKeyStruct }

class GetExpanded a where
    expandedKey :: a -> ForeignPtr AESKeyStruct

instance GetExpanded AESKey256 where
    expandedKey :: AESKey256 -> ForeignPtr AESKeyStruct
expandedKey = AESKey256 -> ForeignPtr AESKeyStruct
expandedKey256
instance GetExpanded AESKey192 where
    expandedKey :: AESKey192 -> ForeignPtr AESKeyStruct
expandedKey = AESKey192 -> ForeignPtr AESKeyStruct
expandedKey192
instance GetExpanded AESKey128 where
    expandedKey :: AESKey128 -> ForeignPtr AESKeyStruct
expandedKey = AESKey128 -> ForeignPtr AESKeyStruct
expandedKey128

type AESGcmPtr = Ptr GCMStruct
data GCMStruct

-- Store the key, the precomputed GCM data, and the current IV by way of
-- a foreign pointer
data GCM k = GCM { GCM k -> GCMpc
_gcmFP   :: GCMpc
                 , GCM k -> k
_keyFP   :: k
                 , GCM k -> ForeignPtr CTXStruct
_ctxFP2  :: ForeignPtr CTXStruct
                 }

newtype GCMpc = GCMpc { GCMpc -> ForeignPtr GCMStruct
unGCMpc :: ForeignPtr GCMStruct }

type AESCtxPtr = Ptr CTXStruct
data CTXStruct
-- data CTX = CTX { _ctxFP :: ForeignPtr CTXStruct }

foreign import ccall unsafe "aes.h tmd_aes_initkey"
        c_aes_initkey :: AESKeyPtr -> Ptr Word8 -> Word8 -> IO ()

foreign import ccall unsafe "aes.h tmd_allocatekey"
        c_allocate_key :: IO AESKeyPtr

foreign import ccall unsafe "aes.h &tmd_freekey"
        c_free_key :: FunPtr (AESKeyPtr -> IO ())

-- foreign import ccall unsafe "aes.h tmd_freekey"
--         c_key_free :: AESKeyPtr -> IO ()

foreign import ccall unsafe "aes.h tmd_allocatectx"
        c_allocate_ctx :: IO AESCtxPtr

foreign import ccall unsafe "aes.h &tmd_freectx"
        c_free_ctx :: FunPtr (AESCtxPtr -> IO ())

-- foreign import ccall unsafe "aes.h tmd_freectx"
--         c_ctx_free :: AESCtxPtr -> IO ()

foreign import ccall unsafe "aes.h tmd_allocategcm"
        c_allocate_gcm :: IO AESGcmPtr

foreign import ccall unsafe "aes.h &tmd_freegcm"
        c_free_gcm :: FunPtr (AESGcmPtr -> IO ())

-- foreign import ccall unsafe "aes.h tmd_freegcm"
--         c_gcm_free :: AESGcmPtr -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_init"
    c_gcm_init :: AESGcmPtr
               -> AESKeyPtr
               -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_ctx_init"
    c_ctx_init :: AESGcmPtr
               -> AESCtxPtr
               -> AESKeyPtr
               -> Ptr Word8 -> Word32 -- ^ IV and length
               -> IO ()


foreign import ccall unsafe "aes.h tmd_aes_encrypt_ecb"
        c_encrypt_ecb :: Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_decrypt_ecb"
        c_decrypt_ecb :: Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO ()


foreign import ccall unsafe "aes.h tmd_aes_gcm_finish"
    c_gcm_finish  :: Ptr Word8           -- Tag
                  -> AESGcmPtr
                  -> AESKeyPtr           -- Key
                  -> AESCtxPtr           -- Context
                  -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_aad"
    c_gcm_aad     :: AESGcmPtr
                  -> AESCtxPtr
                  -> Ptr Word8 -> Word32 -- AAD, len
                  -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_decrypt"
    c_gcm_decrypt :: Ptr Word8           -- Output
                  -> AESGcmPtr
                  -> AESCtxPtr
                  -> AESKeyPtr
                  -> Ptr Word8 -> Word32 -- CT and length
                  -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_encrypt"
    c_gcm_encrypt :: Ptr Word8           -- Output
                  -> AESGcmPtr
                  -> AESCtxPtr
                  -> AESKeyPtr
                  -> Ptr Word8 -> Word32 -- PT and length
                  -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_full_encrypt"
    c_gcm_full_encrypt :: AESKeyPtr -> AESGcmPtr
                       -> Ptr Word8 -> Word32           -- IV, IVLen
                       -> Ptr Word8 -> Word32           -- AAD, AADLen
                       -> Ptr Word8 -> Word32           -- PT, PTLen
                       -> Ptr Word8                     -- CT
                       -> Ptr Word8                     -- Tag
                       -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_gcm_full_decrypt"
    c_gcm_full_decrypt :: AESKeyPtr -> AESGcmPtr
                       -> Ptr Word8 -> Word32           -- IV, IVLen
                       -> Ptr Word8 -> Word32           -- AAD, AADLen
                       -> Ptr Word8 -> Word32           -- PT, PTLen
                       -> Ptr Word8                     -- CT
                       -> Ptr Word8                     -- Tag
                       -> IO ()

foreign import ccall unsafe "aes.h tmd_aes_encrypt_ctr"
    c_encrypt_ctr :: Ptr Word8 -- ^ Output
                  -> AESKeyPtr
                  -> Ptr Word8 -- ^ 128 bit IV
                  -> Ptr Word8 -- ^ 128 bit new IV
                  -> Ptr Word8 -- ^ Input
                  -> Word32    -- ^ Input length in bytes
                  -> IO ()

c_decrypt_ctr :: Ptr Word8 -- ^ Result
              -> AESKeyPtr
              -> Ptr Word8 -- ^ 128 bit IV
              -> Ptr Word8 -- ^ 128 bit new IV
              -> Ptr Word8 -- ^ Input
              -> Word32    -- ^ Input length in bytes
              -> IO ()
c_decrypt_ctr :: Ptr Word8
-> AESKeyPtr
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO ()
c_decrypt_ctr = Ptr Word8
-> AESKeyPtr
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO ()
c_encrypt_ctr

blkSzC :: Word32
blkSzC :: Word32
blkSzC = Word32
16

-- Given a 16 byte buffer, allocate and return an AESKey
generateKey128 :: Ptr Word64
            -- ^ Buffer of 16 bytes of key material
            -> IO (Maybe AESKey128)
generateKey128 :: Ptr Word64 -> IO (Maybe AESKey128)
generateKey128 Ptr Word64
keyPtr = do
    RawKey128
raw <- do
            Word64
a <- Ptr Word8 -> IO Word64
peekLE (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr)
            let keyPtr2 :: Ptr b
keyPtr2 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a
            Word64
b <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr2
            RawKey128 -> IO RawKey128
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Word64 -> RawKey128
RKey128 Word64
b Word64
a)
    AESKeyPtr
k <- IO AESKeyPtr
c_allocate_key
    AESKeyPtr -> Ptr Word8 -> Word8 -> IO ()
c_aes_initkey AESKeyPtr
k (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Word8
16
    (ForeignPtr AESKeyStruct -> Maybe AESKey128)
-> IO (ForeignPtr AESKeyStruct) -> IO (Maybe AESKey128)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AESKey128 -> Maybe AESKey128
forall a. a -> Maybe a
Just (AESKey128 -> Maybe AESKey128)
-> (ForeignPtr AESKeyStruct -> AESKey128)
-> ForeignPtr AESKeyStruct
-> Maybe AESKey128
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RawKey128 -> ForeignPtr AESKeyStruct -> AESKey128
AESKey128 RawKey128
raw) (FinalizerPtr AESKeyStruct
-> AESKeyPtr -> IO (ForeignPtr AESKeyStruct)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr AESKeyStruct
c_free_key AESKeyPtr
k)
 where
     peekLE :: Ptr Word8 -> IO Word64
     peekLE :: Ptr Word8 -> IO Word64
peekLE Ptr Word8
p = do
        Word8
a1 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
0
        Word8
a2 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
1
        Word8
a3 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
2
        Word8
a4 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
3
        Word8
a5 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
4
        Word8
a6 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
5
        Word8
a7 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
6
        Word8
a8 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
7
        let f :: a -> Int -> a
f a
n Int
s = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
s
        let a :: Word64
a = (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a1 Int
56) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a2 Int
48) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a3 Int
40) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a4 Int
32) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a5 Int
24) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a6 Int
16) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a7 Int
8)  Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a8
        Word64 -> IO Word64
forall (m :: * -> *) a. Monad m => a -> m a
return Word64
a
{-# INLINE generateKey128 #-}

-- Given a 16 byte buffer, allocate and return an AESKey
generateKey192 :: Ptr Word64
            -- ^ Buffer of 16 bytes of key material
            -> IO (Maybe AESKey192)
generateKey192 :: Ptr Word64 -> IO (Maybe AESKey192)
generateKey192 Ptr Word64
keyPtr = do
    RawKey192
raw <- do
            Word64
a <- Ptr Word8 -> IO Word64
peekLE (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr)
            let keyPtr2 :: Ptr b
keyPtr2 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a
            Word64
b <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr2
            let keyPtr3 :: Ptr b
keyPtr3 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
b
            Word64
c <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr3
            RawKey192 -> IO RawKey192
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Word64 -> Word64 -> RawKey192
RKey192 Word64
c Word64
b Word64
a)
    AESKeyPtr
k <- IO AESKeyPtr
c_allocate_key
    AESKeyPtr -> Ptr Word8 -> Word8 -> IO ()
c_aes_initkey AESKeyPtr
k (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Word8
24
    (ForeignPtr AESKeyStruct -> Maybe AESKey192)
-> IO (ForeignPtr AESKeyStruct) -> IO (Maybe AESKey192)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AESKey192 -> Maybe AESKey192
forall a. a -> Maybe a
Just (AESKey192 -> Maybe AESKey192)
-> (ForeignPtr AESKeyStruct -> AESKey192)
-> ForeignPtr AESKeyStruct
-> Maybe AESKey192
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RawKey192 -> ForeignPtr AESKeyStruct -> AESKey192
AESKey192 RawKey192
raw) (FinalizerPtr AESKeyStruct
-> AESKeyPtr -> IO (ForeignPtr AESKeyStruct)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr AESKeyStruct
c_free_key AESKeyPtr
k)
 where
     peekLE :: Ptr Word8 -> IO Word64
     peekLE :: Ptr Word8 -> IO Word64
peekLE Ptr Word8
p = do
        Word8
a1 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
0
        Word8
a2 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
1
        Word8
a3 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
2
        Word8
a4 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
3
        Word8
a5 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
4
        Word8
a6 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
5
        Word8
a7 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
6
        Word8
a8 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
7
        let f :: a -> Int -> a
f a
n Int
s = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
s
        let a :: Word64
a = (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a1 Int
56) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a2 Int
48) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a3 Int
40) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a4 Int
32) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a5 Int
24) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a6 Int
16) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a7 Int
8)  Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a8
        Word64 -> IO Word64
forall (m :: * -> *) a. Monad m => a -> m a
return Word64
a
{-# INLINE generateKey192 #-}

-- Given a 16 byte buffer, allocate and return an AESKey
generateKey256 :: Ptr Word64
            -- ^ Buffer of 16 bytes of key material
            -> IO (Maybe AESKey256)
generateKey256 :: Ptr Word64 -> IO (Maybe AESKey256)
generateKey256 Ptr Word64
keyPtr = do
    RawKey256
raw <- do
            Word64
a <- Ptr Word8 -> IO Word64
peekLE (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr)
            let keyPtr2 :: Ptr b
keyPtr2 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a
            Word64
b <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr2
            let keyPtr3 :: Ptr b
keyPtr3 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
b
            Word64
c <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr3
            let keyPtr4 :: Ptr b
keyPtr4 = (Ptr Word64 -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Ptr Any -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
a Ptr Any -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
b Ptr Any -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Word64 -> Int
forall a. Storable a => a -> Int
sizeOf Word64
c
            Word64
d <- Ptr Word8 -> IO Word64
peekLE Ptr Word8
forall b. Ptr b
keyPtr4
            RawKey256 -> IO RawKey256
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Word64 -> Word64 -> Word64 -> RawKey256
RKey256 Word64
d Word64
c Word64
b Word64
a)
    AESKeyPtr
k <- IO AESKeyPtr
c_allocate_key
    AESKeyPtr -> Ptr Word8 -> Word8 -> IO ()
c_aes_initkey AESKeyPtr
k (Ptr Word64 -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Word64
keyPtr) Word8
32
    (ForeignPtr AESKeyStruct -> Maybe AESKey256)
-> IO (ForeignPtr AESKeyStruct) -> IO (Maybe AESKey256)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AESKey256 -> Maybe AESKey256
forall a. a -> Maybe a
Just (AESKey256 -> Maybe AESKey256)
-> (ForeignPtr AESKeyStruct -> AESKey256)
-> ForeignPtr AESKeyStruct
-> Maybe AESKey256
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RawKey256 -> ForeignPtr AESKeyStruct -> AESKey256
AESKey256 RawKey256
raw) (FinalizerPtr AESKeyStruct
-> AESKeyPtr -> IO (ForeignPtr AESKeyStruct)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr AESKeyStruct
c_free_key AESKeyPtr
k)
 where
     peekLE :: Ptr Word8 -> IO Word64
     peekLE :: Ptr Word8 -> IO Word64
peekLE Ptr Word8
p = do
        Word8
a1 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
0
        Word8
a2 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
1
        Word8
a3 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
2
        Word8
a4 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
3
        Word8
a5 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
4
        Word8
a6 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
5
        Word8
a7 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
6
        Word8
a8 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
p Int
7
        let f :: a -> Int -> a
f a
n Int
s = a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
s
        let a :: Word64
a = (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a1 Int
56) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a2 Int
48) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a3 Int
40) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a4 Int
32) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a5 Int
24) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a6 Int
16) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
                (Word8 -> Int -> Word64
forall a a. (Bits a, Integral a, Num a) => a -> Int -> a
f Word8
a7 Int
8)  Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a8
        Word64 -> IO Word64
forall (m :: * -> *) a. Monad m => a -> m a
return Word64
a
{-# INLINE generateKey256 #-}

-- Given a 16 byte buffer, allocate and return an key expansion useful for
-- GCM
generateGCM :: GetExpanded k
            => k
            -> IO (GCM k)
generateGCM :: k -> IO (GCM k)
generateGCM k
keyStruct = do
    let gcmPC :: GCMpc
gcmPC = k -> GCMpc
forall k. GetExpanded k => k -> GCMpc
precomputeGCMdata k
keyStruct
    ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO (GCM k)) -> IO (GCM k)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey k
keyStruct) ((AESKeyPtr -> IO (GCM k)) -> IO (GCM k))
-> (AESKeyPtr -> IO (GCM k)) -> IO (GCM k)
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
k -> do
      AESCtxPtr
c <- IO AESCtxPtr
c_allocate_ctx
      Int -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
12 ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ivPtr -> GCMpc -> (AESGcmPtr -> IO ()) -> IO ()
forall a. GCMpc -> (AESGcmPtr -> IO a) -> IO a
withGCMpc GCMpc
gcmPC ((AESGcmPtr -> IO ()) -> IO ()) -> (AESGcmPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESGcmPtr
g -> do
          (Int -> IO ()) -> [Int] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\Int
i -> Ptr Word8 -> Int -> Word8 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
ivPtr Int
i (Word8
0::Word8)) [Int
0..Int
11]
          AESGcmPtr -> AESCtxPtr -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO ()
c_ctx_init AESGcmPtr
g AESCtxPtr
c AESKeyPtr
k Ptr Word8
ivPtr Word32
12
      ForeignPtr CTXStruct
cFP <- FinalizerPtr CTXStruct -> AESCtxPtr -> IO (ForeignPtr CTXStruct)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr CTXStruct
c_free_ctx AESCtxPtr
c
      GCM k -> IO (GCM k)
forall (m :: * -> *) a. Monad m => a -> m a
return (GCMpc -> k -> ForeignPtr CTXStruct -> GCM k
forall k. GCMpc -> k -> ForeignPtr CTXStruct -> GCM k
GCM GCMpc
gcmPC k
keyStruct ForeignPtr CTXStruct
cFP)
{-# INLINE generateGCM #-}

precomputeGCMdata :: GetExpanded k => k -> GCMpc
precomputeGCMdata :: k -> GCMpc
precomputeGCMdata k
k = IO GCMpc -> GCMpc
forall a. IO a -> a
unsafePerformIO (IO GCMpc -> GCMpc) -> IO GCMpc -> GCMpc
forall a b. (a -> b) -> a -> b
$ do
    ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO GCMpc) -> IO GCMpc
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey k
k) ((AESKeyPtr -> IO GCMpc) -> IO GCMpc)
-> (AESKeyPtr -> IO GCMpc) -> IO GCMpc
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
kp -> do
        AESGcmPtr
g <- IO AESGcmPtr
c_allocate_gcm
        AESGcmPtr -> AESKeyPtr -> IO ()
c_gcm_init AESGcmPtr
g AESKeyPtr
kp
        ForeignPtr GCMStruct
gFP <- FinalizerPtr GCMStruct -> AESGcmPtr -> IO (ForeignPtr GCMStruct)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr GCMStruct
c_free_gcm AESGcmPtr
g
        GCMpc -> IO GCMpc
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr GCMStruct -> GCMpc
GCMpc ForeignPtr GCMStruct
gFP)

withGCMpc :: GCMpc -> (AESGcmPtr -> IO a) -> IO a
withGCMpc :: GCMpc -> (AESGcmPtr -> IO a) -> IO a
withGCMpc (GCMpc ForeignPtr GCMStruct
p) = ForeignPtr GCMStruct -> (AESGcmPtr -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr GCMStruct
p

-- An encrypt function that can handle up to blks < maxBound `div` 16 :: Word32
-- simultaneous blocks.
encryptECB :: GetExpanded k
           => k         -- ^ The key
           -> Ptr Word8 -- ^ The result buffer
           -> Ptr Word8 -- ^ The source buffer
           -> Int       -- ^ The input size in blocks
           -> IO ()
encryptECB :: k -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
encryptECB (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) Ptr Word8
dst Ptr Word8
src Int
blks = ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
p -> Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO ()
c_encrypt_ecb Ptr Word8
dst AESKeyPtr
p Ptr Word8
src (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
blks)
{-# INLINE encryptECB #-}

decryptECB :: GetExpanded k
           => k         -- ^ The key
           -> Ptr Word8 -- ^ The result buffer
           -> Ptr Word8 -- ^ The source buffer
           -> Int       -- ^ The input size in blocks
           -> IO ()
decryptECB :: k -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
decryptECB (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) Ptr Word8
dst Ptr Word8
src Int
blks
  | Int
blks Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
forall a. Bounded a => a
maxBound Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
`div` Word32
blkSzC :: Word32) = [Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"Can not decrypt so many blocks at once"
  | Bool
otherwise = ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
p -> Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO ()
c_decrypt_ecb Ptr Word8
dst AESKeyPtr
p Ptr Word8
src (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
blks)
{-# INLINE decryptECB #-}

aadGCM :: GetExpanded k => GCM k -> Ptr Word8 -> Int -> IO ()
aadGCM :: GCM k -> Ptr Word8 -> Int -> IO ()
aadGCM GCM k
gcm Ptr Word8
aad Int
aadLen = GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall k a.
GetExpanded k =>
GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM GCM k
gcm (((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ())
-> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(AESGcmPtr
g,AESKeyPtr
_k,AESCtxPtr
c) ->
    AESGcmPtr -> AESCtxPtr -> Ptr Word8 -> Word32 -> IO ()
c_gcm_aad AESGcmPtr
g AESCtxPtr
c Ptr Word8
aad (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
aadLen)

cipherOnlyGCM :: GetExpanded k
              => GCM k
              -> Ptr Word8         -- CT  (length assumed to match PT)
              -> Ptr Word8 -> Int  -- PT and length
              -> IO ()
cipherOnlyGCM :: GCM k -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
cipherOnlyGCM GCM k
gcm Ptr Word8
ct Ptr Word8
pt Int
ptlen = GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall k a.
GetExpanded k =>
GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM GCM k
gcm (((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ())
-> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(AESGcmPtr
g,AESKeyPtr
k,AESCtxPtr
c) ->
    Ptr Word8
-> AESGcmPtr
-> AESCtxPtr
-> AESKeyPtr
-> Ptr Word8
-> Word32
-> IO ()
c_gcm_encrypt Ptr Word8
ct AESGcmPtr
g AESCtxPtr
c AESKeyPtr
k Ptr Word8
pt  (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ptlen)

decipherOnlyGCM :: GetExpanded k
                => GCM k
                -> Ptr Word8         -- PT (length assumed to match CT)
                -> Ptr Word8 -> Int  -- CT and length
                -> IO ()
decipherOnlyGCM :: GCM k -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
decipherOnlyGCM GCM k
gcm Ptr Word8
pt Ptr Word8
ct Int
ctlen = GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall k a.
GetExpanded k =>
GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM GCM k
gcm (((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ())
-> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(AESGcmPtr
g,AESKeyPtr
k,AESCtxPtr
c) ->
    Ptr Word8
-> AESGcmPtr
-> AESCtxPtr
-> AESKeyPtr
-> Ptr Word8
-> Word32
-> IO ()
c_gcm_decrypt Ptr Word8
pt AESGcmPtr
g AESCtxPtr
c AESKeyPtr
k Ptr Word8
ct (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ctlen)

finishGCM :: GetExpanded k
          => GCM k     -- GCM context (which is mutated!)
          -> Ptr Word8 -- Tag, must point to 16 byte buffer (or larger)
          -> IO ()
finishGCM :: GCM k -> Ptr Word8 -> IO ()
finishGCM GCM k
gcm Ptr Word8
tagPtr =
    GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall k a.
GetExpanded k =>
GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM GCM k
gcm (((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ())
-> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(AESGcmPtr
gp,AESKeyPtr
kp,AESCtxPtr
cp) -> Ptr Word8 -> AESGcmPtr -> AESKeyPtr -> AESCtxPtr -> IO ()
c_gcm_finish Ptr Word8
tagPtr AESGcmPtr
gp AESKeyPtr
kp AESCtxPtr
cp

withForeignGCM :: GetExpanded k => GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM :: GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a
withForeignGCM (GCM GCMpc
g k
k ForeignPtr CTXStruct
c) (AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a
f =
    ForeignPtr GCMStruct -> (AESGcmPtr -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (GCMpc -> ForeignPtr GCMStruct
unGCMpc GCMpc
g) ((AESGcmPtr -> IO a) -> IO a) -> (AESGcmPtr -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AESGcmPtr
gp -> ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey k
k) ((AESKeyPtr -> IO a) -> IO a) -> (AESKeyPtr -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
kp -> ForeignPtr CTXStruct -> (AESCtxPtr -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CTXStruct
c ((AESCtxPtr -> IO a) -> IO a) -> (AESCtxPtr -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \AESCtxPtr
cp -> (AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a
f (AESGcmPtr
gp,AESKeyPtr
kp,AESCtxPtr
cp)

encryptCTR :: GetExpanded k
           => k
           -> Ptr Word8 -- ^ IV
           -> Ptr Word8 -- ^ NEW IV
           -> Ptr Word8 -- ^ CT
           -> Ptr Word8 -- ^ PT
           -> Int       -- ^ Length in bytes
           -> IO ()
encryptCTR :: k
-> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
encryptCTR (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) Ptr Word8
iv Ptr Word8
niv Ptr Word8
ct Ptr Word8
pt Int
len = ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
p -> do
    Ptr Word8
-> AESKeyPtr
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO ()
c_encrypt_ctr Ptr Word8
ct AESKeyPtr
p Ptr Word8
iv Ptr Word8
niv Ptr Word8
pt (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
{-# INLINE encryptCTR #-}

decryptCTR :: GetExpanded k
           => k
           -> Ptr Word8 -- ^ IV
           -> Ptr Word8 -- ^ NEW IV
           -> Ptr Word8 -- ^ PT
           -> Ptr Word8 -- ^ CT
           -> Int       -- ^ Length in bytes
           -> IO ()
decryptCTR :: k
-> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
decryptCTR (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) Ptr Word8
iv Ptr Word8
niv Ptr Word8
pt Ptr Word8
ct Int
len = ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
p -> do
    Ptr Word8
-> AESKeyPtr
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO ()
c_decrypt_ctr Ptr Word8
pt AESKeyPtr
p Ptr Word8
iv Ptr Word8
niv Ptr Word8
ct (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)

encryptGCM :: GetExpanded k
           => k                   -- AES{128,192,256}
           -> GCMpc               -- Precomputed GCM Data
           -> Ptr Word8 -> Word32 -- IV, len
           -> Ptr Word8 -> Word32 -- AAD, len
           -> Ptr Word8 -> Word32 -- PT, len
           -> Ptr Word8 -- CT  (out)
           -> Ptr Word8 -- Tag (128 bits out)
           -> IO ()
encryptGCM :: k
-> GCMpc
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> IO ()
encryptGCM (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) (GCMpc ForeignPtr GCMStruct
g) Ptr Word8
iv Word32
ivLen Ptr Word8
aad Word32
aadLen Ptr Word8
pt Word32
ptLen Ptr Word8
ct Ptr Word8
tag =
    ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
kp ->
      ForeignPtr GCMStruct -> (AESGcmPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr GCMStruct
g ((AESGcmPtr -> IO ()) -> IO ()) -> (AESGcmPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESGcmPtr
gp ->
       AESKeyPtr
-> AESGcmPtr
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> IO ()
c_gcm_full_encrypt AESKeyPtr
kp AESGcmPtr
gp Ptr Word8
iv Word32
ivLen Ptr Word8
aad Word32
aadLen Ptr Word8
pt Word32
ptLen Ptr Word8
ct Ptr Word8
tag

decryptGCM :: GetExpanded k
           => k
           -> GCMpc
           -> Ptr Word8 -> Word32 -- IV, len
           -> Ptr Word8 -> Word32 -- AAD, len
           -> Ptr Word8 -> Word32 -- CT, len
           -> Ptr Word8           -- PT (out)
           -> Ptr Word8           -- Tag (out)
           -> IO ()
decryptGCM :: k
-> GCMpc
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> IO ()
decryptGCM (k -> ForeignPtr AESKeyStruct
forall a. GetExpanded a => a -> ForeignPtr AESKeyStruct
expandedKey -> ForeignPtr AESKeyStruct
k) (GCMpc ForeignPtr GCMStruct
g) Ptr Word8
iv Word32
ivLen Ptr Word8
aad Word32
aadLen Ptr Word8
ct Word32
ctLen Ptr Word8
pt Ptr Word8
tag =
    ForeignPtr AESKeyStruct -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr AESKeyStruct
k ((AESKeyPtr -> IO ()) -> IO ()) -> (AESKeyPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESKeyPtr
kp ->
      ForeignPtr GCMStruct -> (AESGcmPtr -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr GCMStruct
g ((AESGcmPtr -> IO ()) -> IO ()) -> (AESGcmPtr -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \AESGcmPtr
gp ->
       AESKeyPtr
-> AESGcmPtr
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> IO ()
c_gcm_full_decrypt AESKeyPtr
kp AESGcmPtr
gp Ptr Word8
iv Word32
ivLen Ptr Word8
aad Word32
aadLen Ptr Word8
ct Word32
ctLen Ptr Word8
pt Ptr Word8
tag

{-# INLINE decryptCTR #-}