{-# LANGUAGE CPP #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ConstraintKinds #-}
module Raaz.Cipher.Internal
(
Cipher, CipherMode(..)
, CipherI(..), SomeCipherI(..)
, StreamCipher, makeCipherI
, transform, transform'
, unsafeEncrypt, unsafeDecrypt, unsafeEncrypt', unsafeDecrypt'
) where
import Control.Monad.IO.Class (liftIO)
import Data.ByteString.Internal as IB
import Foreign.Ptr (castPtr)
import System.IO.Unsafe (unsafePerformIO)
import Raaz.Core
import Raaz.Core.Util.ByteString as B
data CipherMode = CBC
| CTR
deriving (Int -> CipherMode -> ShowS
[CipherMode] -> ShowS
CipherMode -> String
(Int -> CipherMode -> ShowS)
-> (CipherMode -> String)
-> ([CipherMode] -> ShowS)
-> Show CipherMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CipherMode] -> ShowS
$cshowList :: [CipherMode] -> ShowS
show :: CipherMode -> String
$cshow :: CipherMode -> String
showsPrec :: Int -> CipherMode -> ShowS
$cshowsPrec :: Int -> CipherMode -> ShowS
Show, CipherMode -> CipherMode -> Bool
(CipherMode -> CipherMode -> Bool)
-> (CipherMode -> CipherMode -> Bool) -> Eq CipherMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CipherMode -> CipherMode -> Bool
$c/= :: CipherMode -> CipherMode -> Bool
== :: CipherMode -> CipherMode -> Bool
$c== :: CipherMode -> CipherMode -> Bool
Eq)
data CipherI cipher encMem decMem = CipherI
{ CipherI cipher encMem decMem -> String
cipherIName :: String
, CipherI cipher encMem decMem -> String
cipherIDescription :: String
, CipherI cipher encMem decMem
-> Pointer -> BLOCKS cipher -> MT encMem ()
encryptBlocks :: Pointer -> BLOCKS cipher -> MT encMem ()
, CipherI cipher encMem decMem
-> Pointer -> BLOCKS cipher -> MT decMem ()
decryptBlocks :: Pointer -> BLOCKS cipher -> MT decMem ()
, CipherI cipher encMem decMem -> Alignment
cipherStartAlignment :: Alignment
}
type CipherM cipher encMem decMem = ( Initialisable encMem (Key cipher)
, Initialisable decMem (Key cipher)
, Primitive cipher
)
data SomeCipherI cipher =
forall encMem decMem . CipherM cipher encMem decMem
=> SomeCipherI (CipherI cipher encMem decMem)
instance BlockAlgorithm (CipherI cipher encMem decMem) where
bufferStartAlignment :: CipherI cipher encMem decMem -> Alignment
bufferStartAlignment = CipherI cipher encMem decMem -> Alignment
forall cipher encMem decMem.
CipherI cipher encMem decMem -> Alignment
cipherStartAlignment
instance Describable (CipherI cipher encMem decMem) where
name :: CipherI cipher encMem decMem -> String
name = CipherI cipher encMem decMem -> String
forall cipher encMem decMem. CipherI cipher encMem decMem -> String
cipherIName
description :: CipherI cipher encMem decMem -> String
description = CipherI cipher encMem decMem -> String
forall cipher encMem decMem. CipherI cipher encMem decMem -> String
cipherIDescription
instance Describable (SomeCipherI cipher) where
name :: SomeCipherI cipher -> String
name (SomeCipherI CipherI cipher encMem decMem
cI) = CipherI cipher encMem decMem -> String
forall d. Describable d => d -> String
name CipherI cipher encMem decMem
cI
description :: SomeCipherI cipher -> String
description (SomeCipherI CipherI cipher encMem decMem
cI) = CipherI cipher encMem decMem -> String
forall d. Describable d => d -> String
description CipherI cipher encMem decMem
cI
instance BlockAlgorithm (SomeCipherI cipher) where
bufferStartAlignment :: SomeCipherI cipher -> Alignment
bufferStartAlignment (SomeCipherI CipherI cipher encMem decMem
imp) = CipherI cipher encMem decMem -> Alignment
forall a. BlockAlgorithm a => a -> Alignment
bufferStartAlignment CipherI cipher encMem decMem
imp
class (Primitive cipher, Implementation cipher ~ SomeCipherI cipher, Describable cipher)
=> Cipher cipher
class Cipher cipher => StreamCipher cipher
makeCipherI :: String
-> String
-> (Pointer -> BLOCKS prim -> MT mem ())
-> Alignment
-> CipherI prim mem mem
makeCipherI :: String
-> String
-> (Pointer -> BLOCKS prim -> MT mem ())
-> Alignment
-> CipherI prim mem mem
makeCipherI String
nm String
des Pointer -> BLOCKS prim -> MT mem ()
trans = String
-> String
-> (Pointer -> BLOCKS prim -> MT mem ())
-> (Pointer -> BLOCKS prim -> MT mem ())
-> Alignment
-> CipherI prim mem mem
forall cipher encMem decMem.
String
-> String
-> (Pointer -> BLOCKS cipher -> MT encMem ())
-> (Pointer -> BLOCKS cipher -> MT decMem ())
-> Alignment
-> CipherI cipher encMem decMem
CipherI String
nm String
des Pointer -> BLOCKS prim -> MT mem ()
trans Pointer -> BLOCKS prim -> MT mem ()
trans
unsafeEncrypt' :: Cipher c
=> c
-> Implementation c
-> Key c
-> ByteString
-> ByteString
unsafeEncrypt' :: c -> Implementation c -> Key c -> ByteString -> ByteString
unsafeEncrypt' c
c simp :: Implementation c
simp@(SomeCipherI imp) Key c
key ByteString
bs = Int -> (Ptr Word8 -> IO ()) -> ByteString
IB.unsafeCreate Int
sbytes Ptr Word8 -> IO ()
go
where sz :: BLOCKS c
sz = BYTES Int -> BLOCKS c
forall src dest. (LengthUnit src, LengthUnit dest) => src -> dest
atMost (ByteString -> BYTES Int
B.length ByteString
bs) BLOCKS c -> BLOCKS c -> BLOCKS c
forall a. a -> a -> a
`asTypeOf` Int -> c -> BLOCKS c
forall p. Int -> p -> BLOCKS p
blocksOf Int
1 c
c
BYTES Int
sbytes = BLOCKS c -> BYTES Int
forall u. LengthUnit u => u -> BYTES Int
inBytes BLOCKS c
sz
go :: Ptr Word8 -> IO ()
go Ptr Word8
ptr = Implementation c -> BLOCKS c -> (Pointer -> IO ()) -> IO ()
forall prim b.
Primitive prim =>
Implementation prim -> BLOCKS prim -> (Pointer -> IO b) -> IO b
allocBufferFor Implementation c
simp BLOCKS c
sz ((Pointer -> IO ()) -> IO ()) -> (Pointer -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Pointer
buf -> MT encMem () -> IO ()
forall (mT :: * -> * -> *) mem a.
(MemoryThread mT, Memory mem) =>
mT mem a -> IO a
insecurely (MT encMem () -> IO ()) -> MT encMem () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Key c -> MT encMem ()
forall m v. Initialisable m v => v -> MT m ()
initialise Key c
key
IO () -> MT encMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT encMem ()) -> IO () -> MT encMem ()
forall a b. (a -> b) -> a -> b
$ BLOCKS c -> ByteString -> Pointer -> IO ()
forall n. LengthUnit n => n -> ByteString -> Pointer -> IO ()
unsafeNCopyToPointer BLOCKS c
sz ByteString
bs Pointer
buf
CipherI c encMem decMem -> Pointer -> BLOCKS c -> MT encMem ()
forall cipher encMem decMem.
CipherI cipher encMem decMem
-> Pointer -> BLOCKS cipher -> MT encMem ()
encryptBlocks CipherI c encMem decMem
imp Pointer
buf BLOCKS c
sz
IO () -> MT encMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT encMem ()) -> IO () -> MT encMem ()
forall a b. (a -> b) -> a -> b
$ Dest Pointer -> Src Pointer -> BLOCKS c -> IO ()
forall (m :: * -> *) l.
(MonadIO m, LengthUnit l) =>
Dest Pointer -> Src Pointer -> l -> m ()
Raaz.Core.memcpy (Pointer -> Dest Pointer
forall a. a -> Dest a
destination (Ptr Word8 -> Pointer
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr)) (Pointer -> Src Pointer
forall a. a -> Src a
source Pointer
buf) BLOCKS c
sz
transform' :: StreamCipher c
=> c
-> Implementation c
-> Key c
-> ByteString
-> ByteString
transform' :: c -> Implementation c -> Key c -> ByteString -> ByteString
transform' c
c simp :: Implementation c
simp@(SomeCipherI imp) Key c
key ByteString
bs = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr Word8 -> IO Int) -> IO ByteString
IB.createAndTrim (BYTES Int -> Int
forall a. Enum a => a -> Int
fromEnum (BYTES Int -> Int) -> BYTES Int -> Int
forall a b. (a -> b) -> a -> b
$ BLOCKS c -> BYTES Int
forall u. LengthUnit u => u -> BYTES Int
inBytes BLOCKS c
blks) Ptr Word8 -> IO Int
action
where blks :: BLOCKS c
blks = BYTES Int -> BLOCKS c
forall src dest. (LengthUnit src, LengthUnit dest) => src -> dest
atLeast BYTES Int
len BLOCKS c -> BLOCKS c -> BLOCKS c
forall a. a -> a -> a
`asTypeOf` Int -> c -> BLOCKS c
forall p. Int -> p -> BLOCKS p
blocksOf Int
1 c
c
len :: BYTES Int
len = ByteString -> BYTES Int
B.length ByteString
bs
action :: Ptr Word8 -> IO Int
action Ptr Word8
ptr = Implementation c -> BLOCKS c -> (Pointer -> IO Int) -> IO Int
forall prim b.
Primitive prim =>
Implementation prim -> BLOCKS prim -> (Pointer -> IO b) -> IO b
allocBufferFor Implementation c
simp BLOCKS c
blks ((Pointer -> IO Int) -> IO Int) -> (Pointer -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ Pointer
buf -> MT encMem Int -> IO Int
forall (mT :: * -> * -> *) mem a.
(MemoryThread mT, Memory mem) =>
mT mem a -> IO a
insecurely (MT encMem Int -> IO Int) -> MT encMem Int -> IO Int
forall a b. (a -> b) -> a -> b
$ do
Key c -> MT encMem ()
forall m v. Initialisable m v => v -> MT m ()
initialise Key c
key
IO () -> MT encMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT encMem ()) -> IO () -> MT encMem ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Pointer -> IO ()
unsafeCopyToPointer ByteString
bs Pointer
buf
CipherI c encMem decMem -> Pointer -> BLOCKS c -> MT encMem ()
forall cipher encMem decMem.
CipherI cipher encMem decMem
-> Pointer -> BLOCKS cipher -> MT encMem ()
encryptBlocks CipherI c encMem decMem
imp Pointer
buf BLOCKS c
blks
IO () -> MT encMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT encMem ()) -> IO () -> MT encMem ()
forall a b. (a -> b) -> a -> b
$ Dest Pointer -> Src Pointer -> BYTES Int -> IO ()
forall (m :: * -> *) l.
(MonadIO m, LengthUnit l) =>
Dest Pointer -> Src Pointer -> l -> m ()
Raaz.Core.memcpy (Pointer -> Dest Pointer
forall a. a -> Dest a
destination (Ptr Word8 -> Pointer
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr)) (Pointer -> Src Pointer
forall a. a -> Src a
source Pointer
buf) BYTES Int
len
Int -> MT encMem Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> MT encMem Int) -> Int -> MT encMem Int
forall a b. (a -> b) -> a -> b
$ BYTES Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral BYTES Int
len
transform :: (StreamCipher c, Recommendation c)
=> c
-> Key c
-> ByteString
-> ByteString
transform :: c -> Key c -> ByteString -> ByteString
transform c
c = c -> Implementation c -> Key c -> ByteString -> ByteString
forall c.
StreamCipher c =>
c -> Implementation c -> Key c -> ByteString -> ByteString
transform' c
c (Implementation c -> Key c -> ByteString -> ByteString)
-> Implementation c -> Key c -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ c -> Implementation c
forall p. Recommendation p => p -> Implementation p
recommended c
c
unsafeEncrypt :: (Cipher c, Recommendation c)
=> c
-> Key c
-> ByteString
-> ByteString
unsafeEncrypt :: c -> Key c -> ByteString -> ByteString
unsafeEncrypt c
c = c -> Implementation c -> Key c -> ByteString -> ByteString
forall c.
Cipher c =>
c -> Implementation c -> Key c -> ByteString -> ByteString
unsafeEncrypt' c
c (Implementation c -> Key c -> ByteString -> ByteString)
-> Implementation c -> Key c -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ c -> Implementation c
forall p. Recommendation p => p -> Implementation p
recommended c
c
unsafeDecrypt' :: Cipher c
=> c
-> Implementation c
-> Key c
-> ByteString
-> ByteString
unsafeDecrypt' :: c -> Implementation c -> Key c -> ByteString -> ByteString
unsafeDecrypt' c
c simp :: Implementation c
simp@(SomeCipherI imp) Key c
key ByteString
bs = Int -> (Ptr Word8 -> IO ()) -> ByteString
IB.unsafeCreate Int
sbytes Ptr Word8 -> IO ()
go
where sz :: BLOCKS c
sz = BYTES Int -> BLOCKS c
forall src dest. (LengthUnit src, LengthUnit dest) => src -> dest
atMost (ByteString -> BYTES Int
B.length ByteString
bs) BLOCKS c -> BLOCKS c -> BLOCKS c
forall a. a -> a -> a
`asTypeOf` Int -> c -> BLOCKS c
forall p. Int -> p -> BLOCKS p
blocksOf Int
1 c
c
BYTES Int
sbytes = BLOCKS c -> BYTES Int
forall u. LengthUnit u => u -> BYTES Int
inBytes BLOCKS c
sz
go :: Ptr Word8 -> IO ()
go Ptr Word8
ptr = Implementation c -> BLOCKS c -> (Pointer -> IO ()) -> IO ()
forall prim b.
Primitive prim =>
Implementation prim -> BLOCKS prim -> (Pointer -> IO b) -> IO b
allocBufferFor Implementation c
simp BLOCKS c
sz ((Pointer -> IO ()) -> IO ()) -> (Pointer -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Pointer
buf -> MT decMem () -> IO ()
forall (mT :: * -> * -> *) mem a.
(MemoryThread mT, Memory mem) =>
mT mem a -> IO a
insecurely (MT decMem () -> IO ()) -> MT decMem () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Key c -> MT decMem ()
forall m v. Initialisable m v => v -> MT m ()
initialise Key c
key
IO () -> MT decMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT decMem ()) -> IO () -> MT decMem ()
forall a b. (a -> b) -> a -> b
$ BLOCKS c -> ByteString -> Pointer -> IO ()
forall n. LengthUnit n => n -> ByteString -> Pointer -> IO ()
unsafeNCopyToPointer BLOCKS c
sz ByteString
bs Pointer
buf
CipherI c encMem decMem -> Pointer -> BLOCKS c -> MT decMem ()
forall cipher encMem decMem.
CipherI cipher encMem decMem
-> Pointer -> BLOCKS cipher -> MT decMem ()
decryptBlocks CipherI c encMem decMem
imp Pointer
buf BLOCKS c
sz
IO () -> MT decMem ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MT decMem ()) -> IO () -> MT decMem ()
forall a b. (a -> b) -> a -> b
$ Dest Pointer -> Src Pointer -> BLOCKS c -> IO ()
forall (m :: * -> *) l.
(MonadIO m, LengthUnit l) =>
Dest Pointer -> Src Pointer -> l -> m ()
Raaz.Core.memcpy (Pointer -> Dest Pointer
forall a. a -> Dest a
destination (Ptr Word8 -> Pointer
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr)) (Pointer -> Src Pointer
forall a. a -> Src a
source Pointer
buf) BLOCKS c
sz
unsafeDecrypt :: (Cipher c, Recommendation c)
=> c
-> Key c
-> ByteString
-> ByteString
unsafeDecrypt :: c -> Key c -> ByteString -> ByteString
unsafeDecrypt c
c = c -> Implementation c -> Key c -> ByteString -> ByteString
forall c.
Cipher c =>
c -> Implementation c -> Key c -> ByteString -> ByteString
unsafeDecrypt' c
c (Implementation c -> Key c -> ByteString -> ByteString)
-> Implementation c -> Key c -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ c -> Implementation c
forall p. Recommendation p => p -> Implementation p
recommended c
c