dnsbase-1.0.0.0: src/Net/DNSBase/EDNS/Option/Secalgs.hs
{-|
Module : Net.DNSBase.EDNS.Option.Secalgs
Description : EDNS signalling of DNSSEC algorithms understood by the client
Copyright : (c) Viktor Dukhovni, 2020
License : BSD-3-Clause
Maintainer : ietf-dane@dukhovni.org
Stability : experimental
RFC 6975 specifies a way for validating end-system resolvers to signal
to a server which digital signature and hash algorithms they support.
This signalling does not alter server behaviour, rather it just provides
a means to server operators to collect data on client algorithm support
to assist in planning future algorithm selection.
The format of the associated EDNS options is defined in
[RFC6975, Section 3](https://tools.ietf.org/html/rfc6975#section-3)
as follows:
> 0 8 16
> +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
> | OPTION-CODE |
> +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
> | LIST-LENGTH |
> +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
> | ALG-CODE | ... /
> +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
i.e. a 16-bit count, followed by a sequence of 8-bit algorithm numbers.
The use of SHA-1 in NSEC3 is essentially light-weight obfuscation to
discourage casual zone walking. Implementation and adoption of successor
algorithms seems unlikely, and would in also be most counter-productive.
Therefore, while the N3U option is defined here, it is best left unused.
As of February 2020, the IANA registry of
[NSEC3 hash algorithms](https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml#dnssec-nsec3-parameters-3)
lists just SHA-1:
+---------+---------------+-----------+
| Value | Description | Reference |
+=========+===============+===========+
| 0 | Reserved | [RFC5155] |
+---------+---------------+-----------+
| 1 | SHA-1 | [RFC5155] |
+---------+---------------+-----------+
| 2-255 | Unassigned | |
+---------+---------------+-----------+
This is not expected to change.
-}
module Net.DNSBase.EDNS.Option.Secalgs
( O_dau(..)
, O_dhu(..)
, O_n3u(..)
) where
import Net.DNSBase.Decode.Internal.State
import Net.DNSBase.EDNS.Internal.OptNum
import Net.DNSBase.EDNS.Internal.Option
import Net.DNSBase.Encode.Internal.State
import Net.DNSBase.Encode.Internal.Metric
import Net.DNSBase.Internal.Present
import Net.DNSBase.Internal.Util
import Net.DNSBase.Secalgs
-- | DNSSEC Algorithm Understood (RFC6975).
newtype O_dau = O_DAU [DNSKEYAlg] deriving (Eq, Show)
-- | DS Hash Understood (RFC6975).
newtype O_dhu = O_DHU [DSHashAlg] deriving (Eq, Show)
-- | NSEC3 Hash Understood (RFC6975).
newtype O_n3u = O_N3U [NSEC3HashAlg] deriving (Eq, Show)
instance Presentable O_dau where
present (O_DAU val) = case val of
[] -> present '-'
(v:vs) -> present v . flip (foldr presentSp) vs
instance Presentable O_dhu where
present (O_DHU val) = case val of
[] -> present '-'
(v:vs) -> present v . flip (foldr presentSp) vs
instance Presentable O_n3u where
present (O_N3U val) = case val of
[] -> present '-'
(v:vs) -> present v . flip (foldr presentSp) vs
instance KnownEdnsOption O_dau where
optNum _ = DAU
{-# INLINE optNum #-}
optEncode = putSizedBuilder . coerce foldDAU
where
foldDAU :: [DNSKEYAlg] -> SizedBuilder
foldDAU = foldMap mbDAU
mbDAU :: DNSKEYAlg -> SizedBuilder
mbDAU = coerce mbWord8
optDecode _ _ len =
EdnsOption . O_DAU <$> getFixedWidthSequence 1 (coerce <$> get8) len
instance KnownEdnsOption O_dhu where
optNum _ = DHU
{-# INLINE optNum #-}
optEncode = putSizedBuilder . coerce foldDHU
where
foldDHU :: [DSHashAlg] -> SizedBuilder
foldDHU = foldMap mbDHU
mbDHU :: DSHashAlg -> SizedBuilder
mbDHU = coerce mbWord8
optDecode _ _ len =
EdnsOption . O_DHU <$> getFixedWidthSequence 1 (coerce <$> get8) len
instance KnownEdnsOption O_n3u where
optNum _ = N3U
{-# INLINE optNum #-}
optEncode = putSizedBuilder . coerce foldN3U
where
foldN3U :: [NSEC3HashAlg] -> SizedBuilder
foldN3U = foldMap mbN3U
mbN3U :: NSEC3HashAlg -> SizedBuilder
mbN3U = coerce mbWord8
optDecode _ _ len =
EdnsOption . O_N3U <$> getFixedWidthSequence 1 (coerce <$> get8) len