Confirmed users
299
edits
No edit summary |
(add historical content notice) |
||
(24 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
<p style="border: 2px solid red;"><b>This is historical content and has not been revised since it was written about Firefox Desktop in 2011.</b></p> | |||
Tracking bug: [https://bugzilla.mozilla.org/show_bug.cgi?id=672239 672239] | |||
== Background == | == Background == | ||
Line 4: | Line 8: | ||
=== Embedding Certificate Information in DNS === | === Embedding Certificate Information in DNS === | ||
[http://tools.ietf.org/html/draft-ietf-dane-protocol- | [http://tools.ietf.org/html/draft-ietf-dane-protocol-10 DANE], [http://tools.ietf.org/html/draft-hallambaker-donotissue-04 Certification Authority Authorization (CAA)], and [http://tools.ietf.org/html/rfc2538 CERT] records are all methods of embedding certificate information in DNS records. With DANE, either the public key or entire certificate (or the hash thereof) may be put in a TLSA record that specifies, for example, the certificate or public key to be used for connecting to example.com tcp port 443 (in the record _443._tcp.example.com). CAA uses the hash of the certificate and can specify that any certificate issued for (for example) example.com must be rooted by the hashed certificate. CAA uses TYPE257 records. CAA has other policy options, as well. CERT simply embeds a certificate in a DNS record. For the time being, while CAA is powerful, it has been determined to be too complicated for this use case. Furthermore, CERT can only specify whole certificates, not just public keys, and is thus too restrictive. Thus, DANE alone will initially be supported. | ||
=== Domain Validation === | === Domain Validation === | ||
To use DNSSEC to perform domain validation, a key or certificate must be put in a DANE record corresponding to the server to validate. Then, during the TLS handshake, the chain of DNSSEC records from that record to an agreed-upon root must be sent along with the server certificate. The client can walk this chain of records to a trusted root to validate the material. If this succeeds, the client then uses either the embedded key material or the key material in the server certificate (that | To use DNSSEC to perform domain validation, a key or certificate must be put in a DANE record corresponding to the server to validate. Then, during the TLS handshake, the chain of DNSSEC records from that record to an agreed-upon root must be sent along with the server certificate. The client can walk this chain of records to a trusted root to validate the material. If this succeeds, the client then uses either the embedded key material or the key material in the server certificate (that has just been validated by the DNSSEC chain) as the public key for a key exchange. Note that if the DANE record consists of an entire certificate and that certificate will always be sent in the TLS handshake, the DANE record itself may be omitted. In this case, the RRSIG record for the DANE record will have to be used to validate the certificate sent in TLS. | ||
Obviously this mechanism could work out of band. That is, instead of embedding the DNSSEC chain in the TLS handshake, the client could perform simultaneous DNSSEC lookups to verify the material in the server certificate. However, this would be significantly slower as it would involve multiple round-trip communications with another server. | Obviously this mechanism could work out of band. That is, instead of embedding the DNSSEC chain in the TLS handshake, the client could perform simultaneous DNSSEC lookups to verify the material in the server certificate. However, this would be significantly slower as it would involve multiple round-trip communications with another server. | ||
Line 25: | Line 29: | ||
The format of a serialized DNSSEC chain sent in this protocol consists first of a series of the following: | The format of a serialized DNSSEC chain sent in this protocol consists first of a series of the following: | ||
* | * The DNSKEY (and corresponding RRSIG) records for a zone, in wire format. There must be a key signing key present. | ||
* | * A DS (and corresponding RRSIG) record for the key signing key in the previous record, in wire format. This DS must be from a zone outer to that of the keys. The following set of keys must be from the same zone as this DS record. | ||
The root zone may be omitted, because it is assumed that the client already has the DNSSEC keys for the root. The TLSA (and corresponding RRSIG) record is prefixed to the chain and must be from the same zone as the first key set. | |||
So, for example, the DNSSEC chain sent for clients connecting to foo.bar.com could be: | So, for example, the DNSSEC chain sent for clients connecting to foo.bar.com could be: | ||
* The DS (+RRSIG) | * The TLSA (+RRSIG) for foo.bar.com | ||
* The DNSKEYS (+RRSIGs) for bar.com | |||
* The DS (+RRSIG) for bar.com (from .com) | |||
* The DNSKEYS (+RRSIGs) for .com | * The DNSKEYS (+RRSIGs) for .com | ||
* The DS (+RRSIG | * The DS (+RRSIG) for .com (from .) | ||
It is possible to optimize away some fields of these records, but at the moment this is not being done. Another optimization would be for the client to indicate a root of trust deeper down the tree so that the server can omit some zones. For example, a client may already have (and have validated) all of the keys for .com. In the above example, if the client has already validated keys for .com, the server need only send the | It is possible to optimize away some fields of these records, but at the moment this is not being done. Another optimization would be for the client to indicate a root of trust deeper down the tree so that the server can omit some zones. For example, a client may already have (and have validated) all of the keys for .com. In the above example, if the client has already validated keys for .com, the server need only send the TLSA record, the keys for bar.com, and the DS record entering bar.com (as well as the signatures, of course). | ||
Note that once a chain has been serialized, it will only be valid for as long as every signature in it is valid. That is, it will become invalid when any signature it contains expires. | Note that once a chain has been serialized, it will only be valid for as long as every signature in it is valid. That is, it will become invalid when any signature it contains expires. | ||
For reference, another proposal for the serialization of a DNSSEC chain is [http://tools.ietf.org/html/draft-agl-dane-serializechain-01 here]. Note that this proposal does not follow exactly the wire format of DNS records. Consequently, preexisting code cannot be used to serialize, parse, or validate the chain. Additionally, more flexibility means more opportunities for insecure verifier behavior. This proposal is not currently being used in this project. | For reference, another proposal for the serialization of a DNSSEC chain is [http://tools.ietf.org/html/draft-agl-dane-serializechain-01 here]. Note that this proposal does not follow exactly the wire format of DNS records. Additionally, it reverses the order of records. Consequently, preexisting code cannot be used to serialize, parse, or validate the chain. Additionally, more flexibility means more opportunities for insecure verifier behavior. This proposal is not currently being used in this project. | ||
== Google Chrome == | == Google Chrome == | ||
Line 63: | Line 67: | ||
If there is a mechanism for the client to say what keys have already been validated (thus decreasing the length of the chain a server must send), there may be privacy implications. For instance, if a only small number of sites have their DS records signed by a specific key from .com and the client indicates they have already validated that specific key, another server knows the client has visited one of those sites. There may be a way for a client to instead indicate they have all of the keys for a zone as of a certain time (i.e. "now"), thus eliminating a privacy leak. | If there is a mechanism for the client to say what keys have already been validated (thus decreasing the length of the chain a server must send), there may be privacy implications. For instance, if a only small number of sites have their DS records signed by a specific key from .com and the client indicates they have already validated that specific key, another server knows the client has visited one of those sites. There may be a way for a client to instead indicate they have all of the keys for a zone as of a certain time (i.e. "now"), thus eliminating a privacy leak. | ||
== Policies == | |||
=== Self-signed Certificates === | |||
For self-signed certificates, the policy is "The certificate chain must contain one self-signed certificate and the DNSSEC chain must be valid and correspond to data in the certificate." A TLSA certificate type of CA must not be used in this case. | |||
=== Untrusted Roots === | |||
For certificates with a root of trust unknown to the client, a policy could be "The certificate chain must be valid up to the untrusted root and the DNSSEC chain must be valid and correspond to data in the untrusted root." A TLSA certificate type of CA or Public Key must be used in this case. In theory, this policy could be combined with that of self-signed certificates. It may be desirable to separate them for the sake of fine-grained policy control, however. | |||
=== Trusted Roots and DNSSEC === | |||
For certificates with a known root of trust, the policy is "The certificate chain must be valid and (the DNSSEC chain must be valid or the domain does not require such additional validation)". Currently there is no mechanism to specify whether or not a domain requires DNSSEC validation. In This case any TLSA certificate type may be used. | |||
== CNAME issues == | |||
The use of CNAME records introduces complexities into this system that have yet to be ironed out. First, if a CNAME record is present at a node, there are supposed to be no other records for that node. So, if foo.bar.com is CNAMEd to foo.bar.org, there should be no other records for foo.bar.com, and in particular there will be no TLSA record. Thus, when a client connects to foo.bar.com, no DNSSEC chain appropriate for this system can be created. (Note that it may be the case that the prefix mechanism can be used to circumvent this issue. That is, there could be a TLSA record for _443._tcp.foo.bar.com. This however does not solve all of the issues.) | |||
One way to deal with CNAMEs is to essentially build one chain per CNAME. That is, if foo.bar.com is CNAMEd to foo.bar.org, then a chain for foo.bar.com will be constructed using the CNAME record, and then a chain for foo.bar.org will be constructed using the TLSA record for foo.bar.org. If and only if both of these chains verify correctly and the hostname matches that of the first chain will the information in the TLSA record be used in the TLS connection. This could even be extended to multiple CNAMEs. If foo.bar.com is CNAMEd to foo.bar.org is CNAMEd to foo.bar.cn, then three chains will be present. | |||
This introduces a trust issue, however. If foo.bar.com is CNAMEd to foo.bar.cn, anyone in those two hierarchies can masquerade as foo.bar.com. As before, the owners of bar.com, .com, and . can create valid DNSSEC chains that appear to come from foo.bar.com. However, unlike before, now the owners of bar.cn and .cn can do the same. More importantly, just by looking at the domain name "foo.bar.com", it is not apparent that anyone outside that hierarchy has this power, when in fact they do. The issue is that while the owner of foo.bar.com may be fine with this, visitors to that site may not be, and yet they have no indication that such a thing may be taking place. Thus, it is not clear that allowing this form of delegation is desirable for the end user. | |||
== DNSSEC Libraries == | == DNSSEC Libraries == | ||
[http://www.nlnetlabs.nl/projects/ldns/ ldns], [https://www.dnssec-tools.org/ DNSSEC-Tools], and [http://unbound.net/download.html Unbound] all use BSD licenses. Thus far, I've had the most success using ldns. Unbound uses ldns. | [http://www.nlnetlabs.nl/projects/ldns/ ldns], [https://www.dnssec-tools.org/ DNSSEC-Tools], and [http://unbound.net/download.html Unbound] all use BSD licenses. [http://vantage-points.org/libvdns.html libvdns] is a C++ DNS library. Thus far, I've had the most success using ldns. Unbound uses ldns. | ||
Most likely, any DNSSEC library will use openssl. So, if that library is included in Firefox, either openssl will have to be included as well or the library will have to be modified to use nss. | Most likely, any DNSSEC library will use openssl. So, if that library is included in Firefox, either openssl will have to be included as well or the library will have to be modified to use nss. | ||
Line 72: | Line 98: | ||
== Creating a TLSA Record == | == Creating a TLSA Record == | ||
Material embedded in a TLSA record must follow the [http://tools.ietf.org/html/draft-ietf-dane-protocol- | Material embedded in a TLSA record must follow the [http://tools.ietf.org/html/draft-ietf-dane-protocol-10 specification]. This involves making the decision of what to embed. The embedded material may be a certificate identifying an end entity (i.e. the server clients will connect to), a certification authority's certificate (where that certificate is a trust anchor for a certificate on the server), or a public key (which may correspond to either of the two situations). Then, the actual data embedded may be the full representation, a sha256 hash, or a sha512 hash. Different decisions may be appropriate for different situations. (This information is currently undergoing change - refer to the latest draft of the specification.) | ||
Once the certificate type and reference type are determined, the appropriate values can be used to construct an entry that goes into the zone file for the DNS server that is authoritative for the domain name in question. For instance, if the sha256 hash of a public key were to be used, the entry might look like this: | Once the certificate type and reference type are determined, the appropriate values can be used to construct an entry that goes into the zone file for the DNS server that is authoritative for the domain name in question. For instance, if the sha256 hash of a public key were to be used, the entry might look like this: | ||
Line 86: | Line 112: | ||
The first option (X509 extension) is easy to deploy, as it only requires making a special certificate and minimal modifications to server software. It works well with self-signed certificates (where the TLSA record provides the chain of trust), but not with preexisting certificates signed by a third party. Furthermore, in order to use the optimization of sending a chain with a deeper root of trust (i.e. sending a shorter chain), the certificate would have to either be created on the fly or a certificate for every possible chain would have to be created (admittedly, this is a small number). This still doesn't solve the problem, however, because there must be a mechanism for the client to tell the server what root is appropriate. This optimization would require some small server modifications. | The first option (X509 extension) is easy to deploy, as it only requires making a special certificate and minimal modifications to server software. It works well with self-signed certificates (where the TLSA record provides the chain of trust), but not with preexisting certificates signed by a third party. Furthermore, in order to use the optimization of sending a chain with a deeper root of trust (i.e. sending a shorter chain), the certificate would have to either be created on the fly or a certificate for every possible chain would have to be created (admittedly, this is a small number). This still doesn't solve the problem, however, because there must be a mechanism for the client to tell the server what root is appropriate. This optimization would require some small server modifications. | ||
The second option (TLS extension) is more difficult to deploy, because it requires more significant server modification to implement the extension. However, it will work with both self-signed and preexisting certificates. Additionally, the short chain optimization would work as expected: the client specifies a trusted root and the server responds with a chain from that root. | The second option (TLS extension) is more difficult to deploy, because it requires more significant server modification to implement the extension. This is particularly problematic on Windows, due to Microsoft apparently only shipping new versions of SSL/TLS with new versions of Windows. However, it will work with both self-signed and preexisting certificates. Additionally, the short chain optimization would work as expected: the client specifies a trusted root and the server responds with a chain from that root. | ||
Currently the second option (TLS extension) is considered ultimately more flexible and usable. | Currently the second option (TLS extension) is considered ultimately more flexible and usable. | ||
== Format of TLS Extension == | |||
The "extension_data" field of the client hello extension currently consists of no data (i.e. it is empty and of zero length) and serves only as an indication that a DNSSEC chain has been requested. In the future this may be changed to allow for an optimization whereby the server can send less data. | |||
The "extension_data" field of the server hello extension contains "DNSSECChain" where: | |||
<nowiki> | |||
struct { | |||
RR resource_record_chain<1..2^16-1> | |||
} DNSSECChain; | |||
</nowiki> | |||
Each resource record ("RR") in the chain is in wire format as described by the appropriate RFC (see for example [http://www.ietf.org/rfc/rfc1035.txt rfc 1035]). The contents of this chain are described [[Security/DNSSEC-TLS-details#DNSSEC Chains | above]]. | |||
== Test Plans == | == Test Plans == | ||
Current test plans | Current test plans include fuzzing the added attack surface (i.e. throwing data blobs at the validator) as well as deliberately crafted DNSSEC chains (e.g. ones with expired signatures, missing links, invalid links, etc.) Additionally, the library is being run through [http://klee.llvm.org/ KLEE] to check for memory safety errors. | ||
== nginx and openssl == | == nginx and openssl == | ||
The | The webserver 'nginx' has been modified to send DNSSEC chains as a TLS extension. The details of how to set up such a modified server are [[Security/DNSSEC-TLS-nginx|here]]. | ||
== Code == | |||
Support code for this project can be found [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/ here]. Files of interest might be [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/file/tip/nss-dnssec-tls.patch nss-dnssec-tls.patch] (adds the dnssec tls handhake extension to nss), [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/file/tip/dnssec.patch dnssec.patch] (ldns with some additions and modifications), and [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/file/tip/authcertdnssec.patch authcertdnssec.patch] (calls the dnssec library to do verification). These patches are also necessary: [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/file/tip/CERT_PKIXVerifyCert-selfsigned.patch CERT_PKIXVerifyCert-selfsigned.patch] [http://hg.mozilla.org/users/dkeeler_mozilla.com/dnssec-tls/file/tip/rsa-key-from-bytes.patch rsa-key-from-bytes.patch] |