[AEAD] change interface to be less classy (!)

This commit is contained in:
Vincent Hanquez 2015-04-18 06:57:18 +01:00
parent f686733fc6
commit 08732c0939
4 changed files with 47 additions and 46 deletions

View File

@ -7,53 +7,58 @@
-- --
-- AEAD cipher basic types -- AEAD cipher basic types
-- --
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE Rank2Types #-}
module Crypto.Cipher.Types.AEAD where module Crypto.Cipher.Types.AEAD where
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Crypto.Cipher.Types.Base import Crypto.Cipher.Types.Base
import Crypto.Cipher.Types.Block
import Crypto.Internal.ByteArray import Crypto.Internal.ByteArray
import Crypto.Internal.Imports
-- | Append associated data into the AEAD state data AEADModeImpl st = AEADModeImpl
aeadAppendHeader :: BlockCipher a => AEAD a -> ByteString -> AEAD a { aeadImplAppendHeader :: forall ba . ByteArrayAccess ba => st -> ba -> st
aeadAppendHeader (AEAD cipher (AEADState state)) bs = , aeadImplEncrypt :: forall ba . ByteArray ba => st -> ba -> (ba, st)
AEAD cipher $ AEADState (aeadStateAppendHeader cipher state bs) , aeadImplDecrypt :: forall ba . ByteArray ba => st -> ba -> (ba, st)
, aeadImplFinalize :: st -> Int -> AuthTag
}
-- | Encrypt input and append into the AEAD state -- | Authenticated Encryption with Associated Data algorithms
aeadEncrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a) data AEAD cipher = forall st . AEAD
aeadEncrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst)) { aeadModeImpl :: AEADModeImpl st
where (output, nst) = aeadStateEncrypt cipher state input , aeadState :: st
}
-- | Decrypt input and append into the AEAD state aeadAppendHeader :: ByteArrayAccess aad => AEAD cipher -> aad -> AEAD cipher
aeadDecrypt :: BlockCipher a => AEAD a -> ByteString -> (ByteString, AEAD a) aeadAppendHeader (AEAD impl st) aad = AEAD impl $ (aeadImplAppendHeader impl) st aad
aeadDecrypt (AEAD cipher (AEADState state)) input = (output, AEAD cipher (AEADState nst))
where (output, nst) = aeadStateDecrypt cipher state input
-- | Finalize the AEAD state and create an authentification tag aeadEncrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
aeadFinalize :: BlockCipher a => AEAD a -> Int -> AuthTag aeadEncrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplEncrypt impl) st ba
aeadFinalize (AEAD cipher (AEADState state)) len =
aeadStateFinalize cipher state len aeadDecrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
aeadDecrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplDecrypt impl) st ba
aeadFinalize :: AEAD cipher -> Int -> AuthTag
aeadFinalize (AEAD impl st) n = (aeadImplFinalize impl) st n
-- | Simple AEAD encryption -- | Simple AEAD encryption
aeadSimpleEncrypt :: BlockCipher a aeadSimpleEncrypt :: (ByteArrayAccess aad, ByteArray ba)
=> AEAD a -- ^ A new AEAD Context => AEAD a -- ^ A new AEAD Context
-> B.ByteString -- ^ Optional Authentified Header -> aad -- ^ Optional Authentified Header
-> B.ByteString -- ^ Optional Plaintext -> ba -- ^ Optional Plaintext
-> Int -- ^ Tag length -> Int -- ^ Tag length
-> (AuthTag, B.ByteString) -- ^ Authentification tag and ciphertext -> (AuthTag, ba) -- ^ Authentification tag and ciphertext
aeadSimpleEncrypt aeadIni header input taglen = (tag, output) aeadSimpleEncrypt aeadIni header input taglen = (tag, output)
where aead = aeadAppendHeader aeadIni header where aead = aeadAppendHeader aeadIni header
(output, aeadFinal) = aeadEncrypt aead input (output, aeadFinal) = aeadEncrypt aead input
tag = aeadFinalize aeadFinal taglen tag = aeadFinalize aeadFinal taglen
-- | Simple AEAD decryption -- | Simple AEAD decryption
aeadSimpleDecrypt :: BlockCipher a aeadSimpleDecrypt :: (ByteArrayAccess aad, ByteArray ba)
=> AEAD a -- ^ A new AEAD Context => AEAD a -- ^ A new AEAD Context
-> B.ByteString -- ^ Optional Authentified Header -> aad -- ^ Optional Authentified Header
-> B.ByteString -- ^ Optional Plaintext -> ba -- ^ Optional Plaintext
-> AuthTag -- ^ Tag length -> AuthTag -- ^ Tag length
-> Maybe B.ByteString -- ^ Plaintext -> Maybe ba -- ^ Plaintext
aeadSimpleDecrypt aeadIni header input authTag aeadSimpleDecrypt aeadIni header input authTag
| tag == authTag = Just output | tag == authTag = Just output
| otherwise = Nothing | otherwise = Nothing

View File

