-- CryptoAES.hs: OpenPGP (RFC9580) AES helper utilities
-- Copyright © 2012-2026  Clint Adams
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).

{-# LANGUAGE PackageImports #-}
{-# LANGUAGE RankNTypes #-}

module Codec.Encryption.OpenPGP.Internal.CryptoAES
  ( withAESCipher
  ) where

import Codec.Encryption.OpenPGP.Types
import qualified "crypton" Crypto.Cipher.AES as AES
import qualified "crypton" Crypto.Cipher.Types as CCT
import qualified Crypto.Error as CE
import Data.Bifunctor (first)
import qualified Data.ByteString as B

withAESCipher ::
     String
  -> SymmetricAlgorithm
  -> B.ByteString
  -> (forall cipher. CCT.BlockCipher cipher => cipher -> Either String a)
  -> Either String a
withAESCipher :: forall a.
String
-> SymmetricAlgorithm
-> ByteString
-> (forall cipher. BlockCipher cipher => cipher -> Either String a)
-> Either String a
withAESCipher String
unsupportedSymmetricError SymmetricAlgorithm
symalgo ByteString
keyBytes forall cipher. BlockCipher cipher => cipher -> Either String a
f =
  case SymmetricAlgorithm
symalgo of
    SymmetricAlgorithm
AES128 ->
      (CryptoError -> String)
-> Either CryptoError AES128 -> Either String AES128
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first CryptoError -> String
forall a. Show a => a -> String
show (CryptoFailable AES128 -> Either CryptoError AES128
forall a. CryptoFailable a -> Either CryptoError a
CE.eitherCryptoError (ByteString -> CryptoFailable AES128
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES128
CCT.cipherInit ByteString
keyBytes :: CE.CryptoFailable AES.AES128)) Either String AES128
-> (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
>>=
      AES128 -> Either String a
forall cipher. BlockCipher cipher => cipher -> Either String a
f
    SymmetricAlgorithm
AES192 ->
      (CryptoError -> String)
-> Either CryptoError AES192 -> Either String AES192
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first CryptoError -> String
forall a. Show a => a -> String
show (CryptoFailable AES192 -> Either CryptoError AES192
forall a. CryptoFailable a -> Either CryptoError a
CE.eitherCryptoError (ByteString -> CryptoFailable AES192
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES192
CCT.cipherInit ByteString
keyBytes :: CE.CryptoFailable AES.AES192)) Either String AES192
-> (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
>>=
      AES192 -> Either String a
forall cipher. BlockCipher cipher => cipher -> Either String a
f
    SymmetricAlgorithm
AES256 ->
      (CryptoError -> String)
-> Either CryptoError AES256 -> Either String AES256
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first CryptoError -> String
forall a. Show a => a -> String
show (CryptoFailable AES256 -> Either CryptoError AES256
forall a. CryptoFailable a -> Either CryptoError a
CE.eitherCryptoError (ByteString -> CryptoFailable AES256
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES256
CCT.cipherInit ByteString
keyBytes :: CE.CryptoFailable AES.AES256)) Either String AES256
-> (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
>>=
      AES256 -> Either String a
forall cipher. BlockCipher cipher => cipher -> Either String a
f
    SymmetricAlgorithm
_ -> String -> Either String a
forall a b. a -> Either a b
Left String
unsupportedSymmetricError