{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Network.TLS.Types.Cipher where import Crypto.Cipher.Types (AuthTag) import Data.IORef import GHC.Generics import System.IO.Unsafe (unsafePerformIO) import Text.Printf import Network.TLS.Crypto (Hash (..)) import Network.TLS.Imports import Network.TLS.Types.Version ---------------------------------------------------------------- -- | Cipher identification type CipherID = Word16 newtype CipherId = CipherId {fromCipherId :: Word16} deriving (Eq, Ord, Enum, Num, Integral, Real, Read, Generic) instance Show CipherId where show (CipherId 0x00FF) = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" show (CipherId n) = case find eqID dict of Just c -> cipherName c Nothing -> printf "0x%04X" n where eqID c = cipherID c == n dict = unsafePerformIO $ readIORef globalCipherDict -- "ciphersuite" is designed extensible. -- So, it's not available from internal modules. -- This is a compromise to gule "ciphersuite" to Show CipherID. {-# NOINLINE globalCipherDict #-} globalCipherDict :: IORef [Cipher] globalCipherDict = unsafePerformIO $ newIORef [] ---------------------------------------------------------------- -- | Cipher algorithm data Cipher = Cipher { cipherID :: CipherID , cipherName :: String , cipherHash :: Hash , cipherBulk :: Bulk , cipherKeyExchange :: CipherKeyExchangeType , cipherMinVer :: Maybe Version , cipherPRFHash :: Maybe Hash } instance Show Cipher where show c = cipherName c instance Eq Cipher where (==) c1 c2 = cipherID c1 == cipherID c2 ---------------------------------------------------------------- data CipherKeyExchangeType = CipherKeyExchange_RSA | CipherKeyExchange_DH_Anon | CipherKeyExchange_DHE_RSA | CipherKeyExchange_ECDHE_RSA | CipherKeyExchange_DHE_DSA | CipherKeyExchange_DH_DSA | CipherKeyExchange_DH_RSA | CipherKeyExchange_ECDH_ECDSA | CipherKeyExchange_ECDH_RSA | CipherKeyExchange_ECDHE_ECDSA | CipherKeyExchange_TLS13 -- not expressed in cipher suite deriving (Show, Eq) ---------------------------------------------------------------- data Bulk = Bulk { bulkName :: String , bulkKeySize :: Int , bulkIVSize :: Int , bulkExplicitIV :: Int -- Explicit size for IV for AEAD Cipher, 0 otherwise , bulkAuthTagLen :: Int -- Authentication tag length in bytes for AEAD Cipher, 0 otherwise , bulkBlockSize :: Int , bulkF :: BulkFunctions } instance Show Bulk where show bulk = bulkName bulk instance Eq Bulk where b1 == b2 = and [ bulkName b1 == bulkName b2 , bulkKeySize b1 == bulkKeySize b2 , bulkIVSize b1 == bulkIVSize b2 , bulkBlockSize b1 == bulkBlockSize b2 ] ---------------------------------------------------------------- data BulkFunctions = BulkBlockF (BulkDirection -> BulkKey -> BulkBlock) | BulkStreamF (BulkDirection -> BulkKey -> BulkStream) | BulkAeadF (BulkDirection -> BulkKey -> BulkAEAD) data BulkDirection = BulkEncrypt | BulkDecrypt deriving (Show, Eq) type BulkBlock = BulkIV -> ByteString -> (ByteString, BulkIV) type BulkKey = ByteString type BulkIV = ByteString type BulkNonce = ByteString type BulkAdditionalData = ByteString newtype BulkStream = BulkStream (ByteString -> (ByteString, BulkStream)) type BulkAEAD = BulkNonce -> ByteString -> BulkAdditionalData -> (ByteString, AuthTag)