content: -- |Useful TLS ciphersuites for running Tor.
  module Tor.Link.CipherSuites(
           suiteTLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
         , suiteTLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
         , suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA
         , suiteTLS_DHE_DSS_WITH_AES_256_CBC_SHA
         , suiteTLS_ECDH_RSA_WITH_AES_256_CBC_SHA
         , suiteTLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
         , suiteTLS_RSA_WITH_AES_256_CBC_SHA
         , suiteTLS_ECDHE_ECDSA_WITH_RC4_128_SHA
         , suiteTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
         , suiteTLS_ECDHE_RSA_WITH_RC4_128_SHA
         , suiteTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
         , suiteTLS_DHE_RSA_WITH_AES_128_CBC_SHA
         , suiteTLS_DHE_DSS_WITH_AES_128_CBC_SHA
         , suiteTLS_ECDH_RSA_WITH_RC4_128_SHA
         , suiteTLS_ECDH_RSA_WITH_AES_128_CBC_SHA
         , suiteTLS_ECDH_ECDSA_WITH_RC4_128_SHA
         , suiteTLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
         , suiteTLS_RSA_WITH_RC4_128_MD5
         , suiteTLS_RSA_WITH_RC4_128_SHA
         , suiteTLS_RSA_WITH_AES_128_CBC_SHA
         , suiteTLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
         , suiteTLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
         , suiteSSL3_EDH_RSA_DES_192_CBC3_SHA
         , suiteSSL3_EDH_DSS_DES_192_CBC3_SHA
         , suiteTLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
         , suiteTLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
         , suiteSSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
         , suiteTLS_RSA_WITH_3DES_EDE_CBC_SHA
         , suiteTLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
         , suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA256
         )
   where
  
  import Data.ByteArray
  import Data.ByteString(ByteString)
  import qualified Data.ByteString as B
  import Network.TLS
  import Crypto.Cipher.AES
  import Crypto.Cipher.TripleDES
  import Crypto.Cipher.RC4
  import Crypto.Cipher.Types hiding(Cipher, cipherName)
  import qualified Crypto.Cipher.Types as C
  import Crypto.Error
  
  -- -----------------------------------------------------------------------------
  
  prep :: (C.Cipher c, BlockCipher c, ByteArray key) =>
          key -> (c -> IV c -> ByteString -> ByteString) -> c ->
          BulkBlock
  prep key f _ iv input =
    let output = f ctx (makeIV_ iv) input
    in (output, takeLast 16 output)
   where
    ctx          = noFail (cipherInit key)
    makeIV_      = maybe (error "makeIV_") id . makeIV
    takeLast i b = B.drop (B.length b - i) b
  
  noFail :: CryptoFailable a -> a
  noFail = throwCryptoError
  
  bulkAES128 :: Bulk
  bulkAES128 =
    Bulk {
      bulkName       = "AES128"
    , bulkKeySize    = 16
    , bulkIVSize     = 16
    , bulkExplicitIV = 0
    , bulkAuthTagLen = 0
    , bulkBlockSize  = 16
    , bulkF          = BulkBlockF aes128cbc
    }
   where
    aes128cbc BulkEncrypt key = prep key cbcEncrypt (undefined :: AES128)
    aes128cbc BulkDecrypt key = prep key cbcDecrypt (undefined :: AES128)
  
  bulkAES256 :: Bulk
  bulkAES256 =
    Bulk {
      bulkName       = "AES256"
    , bulkKeySize    = 32
    , bulkIVSize     = 16
    , bulkExplicitIV = 0
    , bulkAuthTagLen = 0
    , bulkBlockSize  = 16
    , bulkF          = BulkBlockF aes256cbc
    }
   where
    aes256cbc BulkEncrypt key = prep key cbcEncrypt (undefined :: AES256)
    aes256cbc BulkDecrypt key = prep key cbcDecrypt (undefined :: AES256)
  
  bulk3DES :: Bulk
  bulk3DES =
    Bulk {
      bulkName       = "3DES-EDE-CBC"
    , bulkKeySize    = 24
    , bulkIVSize     = 8
    , bulkExplicitIV = 0
    , bulkAuthTagLen = 0
    , bulkBlockSize  = 8
    , bulkF          = BulkBlockF tripledes
    }
   where
    tripledes BulkEncrypt key = prep key cbcEncrypt (undefined :: DES_EDE3)
    tripledes BulkDecrypt key = prep key cbcDecrypt (undefined :: DES_EDE3)
  
  bulkRC4 :: Bulk
  bulkRC4 =
    Bulk {
      bulkName       = "RC4-128"
    , bulkKeySize    = 16
    , bulkIVSize     = 0
    , bulkExplicitIV = 0
    , bulkAuthTagLen = 0
    , bulkBlockSize  = 0
    , bulkF          = BulkStreamF rc4
    }
   where
    rc4 _ bulkKey = BulkStream (combineRC4 (initialize bulkKey))
    combineRC4 ctx input =
      let (ctx', output) = combine ctx input
      in (output, BulkStream (combineRC4 ctx'))
  
  -- -----------------------------------------------------------------------------
  
  suiteTLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0xc009
    , cipherName        = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_RSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_ECDHE_RSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0xc014
    , cipherName        = "TLS_ECDHE_RSA_WIT_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0x0039
    , cipherName        = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_DHE_DSS_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_DHE_DSS_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0x0038
    , cipherName        = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DHE_DSS
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_RSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_ECDH_RSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0xc00f
    , cipherName        = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0xc005
    , cipherName        = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_RSA_WITH_AES_256_CBC_SHA :: Cipher
  suiteTLS_RSA_WITH_AES_256_CBC_SHA =
    Cipher {
      cipherID          = 0x0035
    , cipherName        = "TLS_RSA_WITH_AES_256_CBC_SHA"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_ECDSA_WITH_RC4_128_SHA :: Cipher
  suiteTLS_ECDHE_ECDSA_WITH_RC4_128_SHA =
    Cipher {
      cipherID          = 0xc007
    , cipherName        = "TLS_ECDHE_ECDSA_WITH_RC4"
    , cipherBulk        = bulkRC4
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0xc009
    , cipherName        = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_RSA_WITH_RC4_128_SHA :: Cipher
  suiteTLS_ECDHE_RSA_WITH_RC4_128_SHA =
    Cipher {
      cipherID          = 0xc011
    , cipherName        = "TLS_ECDHE_RSA_WITH_RC4_128_SHA"
    , cipherBulk        = bulkRC4
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0xc013
    , cipherName        = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_DHE_RSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_DHE_RSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0x0033
    , cipherName        = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_DHE_DSS_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_DHE_DSS_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0x0032
    , cipherName        = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DHE_DSS
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_RSA_WITH_RC4_128_SHA :: Cipher
  suiteTLS_ECDH_RSA_WITH_RC4_128_SHA =
    Cipher {
      cipherID          = 0xc00c
    , cipherName        = "TLS_ECDH_RSA_WITH_RC4_128_SHA"
    , cipherBulk        = bulkRC4
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_RSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_ECDH_RSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0xc00e
    , cipherName        = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_ECDSA_WITH_RC4_128_SHA :: Cipher
  suiteTLS_ECDH_ECDSA_WITH_RC4_128_SHA =
    Cipher {
      cipherID          = 0xc002
    , cipherName        = "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"
    , cipherBulk        = bulkRC4
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0xc004
    , cipherName        = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_RSA_WITH_RC4_128_MD5 :: Cipher
  suiteTLS_RSA_WITH_RC4_128_MD5 =
    Cipher {
      cipherID          = 0x0004
    , cipherName        = "TLS_RSA_WITH_RC4_128_MD5"
    , cipherBulk        = bulkRC4
    , cipherHash        = MD5
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_RSA_WITH_RC4_128_SHA :: Cipher
  suiteTLS_RSA_WITH_RC4_128_SHA =
    Cipher {
      cipherID          = 0x0005
    , cipherName        = "TLS_RSA_WITH_RC4_128_SHA"
    , cipherBulk        = bulkRC4
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_RSA_WITH_AES_128_CBC_SHA :: Cipher
  suiteTLS_RSA_WITH_AES_128_CBC_SHA =
    Cipher {
      cipherID          = 0x002f
    , cipherName        = "TLS_RSA_WITH_AES_128_CBC_SHA"
    , cipherBulk        = bulkAES128
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0xc008
    , cipherName        = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0xc012
    , cipherName        = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0xc00d
    , cipherName        = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0xc003
    , cipherName        = "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_ECDSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_RSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_RSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0x000a
    , cipherName        = "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteSSL3_EDH_RSA_DES_192_CBC3_SHA :: Cipher
  suiteSSL3_EDH_RSA_DES_192_CBC3_SHA =
    Cipher {
      cipherID          = 0x0016
    , cipherName        = "SSL3_EDH_RSA_DES_192_CBC3_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_ECDH_RSA
    , cipherMinVer      = Just SSL3
    }
  
  suiteSSL3_EDH_DSS_DES_192_CBC3_SHA :: Cipher
  suiteSSL3_EDH_DSS_DES_192_CBC3_SHA =
    Cipher {
      cipherID          = 0x0013
    , cipherName        = "SSL3_EDH_DSS_DES_192_CBC3_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DH_DSS -- FIXME: THIS IS WRONG
    , cipherMinVer      = Just SSL3
    }
  
  suiteSSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteSSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0xFEFF
    , cipherName        = "SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_RSA
    , cipherMinVer      = Just SSL3
    }
  
  suiteTLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA :: Cipher
  suiteTLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
    Cipher {
      cipherID          = 0x0016
    , cipherName        = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"
    , cipherBulk        = bulk3DES
    , cipherHash        = SHA1
    , cipherKeyExchange = CipherKeyExchange_DHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA256 :: Cipher
  suiteTLS_DHE_RSA_WITH_AES_256_CBC_SHA256 =
    Cipher {
      cipherID          = 0x006B
    , cipherName        = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"
    , cipherBulk        = bulkAES256
    , cipherHash        = SHA256
    , cipherKeyExchange = CipherKeyExchange_DHE_RSA
    , cipherMinVer      = Just TLS12
    }
  
  
  