comparison with other stored security state mechanisms [was: Re: Sharing Trust Policy between Crypto Libraries]

Gabor Toth tg at
Wed Feb 13 01:53:55 PST 2013

>>>>> On Tue, 15 Jan 2013 12:18:52 +0100, Stef Walter <stefw at> said:

> BTW, I agree with Simo that SQLite is going to be a rough choice when
> sharing information across security boundaries. When building this stuff
> we need to remember that most of the regularly modified key pinning
> information is specific to a user, and not the system. The system
> information tends to be updated infrequently.

The layered databases that dconf supports would help in this case:
system information would be installed in a read-only db, then writable
user information is layered on top of this, so that every user can have their
own configuration while system information can be updated independently.

> Then attached to that you would have a number of pinning extensions that
> define the details of the pinning. So far TACK you would define a TACK
> pinning extension, which would contain the relevant TACK information to
> be used with that peer. Each pinning extension would have a unique OID.


> The format of the different pinning extensions would be defined
> separately, perhaps in an appendix, although we could work through a few
> to make sure they work.

> As an example, there would be pinning extensions for these, which might
> contain fields like the following (rough):

>  * TACK [1]
>    - Initial time
>    - End time
>    - TSK public key
>    - Min_generation
>  * Websec Key Pinning [2]
>    - max-age
>    - Pin Hashes
>    - includeSubDomains
>    - report-uri
>    - strict
>  * Pinned Raw Public Key [3]
>    - subjectPublicKeyInfo

This 3rd type of field with the SPKI would be used for local pinning
information, possibly with a TOFU model (thus it is not limited to be used
together with raw public keys on the wire as in the oob-pubkey draft). SPKI
extracted from an X.509 cert can be stored there as well, which is the case in
the local/TOFU pinning scheme in a CertPatrol-like use case, where the SPKI
structure of one of the certificates in the chain (depending on configuration,
EE/issuer/root CA) is pinned upon first connection. In this model the
following fields would be stored, one entry for each different certificate seen
for a peer:

- status: active/inactive - allows for setting multiple active pins. Replacing
          a pin would just deactivate the other entries, so that they can be
          recognized when a certificate is used again at a later time,
          which happens in case a host is using multiple certificates.
- pubkey: the pinned SPKI structure in DER format that should be present
          in the chain during verification
- chain:  X.509 certificate chain sent by peer. Enables to compare entries
          when there's a changed pubkey, also allows for selecting a different
          pin from the chain later. If intermediate CAs are added to the
          shared trust store so that they can be looked up later, then it is
          enough to store the end entity certificate.
          Empty in case of a raw public key.
- first_seen, last_seen, count_seen: these fields provide more insight when
          deciding whether or not a certificate with a changed pubkey can be
          trusted, e.g. allows detection of multiple certs used for a host

> Similar to certificate extensions these key pinning extensions can be
> marked as critical or not. If one is critical it must be understood and
> respected in order for the key pinning to be used.

So this could be part of the status field in the above structure:
- inactive: skipped during validation
- active:   any active match is accepted during validation, if there's no match,
            fallback to PKI validation is allowed
- critical: a critical entry must match during validation, otherwise it fails,
            no PKI fallback is allowed

In this case local/TOFU pinning model would use the critical status instead of

Verification of peer's certificate chain would work like this:
- check if cert or pubkey is blacklisted in shared trust store
- look up pinning information for available pinning protocols,
  using local pinning database where applicable
- apply stapled extensions to certs in the chain
- if pinning information is available, perform PKIX path validation using trust
  anchors specified by the pinning protocol: in case of DANE this depends on the
  usage field, for websec-key-pinning and local/TOFU pinning this is the SPKI of
  one of the certs in the chain
- if no matching pin entry is found and there are no unmatched critical entries,
  then perform PKIX path validation using trust anchors from shared trust store

Next point to consider is notification. In the TOFU pinning case when the pin
fails to validate, a dialog with information about the new and stored
certificates would be shown, offering the choice between aborting the connection
or replacing the pin, possibly with options to query notary services as well.
Something along the lines of:

In case the certificate is expired, there's a hostname mismatch, or it is not
trusted, a similar dialog could be shown with cert details and notary query
options. When proceeding, in the first two cases a stapled extension would be
added, in the untrusted case either
- the cert could be added to the trust anchor list without the CA bit set as
  suggested in the current version of the Sharing Trust Policy document, but in
  this case the subject names also has to be reduced to just the current host,
  and any existing stapled extensions would have to be merged
- or the cert (or a pubkey in the chain) could be pinned to the peer using the
  local pinning database, which is more suitable for this purpose, as the lookup
  is done by peer, thus there's no extra complexity with adding/merging
  extensions. This is also more similar to what Mozilla does already:

> So for key pinning you would use the 'peer' as a primary-key. One of
> the main forms for a peer is a hostname+port (and perhaps protocol).

Supporting wildcard hostnames would be useful as well when one wants to pin a
public key for a whole domain, in which case * would be stored in the
hostname part.

Websec-key-pinning does this using the includeSubDomains flag, in that case
multiple lookups are needed, every time removing a subdomain component until an
entry is found with the includeSubDomains flag set. The X.509 model defines
wildcards slightly differently: * does not include,
and only one level of subdomains are allowed. First the full host name,
then the wildcard host name would be looked up.

A use case for this would be a feature of the local/TOFU pinning scheme that
allows to pin the public key of a certificate to all hosts listed in
subjectAltName (though I wouldn't do this automatically, but would be useful
manually doing it in some cases.

I'm in the process of writing these up in more detail, and also have some work done on an
implementation of the pubkey pinning part, which I'll write about in a next mail.


More information about the p11-glue mailing list