Public Key Pinning Extension for HTTP
draft-ietf-websec-key-pinning-21

Note: This ballot was opened for revision 19 and is now closed.

(Richard Barnes) Yes

Comment (2014-08-06 for -19)
No email
send info
This is an important document, and overall clearly written.  There are a few points that it would be good to clean up.


Introduction: "At least one UA..."

FWIW, this is now "At least two UAs..."  Firefox also has a manual pin list as of version 32, currently in Beta.


Introduction: "but is possible to pin keys without requiring HSTS"

-> "but it is ... and vice versa."


Section 2.2.2. "Pinned Hosts SHOULD NOT include..."

This applies not just to Pinned Hosts, but to any web host, right?


Section 2.3.1. "If a UA receives more than one PKP header field ... only the first PKP-RO header field (if present)"

This seems problematic in light of the fact that HTTP recipients are allowed to coalesce the values of multiple header fields.
http://tools.ietf.org/html/rfc7230#section-3.2.2

So, for example, if header coalescing were done at a lower layer in the HTTP stack than HPKP, then the pinning code wouldn't be able to distinguish "first" vs. "rest".  On the other hand, maybe this is a use case for using semicolons as separators, since the combined header field would not be valid.  In either case, there's a need for updated text.


Section 2.5. "at least one Pin that does NOT refer to an SPKI in the certificate chain"

I understand the motivation for this, but this doesn't actually force the site to have a backup pin -- they can just make up a pin value.  It seems like it would be more effective to make the recommendation in Section 4.3 stronger.


Section 4. "Security Considerations"

Most of these seem more like "Operational Considerations" or "How-To-Not-Brick-Your-Site Considerations".  :)

Alissa Cooper Yes

Comment (2014-08-05 for -19)
No email
send info
I agree with Pete's comment about the first sentence.

It would be nice if in Section 5 or 7 some suggestion could be made for UAs to consider the relationship between the functionality they provide to clear pins/pinned hosts and the functionality they provide to clear (or prevent the storage of) other UA state. E.g., upon clearing one's browsing history or entering private browsing mode, it seems like having the option to clear pins/pinned hosts or not pin would make sense. This is alluded to in Section 7 but not really tied to the threat described in Section 5.

I'm also curious about whether there is any reason to retain expired pins? (Other than the fact that flushing them requires the UA to actively check which ones are expired.)

(Stephen Farrell) (was Discuss) Yes

Comment (2014-10-09)
No email
send info
Thanks for clearing up my discuss points. One possible
remaining nit though:

- In 2.2 you say: "(1) the processing rules for HTTP
   request messages received over a secure transport (e.g.
   authenticated, non-anonymous TLS); "

Should the "e.g." be an "i.e." ? It's probably fine either
way but just wondered.

-- OLD comments below, didn't check 'em

abstract and elswhere: SubjectPublicKeyInfo doesn't usually
have spaces between the terms. No big deal. After the abstract
would a ref to 5280 be right for SPKI as well?

general: I think emphasising the backup pin requirement in the
intro would be good. It's a little hidden now and would be a
surprise to some I bet.

2.1 - pin-directive has the literal "pin-" but later you say
(in bullet #3) that directive names are case insensitive.  Does
that apply to "pin-" as well or not? 

2.1 - has some typos: reistry and hahs

2.1 - "Known Pinned Host" would be a fine term to define in a
section 1.1 that was renamed via s/Requirements
Language/Terminology/

2.1.1 - max-age is really defined against the time of reception
and not (in principle) from when its emitted?  I know that
makes no difference now, but with a sufficient latency (e.g.
Earth->Mars, min 4 mins, max 20 mins, and yes my DTN heritage
is showing:-) it could, just about. I think to be pedantically
correct, max-age ought be defined versus the time of emission
and not receipt.

2.1.2 - uses the term "Pinned Host" which is not the same as
the previously used "Known Pinned Host" - is the distinction
meant to be significant or is that a typo?

2.1.3/section 4 - shouldn't the potential DoS issues be
discussed for cases where report-uri != same-origin? E.g.  if
busy-site.example.net (is hacked and) sets report-uri to
victim.example.com (maybe with some HTML/JS that generates
loads of queries to the victimj) that'd be like getting /.'d I
think that's maybe worth noting in the security considerations
or in 2.1.3 where you (quite properly) say to rate-limit
reporting. If you'd rather not say why though, that's ok too.

(Barry Leiba) Yes

(Jari Arkko) No Objection

Spencer Dawkins No Objection

(Adrian Farrel) No Objection

(Brian Haberman) No Objection

Comment (2014-08-05 for -19)
No email
send info
I agree with Pete's Comments.

(Joel Jaeggli) No Objection

(Ted Lemon) (was Discuss) No Objection

Comment (2014-10-08)
No email
send info
I've cleared my DISCUSS.   For the record, here it is, but there is no further action required:

This mechanism relies on there being no MiTM attack from a compromised signing key either prior to a legitimate pinning, or in a situation where the host being "protected" doesn't actually do pinning.   I think this should be mentioned in the security considerations section.   I raise this to the level of DISCUSS because I think this actually creates a new attack surface for government censorship: you MiTM the host you're attacking, pin it to a cert signed using a compromised CA, and then that UA can't communicate with the host again for the duration of the pin.

The scenario would be that the government has a transparent web cache in the path between the host and the UA, and the web cache pins false cert for hosts that are being censored.   Now even if the user sets up a tunnel to bypass the transparent cache, they can't access the censored site, so they conclude that the site is down and abandon the tunnel.   I could easily see this being used in a scenario like the recent DNS censorship in Turkey.

Setting a lower maximum pin age mitigates the damage of such attacks if the user keeps the tunnel up for the duration of the pin, but I don't think it's realistic to assume that they will.   I think that the only way to mitigate this attack is to have a mechanism whereby conflicting DANE TLSA information overrides the pin.   This would allow a site being attacked in this way to securely inform the UA that the pin was invalid.   The government could of course prevent DNSSEC validation, but the UA could take this as another signal to drop the pin: if the zone where the TLSA record should be fails to validate (as opposed to isn't signed, which wouldn't signify anything), the pin is likely a censorship attempt.

(Kathleen Moriarty) (was Discuss) No Objection

Comment (2014-10-11)
No email
send info
Thanks for the adjustments to address my concerns/questions.

(Pete Resnick) No Objection

Comment (2014-08-04 for -19)
No email
send info
1: The first sentence is quite confusing. Might I suggest instead:

   This document defines a new HTTP header that enables user agents
   (UAs) to determine which Subject Public Key Info (SPKI) structures
   will be present in the web host's certificate chain in future TLS
   [RFC5246] connections.

2.1:

   Public-Key-Directives = [ directive ] *( OWS ";" OWS [ directive ] )

Are you sure that's correct? First of all, it may be completely empty. That seems like something you wouldn't want. Second of all, it allows for semicolons without directives between them, which may or may not be what you want. It's not clear to me why you made this semicolon-delimited instead of comma-delimited, which would be much more in line with the rest of HTTP. Then you'd simply get:

   Public-Key-Directives = 1#directive

But if you insist on semicolons, you want either:

   Public-Key-Directives = directive *( OWS ";" OWS directive )

or if you want to allow for empty elements:

   Public-Key-Directives = *( ";" OWS ) directive *( OWS ";" [ OWS
    directive ] )
    
If the following is acceptable:

   Public-Key-Directives: ;;;;;

then your original is fine.

s/hahs/hash

10.1:

Update 4627 to 7159

I think W3C.REC-html401-19991224 is informative. This document says that you MUST NOT do what's in that document.

(Martin Stiemerling) No Objection