Runtime detection of SHA-1 support in unbound

Hello,

I am maintainer of unbound in RHEL. We are preparing RHEL9 (and CentOS Stream 9). Because preparations for various security certifications SHA-1 signature validation is disabled now in upcoming RHEL9. It is done via something we call crypto-policies, which sets openssl configuration among others.

In DEFAULT policy (set by update-crypto-policies --set DEFAULT) it would fail to resolve any name signed by DNSSEC key using SHA-1 or SHA-1 digest. Most DNSSEC validators I have seen assume they know all algorithms right from the start. Unfortunately openssl does not seem to provide good API to test if SHA-1 based signature would be accepted.

It can be tried in podman/docker the most easy way:

docker pull quay.io/centos/centos:stream9
run -ti centos:stream9
dnf install unbound
unbound-host -t dnskey -rD int.

Here it what it would emit:

# unbound-host -t dnskey -rD int
int has DNSKEY record 256 3 7 AwEAAakqkuFzCwB8Zo3lCQGR+7FiPDiaDCpyFdFq2gFeNUF3yFqWwAoCV+A/U5wza2rS0bQaADpnFUO4f8oIdOJbMGLWObs6MUN1NkcQUeSXEsNsjxGZDBwNhqurBeSmrGkDyGvVrxGLmeb+AmuhTsNXbCzA5nvZinZOlAwK6Ft4OJvJ
int has DNSKEY record 256 3 7 AwEAAbvlwoq07LItqAczwktNYABK/KBD9W1fnZYgezM6OXNRju0zHWph1NJQsBlNsVZJWPfvQJQLjxPjMldYQS4tLPmHM8pLPEaa5K8sSzTRJ0Jlx4LasYaIANp2v9L8v18mTBUDC1VTA2U5rh79zPO3yGaHhxdCiNRsq+MPY1QtOiK9
int has DNSKEY record 257 3 7 AwEAAb8omPP2ctJgDcENW8k7C5HhrCv79Q3sASrugKzHwUxWpfyifwHFRWrRcXVcwG6AnJBQ1U6ZplnhjqdnXSphgH0/Y+CJfqsw2FpHA+sPbOzUO8DCKT3Ez2hEEoUXMr19zqR6a6I/lSt0pO/mg8NSQHVwbWuH35haZ4OEOXGW2T83TGvq19XhLZWu/z4GSEeIKN4XagyVol7HLfjOJpRg1EdPMYWDsWZTWmKd35fZFkLgn6YmzzBgDlLI6x2UfLKgnysIBeoh2h952WyL/EOiO3Lbl0bnVvrQl+VelkfTS1tpgYocWT2FvnU+50PWZnuLjLvnjqDBrbbknTBG7fReYa8=
int has DNSKEY record 256 3 7 AwEAAYwx2ixZwqVrqiIHYEIFcqId+jVQGo/9x4uNWfDVuGyTMq8kmdatfv3y1FZ6N6IH5R3BlzEl96GLChsXmKhdFGLxutfFR8vZyT7lJciux4ik/ckb8nTMuXLizx/V2gRmsJ+Qqnn5WyQD1ZwulISMhnvLKVMX5mwPusZrq2l49UG1
validation failure <int. DNSKEY IN>: keyset not secured by DNSKEY that matches DS from 10.0.2.3 for key int. while building chain of trust

#unbound-host -t dnskey -rddddD int
...
[1649264462] libunbound[6614:0] info: validator: inform_super, sub is int. DNSKEY IN
[1649264462] libunbound[6614:0] info: super is int. DNSKEY IN
[1649264462] libunbound[6614:0] debug: attempt DS match algo 7 keytag 27433
[1649264462] libunbound[6614:0] debug: DS match digest ok, trying signature
[1649264462] libunbound[6614:0] debug: verify: EVP_DigestVerifyInit failed
[1649264462] libunbound[6614:0] debug: rrset failed to verify: all signatures are bogus
[1649264462] libunbound[6614:0] debug: Failed to match any usable DS to a DNSKEY.
[1649264462] libunbound[6614:0] info: Did not match a DS to a DNSKEY, thus bogus.
[1649264462] libunbound[6614:0] debug: validator[module 1] operate: extstate:module_wait_subquery event:module_event_pass
...


It fails in function EVP_DigestVerifyInit on algorithm 7. Would it be possible to modify it, so it would revert on few specific openssl error codes back to insecure validation? It is able to switch to mode enabling also sha-1 digests: update-crypto-policies --set DEFAULT:SHA1

I would like to find a good way to support both mode when validation fails and when it can pass. In single compiled binary. Is there a better way, than building in an example key and checking once after startup each algorithm in question? I think it is now decided only in dns_resolver_algorithm_supported() function and similar. Would be adjusting unbound code to react to crypto libraries errors too hard? Could such functions return just sec_status_indeterminate in similar cases?

I have added a log_crypto_error after it, and this was the result:

error: verifyInit: crypto error:03000098:digital envelope routines::invalid digest

Would it make sense to return something like sec_status_insecure in such failing cases? Could similar cases be hit for example on ED448 or other rare key algorithms?

Filled also issue on github: https://github.com/NLnetLabs/unbound/issues/656

Regards,
Petr

This is broken and violates RFC 8624.

It means RHEL9 cannot be used as a platform for DNS resolvers.

The unbound package should not use crypto-policies if those cannot facilitate the requirements of RFC 8624.

This would be particularly sad since one of the authors of this RFC (me) wrote it while working at Red Hat.

If Red Hat proceeds with this, users have two choices. Change the system wide policy to LEGACY and degrading security for everything running on the box (ssh, tls) or stick with rhel8 past its secure and supported date.

Paul

