crypton-2.0.0: Crypto/Cipher/AES.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- |
-- Module : Crypto.Cipher.AES
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : stable
-- Portability : good
--
-- AES, in the modes "Crypto.Cipher.Types" defines.
--
-- == Which implementation runs
--
-- Where the processor has instructions for AES -- AES-NI on x86-64, the
-- cryptographic extensions on AArch64 -- every key size and every mode here
-- goes through them, and a block costs the same whatever the key and the data
-- are.
--
-- Where it does not, the fallback is the table-driven code in
-- @cbits\/aes\/generic.c@, which indexes a 256-byte table with bytes derived
-- from the key and from the block. That is the cache-timing exposure the
-- instructions exist to remove, and on such a machine AES here is not
-- constant time. Every x86-64 part since about 2010 and every AArch64 one in
-- ordinary use has the instructions.
--
-- 'Crypto.System.CPU.processorOptions' says which of the two a given machine
-- got: @AESNI@ in that list means the processor's AES instructions, on either
-- architecture.
module Crypto.Cipher.AES (
AES128,
AES192,
AES256,
) where
import Crypto.Cipher.AES.Primitive
import Crypto.Cipher.Types
import Crypto.Cipher.Types.Block
import Crypto.Cipher.Utils
import Crypto.Error
import Crypto.Internal.Imports
-- | AES with 128 bit key
newtype AES128 = AES128 AES
deriving (NFData)
-- | AES with 192 bit key
newtype AES192 = AES192 AES
deriving (NFData)
-- | AES with 256 bit key
newtype AES256 = AES256 AES
deriving (NFData)
instance Cipher AES128 where
cipherName _ = "AES128"
cipherKeySize _ = KeySizeFixed 16
cipherInit k = AES128 <$> (initAES =<< validateKeySize (undefined :: AES128) k)
instance Cipher AES192 where
cipherName _ = "AES192"
cipherKeySize _ = KeySizeFixed 24
cipherInit k = AES192 <$> (initAES =<< validateKeySize (undefined :: AES192) k)
instance Cipher AES256 where
cipherName _ = "AES256"
cipherKeySize _ = KeySizeFixed 32
cipherInit k = AES256 <$> (initAES =<< validateKeySize (undefined :: AES256) k)
#define INSTANCE_BLOCKCIPHER(CSTR) \
instance BlockCipher CSTR where \
{ blockSize _ = 16 \
; ecbEncrypt (CSTR aes) = encryptECB aes \
; ecbDecrypt (CSTR aes) = decryptECB aes \
; cbcEncrypt (CSTR aes) (IV iv) = encryptCBC aes (IV iv) \
; cbcDecrypt (CSTR aes) (IV iv) = decryptCBC aes (IV iv) \
; ctrCombine (CSTR aes) (IV iv) = encryptCTR aes (IV iv) \
; aeadInit AEAD_GCM (CSTR aes) iv = gcmAeadInit aes iv \
; aeadInit AEAD_OCB (CSTR aes) iv = CryptoPassed $ AEAD (ocbMode aes) (ocbInit aes iv) \
; aeadInit (AEAD_CCM n m l) (CSTR aes) iv = AEAD (ccmMode aes) <$> ccmInit aes iv n m l \
; aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported \
}; \
instance BlockCipher128 CSTR where \
{ xtsEncrypt (CSTR aes1, CSTR aes2) (IV iv) = encryptXTS (aes1,aes2) (IV iv) \
; xtsDecrypt (CSTR aes1, CSTR aes2) (IV iv) = decryptXTS (aes1,aes2) (IV iv) \
};
INSTANCE_BLOCKCIPHER(AES128)
INSTANCE_BLOCKCIPHER(AES192)
INSTANCE_BLOCKCIPHER(AES256)