[getdns-users] public key pinning and tls_authentication models

Willem Toorop willem at nlnetlabs.nl
Tue Dec 22 09:25:21 UTC 2015


Hey!

Fantastic work. Thank you!
Sara, could you review too?

I believe we introduced getdns_context_get_tls_authentication() as a
quick way to allow for opportunistic TLS. So renaming the define
GETDNS_AUTHENTICATION_NONE into OPPORTUNISTIC and HOSTNAME in STRICT
would be in line with its original intent I think.  Indicating what
credentials (hostname or pubkey hashes) to use for authentication makes
complete sense to me too.

Question: If you specify a pinset in an upstream with STRICT
authentication, would your cert still need to be authenticated against
the CA store?

Cheers,

-- Willem


Op 22-12-15 om 07:03 schreef Daniel Kahn Gillmor:
> hi all--
> 
> I just submitted:
> 
>   https://github.com/getdnsapi/getdns/pull/130
> 
> This allows the user to require that the certificate offered by the
> TLS-enabled DNS server use an X.509 certificate with a public key that
> matches one of a list of pins.
> 
> It's a large-ish changeset overall, but I've tried to order the patches
> in a series so that they're easy to read sequentially with clear steps
> from one to the next.
> 
> As i wrote in the github pull request:
> 
> 
> -----------
> 
> Configuration is done per-upstream, with an additional member of the
> upstream object, tls_pubkey_pinset (by analogy with tls_auth_name).
> 
> this is a list of dicts, each of which describes a public key pin, which
> looks like this:
> 
>   {
>     "address_data": <bindata for 185.49.141.38>,
>     "address_type": <bindata of "IPv4">,
>     "tls_port": 853,
>     "tls_pubkey_pinset":
>     [
>       {
>         "digest": <bindata of "sha256">,
>         "value": <bindata of 0x17d099f483436ddfb6791428cd8aaa6d...>
>       },
>       {
>         "digest": <bindata of "sha256">,
>         "value": <bindata of 0x7e8c59467221f606695a797ecc488a6b...>
>       }
>     ]
>   }
> 
> The series includes a new argument for getdns_query -K to specify
> pins. All pins are applied to all upstreams. For example:
> 
>    getdns_query -K 'pin-sha256="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S="' -l L -m '@185.49.141.38~getdnsapi.net' google.com
> 
> -------------
> 
> There are still a couple missing pieces, though.  In particular, the
> interaction between getdns_context_get_tls_authentication() and the
> dicts that comprise the list of upstreams seems complicated and
> confusing.
> 
> We could make it so that your authentication choices are limited to
> either NONE or HOSTNAME or PUBKEY_PINSET, but what do we do if the user
> specifies a tls_auth_name combined with a PUBKEY_PINSET ?  it seems like
> we're giving users extra ways to create internally-incompatible
> configurations, and the API has a hard enough time already with nuanced
> error reporting.
> 
> At the same time, i realize that it might be useful for some users to be
> able to suggest a hostname or a public key pinset opportunistically,
> just to see what would happen without getting in the way of
> functionality.
> 
> One way to do this is to drop getdns_context_get_tls_authentication()
> entirely.  I'm calling this the "upstream-dict" model of tls
> authentication:
> 
>  * an upstream configured with tls_auth_name will do hostname
>    verification checking;
> 
>  * an upstream configured with tls_pubkey_pinset will do public key
>    pinset matching;
> 
>  * and an upstream configured without either of these will not be able
>    to do strict TLS.
> 
> A user who wants to do opportunistic "verification" can specify a
> non-TLS transport, which will enable all of these strict modes to become
> advisory-only.
> 
> I think this is the simplest model we can offer that is internally
> consistent, and i think it's less confusing to the user than requiring
> them to set an explicit tls_authentication mode on the context object
> that happens to match the values in each upstream dict.
> 
> There is some question about whether there is a legitimate use case for
> wanting to do "only TLS", but in an opportunistic mode -- that is,
> without fallback to a cleartext transport.  I'll call this "blinded-tls".
> The proposed tls-authentication-in-the-upstream-dict model doesn't
> support blinded-tls explicitly.
> 
> if we decide we do want to support blinded-tls, we could add a function
> getdns_context_allow_opportunistic_tls() that makes this explicitly
> possible.  This is semantically equivalent to having two possible values
> for getdns_tls_authentication_t : OPPORTUNISTIC and STRICT, which we
> could map to the current values of NONE and HOSTNAME and hope we get
> away with a dirty tweak of the library's API :)
> 
> By default, a context would report STRICT if it has only TLS transports,
> and OPPORTUNISTIC if it has non-TLS transports.  If the context has only
> TLS transports, and the user sets OPPORTUNISTIC, that would be
> "blinded-tls".  I'm not sure what we should do if the user sets STRICT
> but has non-TLS transports available, though.  Perhaps that would be an
> error in the configuration?
> 
> Again, it seems better to me to field an API that has fewer ways that a
> user can get themselves into an unusable state, which is why i'm leaning
> toward the pure "upstream-dict" model.
> 
> What do folks think about this?  What are the advantages of retaining
> the current getdns_context_{set,get}_tls_authentication() approach
> (other than API stability)?
> 
>      --dkg
> 
> PS fwiw, no package in the debian archive is currently using
>    g_c_{s,g}et_tls_authentication -- this is the kind of API change that
>    we could probably drop without a lot of pain if we wanted to:
> 
>  https://codesearch.debian.net/results/getdns_context_%5Bsg%5Det_tls_authentication/page_0
> _______________________________________________
> Users mailing list
> Users at getdnsapi.net
> http://getdnsapi.net/mailman/listinfo/users
> 




More information about the Users mailing list