hs-tls/Network/TLS/Struct.hs

465 lines
16 KiB
Haskell
Raw Normal View History

2011-03-02 08:43:05 +00:00
{-# OPTIONS_HADDOCK hide #-}
2011-05-12 08:07:49 +00:00
{-# LANGUAGE DeriveDataTypeable #-}
2010-09-09 21:47:19 +00:00
-- |
-- Module : Network.TLS.Struct
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
-- the Struct module contains all definitions and values of the TLS protocol
--
module Network.TLS.Struct
2012-03-27 07:57:51 +00:00
( Bytes
, Version(..)
, ConnectionEnd(..)
, CipherType(..)
, CipherData(..)
, ExtensionID
2012-05-14 03:41:50 +00:00
, ExtensionRaw
2012-03-27 07:57:51 +00:00
, CertificateType(..)
, HashAlgorithm(..)
, SignatureAlgorithm(..)
, HashAndSignatureAlgorithm
2012-03-27 07:57:51 +00:00
, ProtocolType(..)
, TLSError(..)
, DistinguishedName(..)
2012-03-27 07:57:51 +00:00
, ServerDHParams(..)
, ServerRSAParams(..)
, ServerKeyXchgAlgorithmData(..)
, Packet(..)
, Header(..)
, ServerRandom(..)
, ClientRandom(..)
, serverRandom
, clientRandom
, FinishedData
, SessionID
, Session(..)
, SessionData(..)
2012-07-28 12:40:11 +00:00
, CertVerifyData(..)
2012-03-27 07:57:51 +00:00
, AlertLevel(..)
, AlertDescription(..)
, HandshakeType(..)
, Handshake(..)
, numericalVer
, verOfNum
, TypeValuable, valOfType, valToType
, packetType
, typeOfHandshake
) where
2010-09-09 21:47:19 +00:00
import Data.ByteString (ByteString)
import qualified Data.ByteString as B (length)
2010-09-09 21:47:19 +00:00
import Data.Word
2011-10-11 04:36:15 +00:00
import Data.Certificate.X509 (X509)
import Data.Certificate.X509.Cert (ASN1String, OID)
2011-05-12 08:07:49 +00:00
import Data.Typeable
import Control.Monad.Error (Error(..))
2011-05-12 08:07:49 +00:00
import Control.Exception (Exception(..))
import Network.TLS.Types
2010-09-09 21:47:19 +00:00
type Bytes = ByteString
2010-09-09 21:47:19 +00:00
data ConnectionEnd = ConnectionServer | ConnectionClient
data CipherType = CipherStream | CipherBlock | CipherAEAD
data CipherData = CipherData
2012-03-27 07:57:51 +00:00
{ cipherDataContent :: Bytes
, cipherDataMAC :: Maybe Bytes
, cipherDataPadding :: Maybe Bytes
} deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data CertificateType =
2012-03-27 07:57:51 +00:00
CertificateType_RSA_Sign -- TLS10
| CertificateType_DSS_Sign -- TLS10
| CertificateType_RSA_Fixed_DH -- TLS10
| CertificateType_DSS_Fixed_DH -- TLS10
| CertificateType_RSA_Ephemeral_DH -- TLS12
| CertificateType_DSS_Ephemeral_DH -- TLS12
| CertificateType_fortezza_dms -- TLS12
| CertificateType_Unknown Word8
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data HashAlgorithm =
2012-03-27 07:57:51 +00:00
HashNone
| HashMD5
| HashSHA1
| HashSHA224
| HashSHA256
| HashSHA384
| HashSHA512
| HashOther Word8
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data SignatureAlgorithm =
2012-03-27 07:57:51 +00:00
SignatureAnonymous
| SignatureRSA
| SignatureDSS
| SignatureECDSA
| SignatureOther Word8
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
type HashAndSignatureAlgorithm = (HashAlgorithm, SignatureAlgorithm)
2010-09-09 21:47:19 +00:00
data ProtocolType =
2012-03-27 07:57:51 +00:00
ProtocolType_ChangeCipherSpec
| ProtocolType_Alert
| ProtocolType_Handshake
| ProtocolType_AppData
deriving (Eq, Show)
2010-09-09 21:47:19 +00:00
2011-03-02 08:43:05 +00:00
-- | TLSError that might be returned through the TLS stack
2010-09-09 21:47:19 +00:00
data TLSError =
2012-03-27 07:57:51 +00:00
Error_Misc String -- ^ mainly for instance of Error
| Error_Protocol (String, Bool, AlertDescription)
| Error_Certificate String
| Error_HandshakePolicy String -- ^ handshake policy failed.
| Error_Random String
| Error_EOF
| Error_Packet String
| Error_Packet_Size_Mismatch (Int, Int)
| Error_Packet_unexpected String String
| Error_Packet_Parsing String
| Error_Internal_Packet_ByteProcessed Int Int Int
| Error_Unknown_Version Word8 Word8
| Error_Unknown_Type String
deriving (Eq, Show, Typeable)
2010-09-09 21:47:19 +00:00
instance Error TLSError where
2012-03-27 07:57:51 +00:00
noMsg = Error_Misc ""
strMsg = Error_Misc
2011-05-12 08:07:49 +00:00
instance Exception TLSError
2010-09-09 21:47:19 +00:00
data Packet =
2012-03-27 07:57:51 +00:00
Handshake [Handshake]
| Alert [(AlertLevel, AlertDescription)]
| ChangeCipherSpec
| AppData ByteString
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
2011-08-12 17:33:43 +00:00
data Header = Header ProtocolType Version Word16 deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
newtype ServerRandom = ServerRandom Bytes deriving (Show, Eq)
newtype ClientRandom = ClientRandom Bytes deriving (Show, Eq)
2011-12-12 08:25:21 +00:00
newtype Session = Session (Maybe SessionID) deriving (Show, Eq)
type FinishedData = Bytes
type ExtensionID = Word16
type ExtensionRaw = (ExtensionID, Bytes)
2010-09-09 21:47:19 +00:00
2012-07-28 12:40:11 +00:00
newtype CertVerifyData = CertVerifyData Bytes
deriving (Show, Eq)
constrRandom32 :: (Bytes -> a) -> Bytes -> Maybe a
constrRandom32 constr l = if B.length l == 32 then Just (constr l) else Nothing
2010-09-09 21:47:19 +00:00
serverRandom :: Bytes -> Maybe ServerRandom
2010-09-09 21:47:19 +00:00
serverRandom l = constrRandom32 ServerRandom l
clientRandom :: Bytes -> Maybe ClientRandom
2010-09-09 21:47:19 +00:00
clientRandom l = constrRandom32 ClientRandom l
data AlertLevel =
2012-03-27 07:57:51 +00:00
AlertLevel_Warning
| AlertLevel_Fatal
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data AlertDescription =
2012-03-27 07:57:51 +00:00
CloseNotify
| UnexpectedMessage
| BadRecordMac
| DecryptionFailed -- ^ deprecated alert, should never be sent by compliant implementation
| RecordOverflow
| DecompressionFailure
| HandshakeFailure
| BadCertificate
| UnsupportedCertificate
| CertificateRevoked
| CertificateExpired
| CertificateUnknown
| IllegalParameter
| UnknownCa
| AccessDenied
| DecodeError
| DecryptError
| ExportRestriction
| ProtocolVersion
| InsufficientSecurity
| InternalError
| UserCanceled
| NoRenegotiation
| UnsupportedExtension
2012-08-27 15:25:35 +00:00
| CertificateUnobtainable
| UnrecognizedName
| BadCertificateStatusResponse
| BadCertificateHashValue
2012-03-27 07:57:51 +00:00
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data HandshakeType =
2012-03-27 07:57:51 +00:00
HandshakeType_HelloRequest
| HandshakeType_ClientHello
| HandshakeType_ServerHello
| HandshakeType_Certificate
| HandshakeType_ServerKeyXchg
| HandshakeType_CertRequest
| HandshakeType_ServerHelloDone
| HandshakeType_CertVerify
| HandshakeType_ClientKeyXchg
| HandshakeType_Finished
| HandshakeType_NPN -- Next Protocol Negotiation extension
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data ServerDHParams = ServerDHParams
2012-03-27 07:57:51 +00:00
{ dh_p :: Integer -- ^ prime modulus
, dh_g :: Integer -- ^ generator
, dh_Ys :: Integer -- ^ public value (g^X mod p)
} deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data ServerRSAParams = ServerRSAParams
2012-03-27 07:57:51 +00:00
{ rsa_modulus :: Integer
, rsa_exponent :: Integer
} deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data ServerKeyXchgAlgorithmData =
2012-03-27 07:57:51 +00:00
SKX_DH_Anon ServerDHParams
| SKX_DHE_DSS ServerDHParams [Word8]
| SKX_DHE_RSA ServerDHParams [Word8]
| SKX_RSA (Maybe ServerRSAParams)
| SKX_DH_DSS (Maybe ServerRSAParams)
| SKX_DH_RSA (Maybe ServerRSAParams)
| SKX_Unknown Bytes
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
data DistinguishedName = DistinguishedName [(OID, ASN1String)]
deriving (Eq, Show)
2010-09-09 21:47:19 +00:00
data Handshake =
2012-05-14 03:41:50 +00:00
ClientHello !Version !ClientRandom !Session ![CipherID] ![CompressionID] [ExtensionRaw]
| ServerHello !Version !ServerRandom !Session !CipherID !CompressionID [ExtensionRaw]
2012-03-27 07:57:51 +00:00
| Certificates [X509]
| HelloRequest
| ServerHelloDone
| ClientKeyXchg Bytes
| ServerKeyXchg ServerKeyXchgAlgorithmData
| CertRequest [CertificateType] (Maybe [ HashAndSignatureAlgorithm ]) [DistinguishedName]
| CertVerify (Maybe HashAndSignatureAlgorithm) CertVerifyData
2012-03-27 07:57:51 +00:00
| Finished FinishedData
| HsNextProtocolNegotiation Bytes -- NPN extension
2012-03-27 07:57:51 +00:00
deriving (Show,Eq)
2010-09-09 21:47:19 +00:00
packetType :: Packet -> ProtocolType
packetType (Handshake _) = ProtocolType_Handshake
packetType (Alert _) = ProtocolType_Alert
packetType ChangeCipherSpec = ProtocolType_ChangeCipherSpec
packetType (AppData _) = ProtocolType_AppData
typeOfHandshake :: Handshake -> HandshakeType
2012-02-07 21:24:30 +00:00
typeOfHandshake (ClientHello {}) = HandshakeType_ClientHello
typeOfHandshake (ServerHello {}) = HandshakeType_ServerHello
typeOfHandshake (Certificates {}) = HandshakeType_Certificate
typeOfHandshake HelloRequest = HandshakeType_HelloRequest
typeOfHandshake (ServerHelloDone) = HandshakeType_ServerHelloDone
typeOfHandshake (ClientKeyXchg {}) = HandshakeType_ClientKeyXchg
typeOfHandshake (ServerKeyXchg {}) = HandshakeType_ServerKeyXchg
typeOfHandshake (CertRequest {}) = HandshakeType_CertRequest
typeOfHandshake (CertVerify {}) = HandshakeType_CertVerify
typeOfHandshake (Finished {}) = HandshakeType_Finished
typeOfHandshake (HsNextProtocolNegotiation {}) = HandshakeType_NPN
2010-09-09 21:47:19 +00:00
numericalVer :: Version -> (Word8, Word8)
numericalVer SSL2 = (2, 0)
numericalVer SSL3 = (3, 0)
numericalVer TLS10 = (3, 1)
numericalVer TLS11 = (3, 2)
numericalVer TLS12 = (3, 3)
verOfNum :: (Word8, Word8) -> Maybe Version
verOfNum (2, 0) = Just SSL2
verOfNum (3, 0) = Just SSL3
verOfNum (3, 1) = Just TLS10
verOfNum (3, 2) = Just TLS11
verOfNum (3, 3) = Just TLS12
verOfNum _ = Nothing
class TypeValuable a where
2012-03-27 07:57:51 +00:00
valOfType :: a -> Word8
valToType :: Word8 -> Maybe a
2010-09-09 21:47:19 +00:00
instance TypeValuable ConnectionEnd where
2012-03-27 07:57:51 +00:00
valOfType ConnectionServer = 0
valOfType ConnectionClient = 1
2010-09-09 21:47:19 +00:00
2012-03-27 07:57:51 +00:00
valToType 0 = Just ConnectionServer
valToType 1 = Just ConnectionClient
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable CipherType where
2012-03-27 07:57:51 +00:00
valOfType CipherStream = 0
valOfType CipherBlock = 1
valOfType CipherAEAD = 2
2010-09-09 21:47:19 +00:00
2012-03-27 07:57:51 +00:00
valToType 0 = Just CipherStream
valToType 1 = Just CipherBlock
valToType 2 = Just CipherAEAD
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable ProtocolType where
2012-03-27 07:57:51 +00:00
valOfType ProtocolType_ChangeCipherSpec = 20
valOfType ProtocolType_Alert = 21
valOfType ProtocolType_Handshake = 22
valOfType ProtocolType_AppData = 23
2010-09-09 21:47:19 +00:00
2012-03-27 07:57:51 +00:00
valToType 20 = Just ProtocolType_ChangeCipherSpec
valToType 21 = Just ProtocolType_Alert
valToType 22 = Just ProtocolType_Handshake
valToType 23 = Just ProtocolType_AppData
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable HandshakeType where
2012-03-27 07:57:51 +00:00
valOfType HandshakeType_HelloRequest = 0
valOfType HandshakeType_ClientHello = 1
valOfType HandshakeType_ServerHello = 2
valOfType HandshakeType_Certificate = 11
valOfType HandshakeType_ServerKeyXchg = 12
valOfType HandshakeType_CertRequest = 13
valOfType HandshakeType_ServerHelloDone = 14
valOfType HandshakeType_CertVerify = 15
valOfType HandshakeType_ClientKeyXchg = 16
valOfType HandshakeType_Finished = 20
valOfType HandshakeType_NPN = 67
valToType 0 = Just HandshakeType_HelloRequest
valToType 1 = Just HandshakeType_ClientHello
valToType 2 = Just HandshakeType_ServerHello
valToType 11 = Just HandshakeType_Certificate
valToType 12 = Just HandshakeType_ServerKeyXchg
valToType 13 = Just HandshakeType_CertRequest
valToType 14 = Just HandshakeType_ServerHelloDone
valToType 15 = Just HandshakeType_CertVerify
valToType 16 = Just HandshakeType_ClientKeyXchg
valToType 20 = Just HandshakeType_Finished
valToType 67 = Just HandshakeType_NPN
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable AlertLevel where
2012-03-27 07:57:51 +00:00
valOfType AlertLevel_Warning = 1
valOfType AlertLevel_Fatal = 2
2010-09-09 21:47:19 +00:00
2012-03-27 07:57:51 +00:00
valToType 1 = Just AlertLevel_Warning
valToType 2 = Just AlertLevel_Fatal
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable AlertDescription where
2012-03-27 07:57:51 +00:00
valOfType CloseNotify = 0
valOfType UnexpectedMessage = 10
valOfType BadRecordMac = 20
valOfType DecryptionFailed = 21
valOfType RecordOverflow = 22
valOfType DecompressionFailure = 30
valOfType HandshakeFailure = 40
valOfType BadCertificate = 42
valOfType UnsupportedCertificate = 43
valOfType CertificateRevoked = 44
valOfType CertificateExpired = 45
valOfType CertificateUnknown = 46
valOfType IllegalParameter = 47
valOfType UnknownCa = 48
valOfType AccessDenied = 49
valOfType DecodeError = 50
valOfType DecryptError = 51
valOfType ExportRestriction = 60
valOfType ProtocolVersion = 70
valOfType InsufficientSecurity = 71
valOfType InternalError = 80
valOfType UserCanceled = 90
valOfType NoRenegotiation = 100
valOfType UnsupportedExtension = 110
2012-08-27 15:25:35 +00:00
valOfType CertificateUnobtainable = 111
valOfType UnrecognizedName = 112
valOfType BadCertificateStatusResponse = 113
valOfType BadCertificateHashValue = 114
2012-03-27 07:57:51 +00:00
valToType 0 = Just CloseNotify
valToType 10 = Just UnexpectedMessage
valToType 20 = Just BadRecordMac
valToType 21 = Just DecryptionFailed
valToType 22 = Just RecordOverflow
valToType 30 = Just DecompressionFailure
valToType 40 = Just HandshakeFailure
valToType 42 = Just BadCertificate
valToType 43 = Just UnsupportedCertificate
valToType 44 = Just CertificateRevoked
valToType 45 = Just CertificateExpired
valToType 46 = Just CertificateUnknown
valToType 47 = Just IllegalParameter
valToType 48 = Just UnknownCa
valToType 49 = Just AccessDenied
valToType 50 = Just DecodeError
valToType 51 = Just DecryptError
valToType 60 = Just ExportRestriction
valToType 70 = Just ProtocolVersion
valToType 71 = Just InsufficientSecurity
valToType 80 = Just InternalError
valToType 90 = Just UserCanceled
valToType 100 = Just NoRenegotiation
valToType 110 = Just UnsupportedExtension
2012-08-27 15:25:35 +00:00
valToType 111 = Just CertificateUnobtainable
valToType 112 = Just UnrecognizedName
valToType 113 = Just BadCertificateStatusResponse
valToType 114 = Just BadCertificateHashValue
2012-03-27 07:57:51 +00:00
valToType _ = Nothing
2010-09-09 21:47:19 +00:00
instance TypeValuable CertificateType where
2012-03-27 07:57:51 +00:00
valOfType CertificateType_RSA_Sign = 1
valOfType CertificateType_DSS_Sign = 2
valOfType CertificateType_RSA_Fixed_DH = 3
valOfType CertificateType_DSS_Fixed_DH = 4
valOfType CertificateType_RSA_Ephemeral_DH = 5
valOfType CertificateType_DSS_Ephemeral_DH = 6
valOfType CertificateType_fortezza_dms = 20
valOfType (CertificateType_Unknown i) = i
valToType 1 = Just CertificateType_RSA_Sign
valToType 2 = Just CertificateType_DSS_Sign
valToType 3 = Just CertificateType_RSA_Fixed_DH
valToType 4 = Just CertificateType_DSS_Fixed_DH
valToType 5 = Just CertificateType_RSA_Ephemeral_DH
valToType 6 = Just CertificateType_DSS_Ephemeral_DH
valToType 20 = Just CertificateType_fortezza_dms
valToType i = Just (CertificateType_Unknown i)
2010-09-09 21:47:19 +00:00
instance TypeValuable HashAlgorithm where
2012-03-27 07:57:51 +00:00
valOfType HashNone = 0
valOfType HashMD5 = 1
valOfType HashSHA1 = 2
valOfType HashSHA224 = 3
valOfType HashSHA256 = 4
valOfType HashSHA384 = 5
valOfType HashSHA512 = 6
valOfType (HashOther i) = i
valToType 0 = Just HashNone
valToType 1 = Just HashMD5
valToType 2 = Just HashSHA1
valToType 3 = Just HashSHA224
valToType 4 = Just HashSHA256
valToType 5 = Just HashSHA384
valToType 6 = Just HashSHA512
valToType i = Just (HashOther i)
2010-09-09 21:47:19 +00:00
instance TypeValuable SignatureAlgorithm where
2012-03-27 07:57:51 +00:00
valOfType SignatureAnonymous = 0
valOfType SignatureRSA = 1
valOfType SignatureDSS = 2
valOfType SignatureECDSA = 3
valOfType (SignatureOther i) = i
valToType 0 = Just SignatureAnonymous
valToType 1 = Just SignatureRSA
valToType 2 = Just SignatureDSS
valToType 3 = Just SignatureECDSA
valToType i = Just (SignatureOther i)