[Dnsmasq-discuss] [PATCH] Treat records signed using unknown algorithms as unsigned instead of bogus
Michał Kępień
michal.kepien at nask.pl
Fri Dec 18 13:22:49 GMT 2015
> > First and foremost, the primary issue of returning SERVFAILs for
> > zones with DNSKEY RRsets signed using _only_ unknown algorithms
> > (even though we are able to hash the DNSKEY RRset and authenticate
> > the DS at the parent) is not resolved. Quick example: if you try
> > to resolve anything within a zone signed using only ECC-GOST keys,
> > with an SHA-256 DS at the parent, SERVFAIL is still returned as
> > dnssec_validate_by_ds() still requires the validate_rrset() call
> > for DNSKEY RRset to succeed for it to return anything else than
> > STAT_BOGUS. In my patch which started this thread I tried to
> > demonstrate that if all DNSKEY RRset validations fail only due to
> > the lack of support for the _signing_ algorithms used by its
> > RRSIGs, the zone should be marked as insecure, not bogus.
>
>
> Did you test this on a real domain and see a failure? The way it's
> intended to work is that the call to zone_status() at line 2042 will
> work down from the root to the DS, where it will find that the SHA-256
> DS covers a ECC-GOST key and return STAT_INSECURE at line 1869. That
> will be returned from dnssec_validate_reply at line 2049, before the
> call to validate_rrset is even made. dnssec_validate_by_ds() should
> never be called.
>
> An example of a domain that fails here would be really useful. I did
> testing by removing algorithms but as there are no rare algorithms
> it's difficult not to cause early failure of the process before the
> test case is reached.
Ah, it seems the bugs were intertwined. You see, before 14a4ae8 we
could not tell ECC-GOST is not supported until an actual attempt was
made to call verify() with algorithm 12, so dnssec_validate_by_ds() was
called for the DNSKEY RRset after zone_status() "verified" that ECC-GOST
is supported. With the latest master this is no longer the case and the
zone is processed exactly the way you described above. Though the
algorithm is still flawed, see below.
> > Then there's commit 2dbba34, whose log message says: "A zone which
> > has at least one key with an algorithm we don't support should be
> > considered as insecure."
>
>
> > That's not right. Only a zone whose _all_ keys use algorithms we
> > don't support should be considered as insecure.
>
> No, a zone may have a key we support but records are signed only using
> the key we don't support.
>
> If a zone has a key of a type we don't understand, than we must accept
> an insecure answer, (one signed only with the unsupported algorithm)
> so an insecure result is legitimate for that zone. In the case that
> the records are actually signed by an algorithm we do support, a
> secure result is possible and an insecure response is sub-optimal, but
> it's not wrong.
Could you please provide a specific example? Because I believe every
such zone would violate RFC 4035, section 2.2, which says:
There MUST be an RRSIG for each RRset using at least one DNSKEY of
each algorithm in the zone apex DNSKEY RRset. The apex DNSKEY RRset
itself MUST be signed by each algorithm appearing in the DS RRset
located at the delegating parent (if any).
Assume we authenticated the DS RRset at the parent and that it only
contains one hash of a key using a supported signing algorithm. That
means that the relevant key using that algorithm has to be present in
the zone apex DNSKEY RRset. Now, if we create another key with an
unsupported algorithm and insert it into the zone apex DNSKEY RRset, we
are free to sign that zone's records with it, but we still have to
ensure that all records also have an RRSIG using the algorithm of the
other key.
Try the following: compile dnsmasq with -DNO_NETTLE_ECC and then ask it
for the DNSKEY RRset at dnssec-test.org. You will notice that the
answer incorrectly lacks the AD bit. This zone has a single DS at the
parent, pointing to an RSA/SHA-1 key. Its DNSKEY RRset contains one RSA
key (corresponding to the DS) and one ECDSA key. All records in this
zone are signed with both keys to fulfill the requirement specified by
RFC 4035, section 2.2. As dnsmasq supports RSA/SHA-1, why would it
treat the whole zone as insecure for the sole reason that one of the
authenticated DNSKEY RRs is using an algorithm it doesn't understand?
I also noticed that the DS processing loop in zone_status() is flawed as
well. It returns STAT_INSECURE whenever it encounters even a single
hash/signing algorithm it doesn't support. Why? If there are two or
more DS RRs for the same keytag-algorithm pair (so only the hashing
algorithms are different), why would the zone be considered insecure,
given that we understand at least one hashing algorithm of those used by
the DS RRs?
Moreover, I believe we can break out of that loop immediately after
setting secure_ds to 1 as finding one DS RR whose hashing and signing
algorithms are both supported is enough to be sure that we will be able
to attempt validation of at least one of the zone's DNSKEY RRs (as long
as it actually exists in the zone, of course, but we're checking that
anyway in dnssec_validate_by_ds()).
A useful test subject for these issues is the caint.su zone, which uses
two keys, each using a different algorithm (RSA and ECC-GOST) and also
provides three separate hashes of each of those keys in its parent zone.
Using this zone as an example for the reasoning above, it shouldn't be
considered insecure just because we don't understand GOST hashes and/or
signing.
> > While debugging the latest code, I also noticed that the
> > algorithm support checks seem inconsistent. AFAICT, checking
> > whether a given signing algorithm is supported is done using
> > algo_digest_name(). What that function actually checks is whether
> > the hashing algorithm used by the given signing scheme is
> > supported, not whether the actual signing scheme is supported.
> > Let's compare the behavior for ECC-GOST and ECDSA. For ECC-GOST,
> > algo_digest_name() will always return "gosthash94", which the
> > caller interprets as "this signing scheme is supported". However,
> > verify() will always return 0 for algorithm 12, because ECC-GOST
> > signing isn't actually implemented. Assume now that dnsmasq was
> > compiled with -DNO_NETTLE_ECC. If you ask algo_digest_name() about
> > ECDSA support, it will immediately tell the caller that "this
> > signing scheme is _not_ supported", even though libnettle wouldn't
> > have problems with calculating a SHA-256/SHA-384 hash. This is not
> > that big of an issue, but it hindered my debugging efforts.
>
> That's a good point. The problem is that Nettle supports introspection
> for hash functions, but not public-key signatures. algo_digest_name()
> uses the introspection, but it doesn't tell you that algorithms 13 and
> 14 are not available because ECC is not available. Hence I added the
> #ifdef NO_NETTLE_ECC, which should encompass 12. Even that's not
> right, because 12 needs ECC-GOST, which isn't implemented. The
> canonical place for this information is actually verify(): it knows
> which algorithms are OK. I've fixed the code to do that. A digest is
> supported if it's in the switch in algo_digest_name() AND supported by
> the current Nettle. A signature algo is supported if it's in the
> switch in verify_func(). That has to be kept up-to-date with Nettle's
> capabilities.
Thanks, as I already stated above, this fixed quite some of the problems
I observed.
--
Best regards,
Michał Kępień
More information about the Dnsmasq-discuss
mailing list