-- 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 qualified Crypto.Error as CE
import Data.Bifunctor (first)
import qualified Data.ByteString as B
import qualified "crypton" Crypto.Cipher.AES as AES
import qualified "crypton" Crypto.Cipher.Types as CCT

import Codec.Encryption.OpenPGP.Types

withAESCipher
    :: (CE.CryptoError -> e)
    -> e
    -> SymmetricAlgorithm
    -> B.ByteString
    -> (forall cipher. CCT.BlockCipher cipher => cipher -> Either e a)
    -> Either e a
withAESCipher :: forall e a.
(CryptoError -> e)
-> e
-> SymmetricAlgorithm
-> ByteString
-> (forall cipher. BlockCipher cipher => cipher -> Either e a)
-> Either e a
withAESCipher CryptoError -> e
mkCryptoError e
unsupportedSymmetricError SymmetricAlgorithm
symalgo ByteString
keyBytes forall cipher. BlockCipher cipher => cipher -> Either e a
f =
    case SymmetricAlgorithm
symalgo of
        SymmetricAlgorithm
AES128 ->
            (CryptoError -> e) -> Either CryptoError AES128 -> Either e 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 -> e
mkCryptoError
                ( 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 e AES128 -> (AES128 -> Either e a) -> Either e a
forall a b. Either e a -> (a -> Either e b) -> Either e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= AES128 -> Either e a
forall cipher. BlockCipher cipher => cipher -> Either e a
f
        SymmetricAlgorithm
AES192 ->
            (CryptoError -> e) -> Either CryptoError AES192 -> Either e 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 -> e
mkCryptoError
                ( 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 e AES192 -> (AES192 -> Either e a) -> Either e a
forall a b. Either e a -> (a -> Either e b) -> Either e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= AES192 -> Either e a
forall cipher. BlockCipher cipher => cipher -> Either e a
f
        SymmetricAlgorithm
AES256 ->
            (CryptoError -> e) -> Either CryptoError AES256 -> Either e 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 -> e
mkCryptoError
                ( 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 e AES256 -> (AES256 -> Either e a) -> Either e a
forall a b. Either e a -> (a -> Either e b) -> Either e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= AES256 -> Either e a
forall cipher. BlockCipher cipher => cipher -> Either e a
f
        SymmetricAlgorithm
_ -> e -> Either e a
forall a b. a -> Either a b
Left e
unsupportedSymmetricError