    -- BlockCipher.hs: OpenPGP (RFC4880) block cipher stuff
    -- Copyright © 2013-2016  Clint Adams
    -- This software is released under the terms of the Expat license.
    -- (See the LICENSE file).
    {-# LANGUAGE RankNTypes #-}

    module Codec.Encryption.OpenPGP.BlockCipher
      ( keySize
      , withSymmetricCipher
      ) where

    import Codec.Encryption.OpenPGP.Internal.CryptoCipherTypes (HOWrappedOldCCT(..))
    import Codec.Encryption.OpenPGP.Internal.Cryptonite (HOWrappedCCT(..))
    import Codec.Encryption.OpenPGP.Internal.HOBlockCipher
    import Codec.Encryption.OpenPGP.Types

    import qualified Crypto.Cipher.AES as AES
    import qualified Crypto.Cipher.Blowfish as Blowfish
    import qualified Crypto.Cipher.Camellia as Camellia
    import qualified Crypto.Cipher.TripleDES as TripleDES
    import qualified Crypto.Nettle.Ciphers as CNC
    import qualified Data.ByteString as B

    type HOCipher a
       = forall cipher. HOBlockCipher cipher =>
                          cipher -> Either String a

    withSymmetricCipher ::
         SymmetricAlgorithm -> B.ByteString -> HOCipher a -> Either String a
    withSymmetricCipher :: forall a.
    SymmetricAlgorithm -> ByteString -> HOCipher a -> Either String a
    withSymmetricCipher SymmetricAlgorithm
    Plaintext ByteString
    _ HOCipher a
    _ = String -> Either String a
    forall a b. a -> Either a b
    Left String
    "this shouldn't have happened" -- FIXME: orphan instance?
    withSymmetricCipher SymmetricAlgorithm
    IDEA ByteString
    _ HOCipher a
    _ = String -> Either String a
    forall a b. a -> Either a b
    Left String
    "IDEA not yet implemented" -- FIXME: IDEA
    withSymmetricCipher SymmetricAlgorithm
    ReservedSAFER ByteString
    _ HOCipher a
    _ = String -> Either String a
    forall a b. a -> Either a b
    Left String
    "SAFER not implemented" -- FIXME: or not?
    withSymmetricCipher SymmetricAlgorithm
    ReservedDES ByteString
    _ HOCipher a
    _ = String -> Either String a
    forall a b. a -> Either a b
    Left String
    "DES not implemented" -- FIXME: or not?
    withSymmetricCipher (OtherSA Word8
    _) ByteString
    _ HOCipher a
    _ =
      String -> Either String a
    forall a b. a -> Either a b
    Left String
    "Unknown, unimplemented symmetric algorithm"
    withSymmetricCipher SymmetricAlgorithm
    CAST5 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedOldCCT CAST128)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedOldCCT CNC.CAST128)) Either String (HOWrappedOldCCT CAST128)
    -> (HOWrappedOldCCT CAST128 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedOldCCT CAST128 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    Twofish ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedOldCCT TWOFISH)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedOldCCT CNC.TWOFISH)) Either String (HOWrappedOldCCT TWOFISH)
    -> (HOWrappedOldCCT TWOFISH -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedOldCCT TWOFISH -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    TripleDES ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT DES_EDE3)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT TripleDES.DES_EDE3)) Either String (HOWrappedCCT DES_EDE3)
    -> (HOWrappedCCT DES_EDE3 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT DES_EDE3 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    Blowfish ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT Blowfish128)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT Blowfish.Blowfish128)) Either String (HOWrappedCCT Blowfish128)
    -> (HOWrappedCCT Blowfish128 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT Blowfish128 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    AES128 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT AES128)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT AES.AES128)) Either String (HOWrappedCCT AES128)
    -> (HOWrappedCCT AES128 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT AES128 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    AES192 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT AES192)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT AES.AES192)) Either String (HOWrappedCCT AES192)
    -> (HOWrappedCCT AES192 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT AES192 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    AES256 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT AES256)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT AES.AES256)) Either String (HOWrappedCCT AES256)
    -> (HOWrappedCCT AES256 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT AES256 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    Camellia128 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedCCT Camellia128)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedCCT Camellia.Camellia128)) Either String (HOWrappedCCT Camellia128)
    -> (HOWrappedCCT Camellia128 -> Either String a) -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedCCT Camellia128 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    Camellia192 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedOldCCT Camellia192)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedOldCCT CNC.Camellia192)) Either String (HOWrappedOldCCT Camellia192)
    -> (HOWrappedOldCCT Camellia192 -> Either String a)
    -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedOldCCT Camellia192 -> Either String a
    HOCipher a
    f
    withSymmetricCipher SymmetricAlgorithm
    Camellia256 ByteString
    key HOCipher a
    f =
      (ByteString -> Either String (HOWrappedOldCCT Camellia256)
    forall cipher.
    HOBlockCipher cipher =>
    ByteString -> Either String cipher
    cipherInit ByteString
    key :: Either String (HOWrappedOldCCT CNC.Camellia256)) Either String (HOWrappedOldCCT Camellia256)
    -> (HOWrappedOldCCT Camellia256 -> Either String a)
    -> Either String a
    forall a b.
    Either String a -> (a -> Either String b) -> Either String b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= HOWrappedOldCCT Camellia256 -> Either String a
    HOCipher a
    f

    -- in octets; FIXME: co-opt Cipher's cipherKeySize or not?
    keySize :: SymmetricAlgorithm -> Int
    keySize :: SymmetricAlgorithm -> Int
    keySize SymmetricAlgorithm
    Plaintext = Int
    0
    keySize SymmetricAlgorithm
    IDEA = Int
    16 -- according to https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
    keySize SymmetricAlgorithm
    TripleDES = Int
    24 -- RFC 4880 says 168 bits (derived from 192 bits) but we don't know who does the derivation
    keySize SymmetricAlgorithm
    CAST5 = Int
    16
    keySize SymmetricAlgorithm
    Blowfish = Int
    16
    keySize SymmetricAlgorithm
    ReservedSAFER = Int
    forall a. HasCallStack => a
    undefined
    keySize SymmetricAlgorithm
    ReservedDES = Int
    forall a. HasCallStack => a
    undefined
    keySize SymmetricAlgorithm
    AES128 = Int
    16
    keySize SymmetricAlgorithm
    AES192 = Int
    24
    keySize SymmetricAlgorithm
    AES256 = Int
    32
    keySize SymmetricAlgorithm
    Twofish = Int
    32
    keySize SymmetricAlgorithm
    Camellia128 = Int
    16
    keySize SymmetricAlgorithm
    Camellia192 = Int
    24
    keySize SymmetricAlgorithm
    Camellia256 = Int
    32
    keySize (OtherSA Word8
    _) = Int
    forall a. HasCallStack => a
    undefined