Skip to content
trevp edited this page Feb 3, 2012 · 40 revisions

TACK (Tethered Assertions for Certificate Keys)

Rationale

The Convergence system is very effective at introducing clients to servers. The Convergence client then caches the server's certificate for future use. If the cached certificate changes in the future, the client will contact Convergence notaries. This mitigates local attacks (the common case) but not global attacks which replace the server from all network viewpoints.

TACK provides a way for clients to cryptographically verify certificate changes without relying on notaries or CAs. This provides security against global attacks, and improves efficiency by reducing notary connections.

Non-Convergence clients can use TACK as well. Without Convergence, a client's initial connection to a site will rely on existing security mechanisms. However, subsequent connections will be strongly protected.

Overview

TACK allows an SSL site to specify a TACK public key which the site will use to sign its certificate chain(s). This TACK key and its signatures are distinct from the SSL keys and signatures comprising the site's certificate chain. TACK keys and signatures are ignored by non-TACK-aware clients.

Delivery Mechanisms

The TACK key and signature, along with some associated data, are collectively known as a "TACK". The TACK is packaged into a "TACK Extension". This TACK Extension is asserted by the server, and validated by the client, as part of the SSL (or TLS) handshake. There are two ways a TACK Extension can be sent from server to client:

  • As a TLS Extension to the ClientHello and ServerHello messages
  • As an X.509v3 Extension inside a "superfluous" certificate in the server's certificate chain.

The first approach is the most standards-compliant, but requires software updates to the client and server. The second approach can be deployed on legacy servers, and can be supported in browsers via plugins. It works as follows:

A normal SSL certificate chain for an end-entity such as thoughtcrime.org might look like this:

VeriSign Level 1
   |
   ---> VeriSign Intermediate CA
           |
           ---> www.thoughtcrime.org

If thoughtcrime.org were to present a TACK Extension, however, the certificate chain would look like this:

TACK Certificate (does not sign or chain to the preceding certificate)
VeriSign Level 1
   |
   ---> VeriSign Intermediate CA
           |
           ---> www.thoughtcrime.org

