comparison with other stored security state mechanisms [was: Re: Sharing Trust Policy between Crypto Libraries]
Ryan Sleevi
rsleevi at chromium.org
Wed Feb 13 15:46:35 PST 2013
On Wed, Feb 13, 2013 at 1:53 AM, Gabor Toth <tg at tgbit.net> wrote:
>>>>>> On Tue, 15 Jan 2013 12:18:52 +0100, Stef Walter <stefw at redhat.com> 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.
>
> Right.
>
>> 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
> active.
>
> 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:
> http://tg.tgbit.net/patrol/shots/dialog-change.png
>
> 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:
> https://developer.mozilla.org/en-US/docs/Cert_override.txt
I would discourage the notion of 'stapled extension' being used to
store user overrides. The reasons for failures to a cert can not
always be expressed as issues with end-entity certificates - for
example, it may be due to chaining policies associated with the
constructed chain, in which case, you don't want to override the leaf,
you want to override the intermediate - but only in the context of
that particular server.
I think Apple's approach to this problem is better, so it's just worth
thinking about:
Each certificate in Keychain has an array of TrustSettings objects.
Each TrustSettings is a dictionary of key/value pairs that
(collectively) must match. Only one of the keys need be specified - if
more than one key is supplied, then all criteria must match for the
TrustSettings to apply.
- Policy (eg: SSL, S/MIME, X.509, Wireless, etc)
- Policy-specific data (eg: a hostname for SSL, an e-mail address for S/MIME)
- Requesting application (in this case, a code-signing identity)
- Allowed error (a specific error code that may be overridden)
- Result (the effective result to treat a certificate that matches
this policy)
See the documentation at
https://developer.apple.com/library/mac/documentation/security/Reference/certifkeytrustservices/Reference/reference.html#//apple_ref/c/func/SecTrustSettingsCopyTrustSettings
This acknowledges several important use cases:
1) "overrides" (pinned settings) may be contextual dependent on the
usage/purpose of the certificate
2) "overrides" (pinned settings) may be contextual dependent upon the
error (or SET of errors)
3) "overrides" (pinned settings) do not attempt to 'rewrite' the cert
4) [Not examined in depth] It also reflects a hierarchy of trust
settings - User -> System [Admin Defined] -> System [OS defined].
In thinking about how errors are overridden, especially when storing
them in a system database, it's important to consider the hierarchy of
trust for error overrides (the local/TOFU case).
>
>> 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 *.example.com 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: *.example.com does not include example.com,
> 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.
>
> -tg
> _______________________________________________
> p11-glue mailing list
> p11-glue at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/p11-glue
More information about the p11-glue
mailing list