1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
{-# 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)
|