@ -24,8 +24,12 @@ module Crypto.Cipher.Types.Block
, XTS , XTS
-- * AEAD -- * AEAD
, AEAD(..) , AEAD(..)
, AEADState(..) -- , AEADState(..)
, AEADModeImpl(..) , AEADModeImpl(..)
, aeadAppendHeader
, aeadEncrypt
, aeadDecrypt
, aeadFinalize
-- * CFB 8 bits -- * CFB 8 bits
--, cfb8Encrypt --, cfb8Encrypt
--, cfb8Decrypt --, cfb8Decrypt
@ -35,8 +39,10 @@ import Data.ByteString (ByteString)
import qualified Data.ByteString as B import qualified Data.ByteString as B
import Data.Byteable import Data.Byteable
import Data.Word import Data.Word
import Crypto.Error
import Crypto.Cipher.Types.Base import Crypto.Cipher.Types.Base
import Crypto.Cipher.Types.GF import Crypto.Cipher.Types.GF
import Crypto.Cipher.Types.AEAD
import Crypto.Cipher.Types.Utils import Crypto.Cipher.Types.Utils
import Crypto.Internal.ByteArray import Crypto.Internal.ByteArray
@ -110,8 +116,8 @@ class Cipher cipher => BlockCipher cipher where
-- | Initialize a new AEAD State -- | Initialize a new AEAD State
-- --
-- When Nothing is returns, it means the mode is not handled. -- When Nothing is returns, it means the mode is not handled.
aeadInit :: Byteable iv => AEADMode -> cipher -> iv -> Maybe (AEAD cipher) aeadInit :: ByteArrayAccess iv => AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit _ _ _ = Nothing aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported
-- | class of block cipher with a 128 bits block size -- | class of block cipher with a 128 bits block size
class BlockCipher cipher => BlockCipher128 cipher where class BlockCipher cipher => BlockCipher128 cipher where
@ -139,19 +145,6 @@ class BlockCipher cipher => BlockCipher128 cipher where
-> ba -- ^ Plaintext -> ba -- ^ Plaintext
xtsDecrypt = xtsDecryptGeneric xtsDecrypt = xtsDecryptGeneric
-- | Authenticated Encryption with Associated Data algorithms
data AEAD cipher = AEAD cipher (AEADState cipher)
-- | Wrapper for any AEADState
data AEADState cipher = forall st . AEADModeImpl cipher st => AEADState st
-- | Class of AEAD Mode implementation
class BlockCipher cipher => AEADModeImpl cipher state where
aeadStateAppendHeader :: cipher -> state -> ByteString -> state
aeadStateEncrypt :: cipher -> state -> ByteString -> (ByteString, state)
aeadStateDecrypt :: cipher -> state -> ByteString -> (ByteString, state)
aeadStateFinalize :: cipher -> state -> Int -> AuthTag
-- | Create an IV for a specified block cipher -- | Create an IV for a specified block cipher
makeIV :: (Byteable b, BlockCipher c) => b -> Maybe (IV c) makeIV :: (Byteable b, BlockCipher c) => b -> Maybe (IV c)
makeIV b = toIV undefined makeIV b = toIV undefined

View File

@ -28,6 +28,7 @@ data CryptoError =
-- symmetric cipher errors -- symmetric cipher errors
CryptoError_KeySizeInvalid CryptoError_KeySizeInvalid
| CryptoError_IvSizeInvalid | CryptoError_IvSizeInvalid
| CryptoError_AEADModeNotSupported
deriving (Show,Eq,Enum,Data,Typeable) deriving (Show,Eq,Enum,Data,Typeable)
instance E.Exception CryptoError instance E.Exception CryptoError

View File

@ -57,7 +57,7 @@ data KAT_CFB = KAT_CFB
data KAT_CTR = KAT_CTR data KAT_CTR = KAT_CTR
{ ctrKey :: ByteString -- ^ Key { ctrKey :: ByteString -- ^ Key
, ctrIV :: ByteString -- ^ IV (usually represented as a 128 bits integer) , ctrIV :: ByteString -- ^ IV (usually represented as a 128 bits integer)
, ctrPlaintext :: ByteString -- ^ Plaintext , ctrPlaintext :: ByteString -- ^ Plaintext
, ctrCiphertext :: ByteString -- ^ Ciphertext , ctrCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq) } deriving (Show,Eq)
@ -398,14 +398,16 @@ testBlockCipherAEAD cipher =
toTests _ = testProperty_AEAD toTests _ = testProperty_AEAD
testProperty_AEAD mode (AEADUnit key testIV (unPlaintext -> aad) (unPlaintext -> plaintext)) = withCtx key $ \ctx -> testProperty_AEAD mode (AEADUnit key testIV (unPlaintext -> aad) (unPlaintext -> plaintext)) = withCtx key $ \ctx ->
case aeadInit mode ctx testIV of case aeadInit mode ctx testIV of
Just iniAead -> CryptoPassed iniAead ->
let aead = aeadAppendHeader iniAead aad let aead = aeadAppendHeader iniAead aad
(eText, aeadE) = aeadEncrypt aead plaintext (eText, aeadE) = aeadEncrypt aead plaintext
(dText, aeadD) = aeadDecrypt aead eText (dText, aeadD) = aeadDecrypt aead eText
eTag = aeadFinalize aeadE (blockSize ctx) eTag = aeadFinalize aeadE (blockSize ctx)
dTag = aeadFinalize aeadD (blockSize ctx) dTag = aeadFinalize aeadD (blockSize ctx)
in (plaintext `assertEq` dText) && (eTag `byteArrayEq` dTag) in (plaintext `assertEq` dText) && (eTag `byteArrayEq` dTag)
Nothing -> True CryptoFailed err
| err == CryptoError_AEADModeNotSupported -> True
| otherwise -> error ("testProperty_AEAD: " ++ show err)
withCtx :: Cipher c => Key c -> (c -> a) -> a withCtx :: Cipher c => Key c -> (c -> a) -> a
withCtx (Key key) f = withCtx (Key key) f =