It's local policy, which usually takes precedence over whatever algorithms are prescribed by default non-local policy. If RHEL wants it that way let them deal with consequences of their choices.

After all, maybe they got the policy right! draft-fanf-dnsop-sha-ll-not-00.txt seems persuasive to me.

In any case, I think it would be a good idea to treat that as any other unsupported algorithm and thus DNSSEC-insecure.

It is, but the change have been already made and cannot revert. That is not correct. Policy DEFAULT:SHA1 enables also SHA-1 signatures verification and it would work suitable. I admit the change got implemented quite late, so we could make our unbound with completely disabled SHA-1 at build time. I know you are the author of RFC we now violate. 1. 2.

I did not expect to see you here. Similar problem is with named, which
has a workaround with included config. delv tool has no workaround
however, so similar thing should be implemented also in bind sources. I
think no open source implementation would cope with this policy without
changes. If it doesn't avoid using openssl or gnutls like dnsmasq does.

It means RHEL9 cannot be used as a platform for DNS resolvers.

It can, you just need to set crypto-policies to allow SHA1 signatures.
It is just a matter of configuration like many others.

but unbound has no seperate policies in the system-wide crypto
backends. Bind does, but will it be modified to allow SHA1? As I
understand it, it is the openssl backend that will refuse SHA1?

The unbound package should not use crypto-policies if those cannot
facilitate the requirements of RFC 8624.

This is applied at the openssl library level.

So that is a problem then. You have to enable it in openssl to make
it available to bind/unbound and now it is exposed to other parts too,
eg tls and ssh.

If Red Hat proceeds with this, users have two choices. Change the
system wide policy to LEGACY and degrading security for everything
running on the box (ssh, tls) or stick with rhel8 past its secure and
supported date.

We think this is a legitimate choice.
But it does not need to be this drastic. A custom openssl configuration
can be provided just to the application that needs to do DNSSEC
verification via OPENSSL_CONF variable.

However we hope DNSSEC can move away from SHA1 quickly, there is no
reason to stick to weak digest for so long.

Rubber meets the road somewhere and RFC 8624 has done these
determinations. If you think Red Hat can go against the worldwide
view/flow, then go ahead. You get to keep the pieces. The authors
of RFC 8624 are closely monitoring worldwide statistics and will
update the RFC when appropriate.

Note also that just breaking the crypto without proper support in the
DNS software causes ServFail's and not just a change from DNS data
being handles as "insecure" instead of "dnssec protected". This is
the bigger problem. Please do ensure unbound, bind et all do not
fail due to crypto library failing, but handle it properly as an
"unsupported algorithm" or otherwise there will be user outages.

Paul

It means RHEL9 cannot be used as a platform for DNS resolvers.

It can, you just need to set crypto-policies to allow SHA1 signatures.
It is just a matter of configuration like many others.

but unbound has no seperate policies in the system-wide crypto
backends. Bind does, but will it be modified to allow SHA1? As I
understand it, it is the openssl backend that will refuse SHA1?

No, because it is not possible in a self-contained way. It would be the
other way around.
It would disable SHA-1 in DEFAULT and FUTURE policy to avoid SERVFAIL on
those names.
Because openssl does not provide a way to verify SHA-1 based signature,
any configuration of bind cannot revert that. It might be possible with
custom openssl configuration,
but that might introduce more issues than it solves. Simo shared such
example.

The unbound package should not use crypto-policies if those cannot
facilitate the requirements of RFC 8624.

This is applied at the openssl library level.

So that is a problem then. You have to enable it in openssl to make
it available to bind/unbound and now it is exposed to other parts too,
eg tls and ssh.

Yes, that is correct.

If Red Hat proceeds with this, users have two choices. Change the
system wide policy to LEGACY and degrading security for everything
running on the box (ssh, tls) or stick with rhel8 past its secure and
supported date.

We think this is a legitimate choice.
But it does not need to be this drastic. A custom openssl configuration
can be provided just to the application that needs to do DNSSEC
verification via OPENSSL_CONF variable.

However we hope DNSSEC can move away from SHA1 quickly, there is no
reason to stick to weak digest for so long.

Rubber meets the road somewhere and RFC 8624 has done these
determinations. If you think Red Hat can go against the worldwide
view/flow, then go ahead. You get to keep the pieces. The authors
of RFC 8624 are closely monitoring worldwide statistics and will
update the RFC when appropriate.

Note also that just breaking the crypto without proper support in the
DNS software causes ServFail's and not just a change from DNS data
being handles as "insecure" instead of "dnssec protected". This is
the bigger problem. Please do ensure unbound, bind et all do not
fail due to crypto library failing, but handle it properly as an
"unsupported algorithm" or otherwise there will be user outages.

Paul

I am aware that is the result and that is the reason I started that post
here. I would like more solving this in Fedora first and then landing it
later to RHEL, but unfortunately it did not happen this way. I would
like to find a good way for any similar configuration of crypto backend
to make as smooth user-experience as possible. It may influence even
different algorithms, not only SHA-1 based.

Petr

It seems I have successful prototype of unbound reacting to policy changes.

It seems it passes ietf.org or int as INSECURE if DEFAULT policy is
active. But still passes it as secure if DEFAULT:SHA1 is active.

Tested just with unbound-host -rdD ietf.org

Create PR #660 [1], any testing, comments or review would be very welcome.

Cheers,
Petr

1. Sha1 runtime insecure by pemensik · Pull Request #660 · NLnetLabs/unbound · GitHub

Thanks, I will have a look.

Note you might also run into unbound startup issues as it tries to fetch the Icann pem bundle from icann.org which is also on rsasha1 - so ensure to check unbound’s PreStart items too.

https://stats.dnssec-tools.org/explore/?icann.org

Sent using a virtual keyboard on a phone