A "TACK Certificate" containing a TACK Extension is included in the SSL/TLS Certificate message (it is not strictly part of the chain, since it doesn't sign the other certificates). Clients that do not understand TACK will simply ignore it, while clients that do understand TACK will parse it to interpret the TACK.

TACKs

To use TACK, thoughtcrime.org would generate an ECDSA signing key, and use it to sign one of the SSL keys or certificates in its SSL certificate chain (for most cases, signing the end-entity certificate is best). The TACK public key and signature are combined with some metadata into the site's "TACK", and delivered to the client via one of the methods discussed above. When the site updates its certificate chain, it "updates" the TACK by replacing the signature.

Pins

Upon encountering thoughtcrime.org's TACK for the first time, the client creates a "pin". A pin is a data structure that is used to accept or reject future TACKs. A pin consists of:

  • A "TACK_Key" structure containing the site's public key (or a hash of TACK_Key).
  • A "pin expiration" time at which the pin should be discarded.
  • A "generation" number. TACKs with earlier generations will be rejected.

When the client encounters a future TACK for thoughtcrime.org, it checks that:

  • The SSL/TLS handshake completes successfully
  • The pin is non-expired.
  • The TACK's TACK_Key is identical to the pin's TACK_Key.
  • The TACK's TACK_Sig contains a valid signature over some component of the site's SSL certificate chain.
  • The TACK's TACK_Sig is non-expired.
  • The TACK's TACK_Sig generation is >= the pin's generation.

If all these checks pass, the TACK is accepted, and the pin is updated:

  • The pin's expiration is updated based on the TACK's "duration" value.
  • The pin's generation is updated based on the TACK's "generation" value.

Break Signatures

A site might wish to stop maintaining its TACK, or may lose trust in and wish to revoke its TACK public key. To do this, a TACK Extension may contain a list of "Break Signatures". These are signed statements by a TACK public key disavowing a TACK pin.

If a client contacts a site for which it has a pin, and the site either does not have a TACK, or the TACK is rejected by the pin, the client will check the break signatures (if any). If one of the break signatures matches the pin's TACK_Key and is cryptographically valid, the client will discard the pin and behave as if it was contacting the site for the first time (e.g. by checking with Convergence notaries).

If there is a pin failure and no break signature for the pin, the browser will reject the connection.

Structure of TACK Extension

The following definitions use the SSL presentation language defined in RFC 2246.

enum {v1(1)} TACK_Key_Type;
enum {v1_cert(1), v1_key(2)} TACK_Sig_Type;

struct {
   TACK_Key_Type type;
   opaque public_key[64];
   opaque nonce[8];
} TACK_Key;

struct TACK_Sig {
   TACK_Sig_Type type;
   uint8  generation;
   uint32 expiration;
   opaque target_sha256[32];
   opaque signature[64];
} TACK_Sig;

struct {
   TACK_Key key;
   TACK_Sig sig;
   uint32 duration;
} TACK;

struct {
   TACK_Key key;
   opaque break_signature[64];
} TACK_Break_Sig;

struct {
   TACK tack<0...179>   # 0 or 1 TACKs
   TACK_Break_Sig break_sigs<0...1370>   # 0...10 Break Signatures
} TACK_Extension;
  • "public_key" is an elliptic curve public key on the NIST P-256 curve.
  • "nonce" randomizes the TACK_Key so that a single public key can be used with pins for different sites.
  • "expiration" is a uint32 encoding UNIX time / 60. The signature will be rejected by a client if the expiration time has elapsed. Sites could mitigate the risk of SSL key compromise by using shorter-lived signatures.
  • "generation" assigns each signature a generation. A client should store the largest generation it has seen for a given pin. A signature will be rejected if its generation is less than the stored value. This allows a site to explicitly revoke earlier generations of signatures that have not yet expired. Upon receiving a new value for generation, the client should allow a 24 hour grace period before rejecting previous generations, to allow time for all servers in a large site to be updated.
  • "target_sha256" is a SHA256 hash of either a SubjectPublicKeyInfo field from an X.509 certificate (if sig.type=v1_key), or an entire X.509 certificate (if sig.type=v1_cert) in the current SSL Certificate chain.
  • "signature" is an ECDSA-P256-SHA256 signature over the entire TACK structure prior to the "signature" field.
  • "duration" is a uint32 encoding a number of minutes. The pin will be discarded by a client after this many minutes has elapsed. Upon successfully validating a TACK and performing the SSL/TLS handshake, the client will updates its stored pin expiration time to current time + duration.
  • "break_signature" is an ECDSA-P256-SHA256 signature of the TACK_Key.

Details of TACK fields

  • The public key field "public_key" is a pair of nonnegative integers (x,y) representing a point on the elliptic curve P-256 defined in FIPS 186-3. Each integer is less than 2^256. Each integer is encoded as a 32-byte octet string using the Integer-to-Octet-String algorithm from SEC1, and these strings are concatenated with the x value first to produce a 64-byte octet string. (NOTE: This is equivalent to an uncompressed subjectPublicKey from SEC1, except that the initial 0x04 byte from subjectPublicKey is omitted).
  • The signature fields "signature" and "break_signature" are each a pair of nonnegative integers (r,s) representing an ECDSA signature as defined in FIPS 186-3. Each integer is less than 2^256. Each integer is encoded as a 32-byte octet string using the Integer-to-Octet-String algorithm from SEC1, and these strings are concatenated with the r value first to produce a 64-byte octet string. (NOTE: This differs from ECDSA-Sig-Value in SEC1 which conveys the integers inside an ASN.1 sequence. Since ECDSA-Sig-Value is variable-length, and unnecessarily complex for this application, it was avoided).
  • The "expiration" field specifies a check that is applied to the current UTC time to determine whether the TACK Sig should be accepted or rejected. If the current UTC time, when converted to an integer via the algorithm in POSIX.1, is less than the value expiration*60, the check passes and the structure is accepted. Otherwise, the structure is rejected.

Details of TACK Extension Delivery

Clients may include an extension of type "tack" in the (extended) client hello. The "extension_data" field of this extension shall be empty. A server may respond with an extension of type "tack". The "extension_data" field of this extension shall contain a TACK_Extension.

In case the server did not send an extension of type "tack", the client may examine the certificate chain for a TACK Certificate. The TACK certificate is recognizable due to a Subject Name of "TACK" and the presence of an X.509v3 extension of "extnID"=1.3.6.1.4.1.38964.1 and "extnValue" containing a TACK_Extension.

Editors

  • Moxie Marlinspike and Trevor Perrin.

Acknowledgements

Valuable feedback has been provided by: Adam Langley, Chris Palmer, Nate Lawson, and Joseph Bonneau.

Clone this wiki locally