Keeping with our Halloween theme, today we have Pinhead. Because it’s horror stuff but also because the article is about key pinning (because “pin”, get it?) I kill me.
If you’re not familiar with key pinning, it’s basically a mechanism to allow a server, via HTTP response headers, to send a message to a “user agent” (i.e. your browser) about what public key to expect that server to use. In other words, to say something akin to “hey… when you talk to me, you should get this certificate or one of these public keys.”
Why do this? It’s a (kludgy I’d argue) workaround for CA compromise. Say, for example, bad guys trick some CA into issuing a certificate for *.google.com. Those bad guys what to use that certificate to do all kinds of shenanigans – set up a proxy for MITM for example. Sounds nefarious, right? But if the server has already told the client “hey, if you talk to me later and you don’t get this particular cert – or a cert that contains a public key matching XYZ – then you’re probably being scammed.” This lets the browser warn people about it if they get something they don’t expect.
If you really want to understand how it works at a high level of depth, the RFC (RFC 7469) is the best way to get there, but another useful resource is the page up at OWASP about it. It’s really not complicated though: response headers that specific certificate or key information to be used by the browser to “pin” what they should expect to receive from that site.
The primary reason why Google pulling back on it is super interesting though is because it was Google that started all this pinning stuff in the first place. For example, check out that RFC that I linked to before – do you notice who wrote it? Yeah. Google. And recently too. So that’s interesting. They cite three factors for this decision; paraphrased, they are: it’s hard to do (exacerbated by the fact that not many people are supporting it), it’s risky, and someone could attack it. Is it a good idea? Yes… yes it is. Are they right to deprecate it? Yes, I think they are.
If those two statements sound incompatible to you, I come back to the statement that I made earlier about it being a kludge. I say it’s a kludge (for you youngsters, “kludge”=inelegant workaround) because it’s outside where this should (in my opinion) really happen, which is the TLS protocol itself… better yet, in TLS implementations based on instructions built into public PKI certs.
Here’s why I say that. HPKP is out of band to TLS — in the response headers, right? But wouldn’t it be nice if other, non-HTTP connections could have this same safety feature? Sure. Can they? No… not with this mechanism anyway. From a conceptual point of view, the problem we’re trying to solve isn’t really a problem with HTTP… HTTP is fine the way it is. It’s also not really a TLS issue. The mechanics of security issues in the certificates it uses are, I’d argue, outside of the scope of the TLS standard. Instead, it’s a PKI problem. So addressing it at the PKI level seems to make the most sense.
If it were up to me to design a fix, I would use either extended key usage (in the certificate) or the certificate policy extension to implement HPKP. Why? Because that’s what these fields are for – i.e. information about certificate policy (many times this is just a link, but it doesn’t have to be) or about how they key should be used. That’s step one. Step two would be to get relying parties (such as TLS implementations) to “want” to pin the cert if they get one that has this field set to something informative. In other words, they do it because the cert specifies they should and gives them instructions on how. The implementation can be agnostic about why, for what purpose, whether used in HTTPS or something else, etc. In fact, you could do everything you’re doing now in HPKP… just more cleanly and in a way that lets you use it for other use cases too.
At the end of the day, I do think HPKP is a good idea. It starts from the presupposition that “bogus certificates will happen”. As a practical matter they do — for some pretty straightforward economic reasons that I’ve laid out in the past. Recognizing this is good security. But that said… I think if you’re going to do it, the browser is the wrong place to implement it. The cert, on the other hand, seems like a better path.