packages feed

tls-2.4.10: Network/TLS/HashAndSignature.hs

{-# LANGUAGE PatternSynonyms #-}

module Network.TLS.HashAndSignature (
    HashAlgorithm (
        ..,
        HashNone,
        HashMD5,
        HashSHA1,
        HashSHA224,
        HashSHA256,
        HashSHA384,
        HashSHA512,
        HashIntrinsic,
        HashMLDSA
    ),
    SignatureAlgorithm (
        ..,
        SignatureAnonymous,
        SignatureRSA,
        SignatureDSA,
        SignatureECDSA,
        SignatureRSApssRSAeSHA256,
        SignatureRSApssRSAeSHA384,
        SignatureRSApssRSAeSHA512,
        SignatureEd25519,
        SignatureEd448,
        SignatureRSApsspssSHA256,
        SignatureRSApsspssSHA384,
        SignatureRSApsspssSHA512,
        SignatureBrainpoolP256,
        SignatureBrainpoolP384,
        SignatureBrainpoolP512
    ),
    HashAndSignatureAlgorithm,
    pattern MLDSA44,
    pattern MLDSA65,
    pattern MLDSA87,
    supportedSignatureSchemes,
    signatureSchemesForTLS13,
    isMLDSA,
    showSignatureScheme,
) where

import Network.TLS.Imports

------------------------------------------------------------

newtype HashAlgorithm = HashAlgorithm {fromHashAlgorithm :: Word8}
    deriving (Eq)

{- FOURMOLU_DISABLE -}
pattern HashNone      :: HashAlgorithm
pattern HashNone       = HashAlgorithm 0
pattern HashMD5       :: HashAlgorithm
pattern HashMD5        = HashAlgorithm 1
pattern HashSHA1      :: HashAlgorithm
pattern HashSHA1       = HashAlgorithm 2
pattern HashSHA224    :: HashAlgorithm
pattern HashSHA224     = HashAlgorithm 3
pattern HashSHA256    :: HashAlgorithm
pattern HashSHA256     = HashAlgorithm 4
pattern HashSHA384    :: HashAlgorithm
pattern HashSHA384     = HashAlgorithm 5
pattern HashSHA512    :: HashAlgorithm
pattern HashSHA512     = HashAlgorithm 6
pattern HashIntrinsic :: HashAlgorithm
pattern HashIntrinsic  = HashAlgorithm 8
pattern HashMLDSA     :: HashAlgorithm -- not a hash; see MLDSA44 below
pattern HashMLDSA      = HashAlgorithm 9

instance Show HashAlgorithm where
    show HashNone          = "None"
    show HashMD5           = "MD5"
    show HashSHA1          = "SHA1"
    show HashSHA224        = "SHA224"
    show HashSHA256        = "SHA256"
    show HashSHA384        = "SHA384"
    show HashSHA512        = "SHA512"
    show HashIntrinsic     = "TLS13"
    show HashMLDSA         = "MLDSA"
    show (HashAlgorithm x) = "Hash " ++ show x
{- FOURMOLU_ENABLE -}

------------------------------------------------------------

newtype SignatureAlgorithm = SignatureAlgorithm {fromSignatureAlgorithm :: Word8}
    deriving (Eq)

{- FOURMOLU_DISABLE -}
pattern SignatureAnonymous        :: SignatureAlgorithm
pattern SignatureAnonymous         = SignatureAlgorithm 0
pattern SignatureRSA              :: SignatureAlgorithm
pattern SignatureRSA               = SignatureAlgorithm 1
pattern SignatureDSA              :: SignatureAlgorithm
pattern SignatureDSA               = SignatureAlgorithm 2
pattern SignatureECDSA            :: SignatureAlgorithm
pattern SignatureECDSA             = SignatureAlgorithm 3
-- TLS 1.3 from here
pattern SignatureRSApssRSAeSHA256 :: SignatureAlgorithm
pattern SignatureRSApssRSAeSHA256  = SignatureAlgorithm 4
pattern SignatureRSApssRSAeSHA384 :: SignatureAlgorithm
pattern SignatureRSApssRSAeSHA384  = SignatureAlgorithm 5
pattern SignatureRSApssRSAeSHA512 :: SignatureAlgorithm
pattern SignatureRSApssRSAeSHA512  = SignatureAlgorithm 6
pattern SignatureEd25519          :: SignatureAlgorithm
pattern SignatureEd25519           = SignatureAlgorithm 7
pattern SignatureEd448            :: SignatureAlgorithm
pattern SignatureEd448             = SignatureAlgorithm 8
pattern SignatureRSApsspssSHA256  :: SignatureAlgorithm
pattern SignatureRSApsspssSHA256   = SignatureAlgorithm 9
pattern SignatureRSApsspssSHA384  :: SignatureAlgorithm
pattern SignatureRSApsspssSHA384   = SignatureAlgorithm 10
pattern SignatureRSApsspssSHA512  :: SignatureAlgorithm
pattern SignatureRSApsspssSHA512   = SignatureAlgorithm 11
pattern SignatureBrainpoolP256    :: SignatureAlgorithm -- RFC8734
pattern SignatureBrainpoolP256     = SignatureAlgorithm 26
pattern SignatureBrainpoolP384    :: SignatureAlgorithm
pattern SignatureBrainpoolP384     = SignatureAlgorithm 27
pattern SignatureBrainpoolP512    :: SignatureAlgorithm
pattern SignatureBrainpoolP512     = SignatureAlgorithm 28

instance Show SignatureAlgorithm where
    show SignatureAnonymous        = "Anonymous"
    show SignatureRSA              = "RSA"
    show SignatureDSA              = "DSA"
    show SignatureECDSA            = "ECDSA"
    show SignatureRSApssRSAeSHA256 = "RSApssRSAeSHA256"
    show SignatureRSApssRSAeSHA384 = "RSApssRSAeSHA384"
    show SignatureRSApssRSAeSHA512 = "RSApssRSAeSHA512"
    show SignatureEd25519          = "Ed25519"
    show SignatureEd448            = "Ed448"
    show SignatureRSApsspssSHA256  = "RSApsspssSHA256"
    show SignatureRSApsspssSHA384  = "RSApsspssSHA384"
    show SignatureRSApsspssSHA512  = "RSApsspssSHA512"
    show SignatureBrainpoolP256    = "BrainpoolP256"
    show SignatureBrainpoolP384    = "BrainpoolP384"
    show SignatureBrainpoolP512    = "BrainpoolP512"
    show (SignatureAlgorithm x)    = "Signature " ++ show x
{- FOURMOLU_ENABLE -}

------------------------------------------------------------

type HashAndSignatureAlgorithm = (HashAlgorithm, SignatureAlgorithm)

-- ML-DSA, from draft-ietf-tls-mldsa: mldsa44(0x0904), mldsa65(0x0905) and
-- mldsa87(0x0906).
--
-- These are named as whole pairs rather than as a new 'SignatureAlgorithm',
-- because neither byte is what it is elsewhere: 0x09 is not a hash, and the
-- second byte repeats numbers RSASSA-PSS already uses.  Only the pair
-- identifies the scheme, so only the pair is given a name, and code that
-- decides anything about ML-DSA has to match on both bytes.

-- | Name a signature scheme.
--
-- 'show' on the pair cannot do this for ML-DSA.  A scheme is a 16-bit
-- number that hs-tls carries as the two bytes it is made of, and for ML-DSA
-- the size is in the second byte, whose values RSASSA-PSS also uses -- so
-- the components alone render mldsa65 as @(MLDSA,RSApssRSAeSHA384)@, which
-- names the wrong algorithm.  Use this wherever a scheme is put in front of
-- a person.
showSignatureScheme :: HashAndSignatureAlgorithm -> String
showSignatureScheme MLDSA44 = "mldsa44"
showSignatureScheme MLDSA65 = "mldsa65"
showSignatureScheme MLDSA87 = "mldsa87"
showSignatureScheme hs = show hs

-- | Is this one of the ML-DSA schemes?  They are TLS 1.3 only, so the
-- TLS 1.2 paths filter them out and refuse one that arrives anyway.
isMLDSA :: HashAndSignatureAlgorithm -> Bool
isMLDSA MLDSA44 = True
isMLDSA MLDSA65 = True
isMLDSA MLDSA87 = True
isMLDSA _ = False

{- FOURMOLU_DISABLE -}
pattern MLDSA44 :: HashAndSignatureAlgorithm
pattern MLDSA44  = (HashMLDSA, SignatureAlgorithm 4)
pattern MLDSA65 :: HashAndSignatureAlgorithm
pattern MLDSA65  = (HashMLDSA, SignatureAlgorithm 5)
pattern MLDSA87 :: HashAndSignatureAlgorithm
pattern MLDSA87  = (HashMLDSA, SignatureAlgorithm 6)
{- FOURMOLU_ENABLE -}

{- FOURMOLU_DISABLE -}
supportedSignatureSchemes :: [HashAndSignatureAlgorithm]
supportedSignatureSchemes =
    -- ML-DSA algorithms, TLS 1.3 only
    [ MLDSA87                           -- mldsa87(0x0906)
    , MLDSA65                           -- mldsa65(0x0905)
    , MLDSA44                           -- mldsa44(0x0904)
    -- EdDSA algorithms
    , (HashIntrinsic, SignatureEd448)   -- ed448  (0x0808)
    , (HashIntrinsic, SignatureEd25519) -- ed25519(0x0807)
    -- ECDSA algorithms
    , (HashSHA512,    SignatureECDSA)   -- ecdsa_secp512r1_sha512(0x0603)
    , (HashSHA384,    SignatureECDSA)   -- ecdsa_secp384r1_sha384(0x0503)
    , (HashSHA256,    SignatureECDSA)   -- ecdsa_secp256r1_sha256(0x0403)
    -- RSASSA-PSS RSAE algorithms
    , (HashIntrinsic, SignatureRSApssRSAeSHA512) -- rsa_pss_rsae_sha512(0x0806)
    , (HashIntrinsic, SignatureRSApssRSAeSHA384) -- rsa_pss_rsae_sha384(0x0805)
    , (HashIntrinsic, SignatureRSApssRSAeSHA256) -- rsa_pss_rsae_sha256(0x0804)
    -- RSASSA-PSS PSS algorithms with
    , (HashIntrinsic, SignatureRSApsspssSHA512)  -- rsa_pss_pss_sha512(0x080b)
    , (HashIntrinsic, SignatureRSApsspssSHA384)  -- rsa_pss_pss_sha384(0x080a)
    , (HashIntrinsic, SignatureRSApsspssSHA256)  -- rsa_pss_pss_sha256(0x0809)
    -- RSASSA-PKCS1-v1_5 algorithms
    , (HashSHA512,    SignatureRSA)    -- rsa_pkcs1_sha512(0x0601)
    , (HashSHA384,    SignatureRSA)    -- rsa_pkcs1_sha384(0x0501)
    , (HashSHA256,    SignatureRSA)    -- rsa_pkcs1_sha256(0x0401)
    -- Legacy algorithms
    , (HashSHA1,      SignatureRSA)    -- rsa_pkcs1_sha1  (0x0201)
    , (HashSHA1,      SignatureECDSA)  -- ecdsa_sha1      (0x0203)
    ]

signatureSchemesForTLS13 :: [(HashAlgorithm, SignatureAlgorithm)]
signatureSchemesForTLS13 =
    -- ML-DSA algorithms
    [ MLDSA87                           -- mldsa87(0x0906)
    , MLDSA65                           -- mldsa65(0x0905)
    , MLDSA44                           -- mldsa44(0x0904)
    -- EdDSA algorithms
    , (HashIntrinsic, SignatureEd448)   -- ed448  (0x0808)
    , (HashIntrinsic, SignatureEd25519) -- ed25519(0x0807)
    -- ECDSA algorithms
    , (HashSHA512,    SignatureECDSA)   -- ecdsa_secp512r1_sha512(0x0603)
    , (HashSHA384,    SignatureECDSA)   -- ecdsa_secp384r1_sha384(0x0503)
    , (HashSHA256,    SignatureECDSA)   -- ecdsa_secp256r1_sha256(0x0403)
    -- RSASSA-PSS RSAE algorithms
    , (HashIntrinsic, SignatureRSApssRSAeSHA512) -- rsa_pss_rsae_sha512(0x0806)
    , (HashIntrinsic, SignatureRSApssRSAeSHA384) -- rsa_pss_rsae_sha384(0x0805)
    , (HashIntrinsic, SignatureRSApssRSAeSHA256) -- rsa_pss_rsae_sha256(0x0804)
    -- RSASSA-PSS PSS algorithms with
    , (HashIntrinsic, SignatureRSApsspssSHA512)  -- rsa_pss_pss_sha512(0x080b)
    , (HashIntrinsic, SignatureRSApsspssSHA384)  -- rsa_pss_pss_sha384(0x080a)
    , (HashIntrinsic, SignatureRSApsspssSHA256)  -- rsa_pss_pss_sha256(0x0809)
    ]
{- FOURMOLU_ENABLE -}