2014-08-01 IRC conversation

hc: hey Ge0rG
_hc: saw your email
Ge0rG: chatsecure is fixed already, https://github.com/n8fr8/Gibberbot/commit/b2d0b2a71f6317e055e63b73540974807cfbe956
_hc: the change in chatsecure is simple since it is just removing a null. but in fdroid is not so simple since a default trust manager is being passed.
_hc: does MemorizingTrustManager then connect to the system trust manager using the new constructor?
Ge0rG: MemorizingTrustManager will fall back to whatever you supply, and to whatever that will fall back.
Ge0rG: the system trust manager will only be used if the pinning trust manager uses it
Ge0rG: which IIRC it does.
Ge0rG: technically, MemorizingTrustManager always only had a fall back to one trust manager. the first parameter was a wrongly exposed local variable.
_hc: this first parameter? do you mean the third parameter, the one that was removed?
Ge0rG: from the three parameters, the second was removed. both chatsecure and fdroid incorrectly used it, instead of the third one.
Ge0rG: but of course, the error was in exposing it at all.
Ge0rG: what MemorizingTrustManager exposed as the second parameter was its own trustmanager based on its local keyfile. overwriting that essentially broke MemorizingTrustManager
Ge0rG: the former third (now second) parameter is the default trustmanager that MemorizingTrustManager should use if it does not have a server cert stored.
Ge0rG: so you supply AndroidPinning as the new second parameter, and MemorizingTrustManager will do the follwing: a) check local keystore, b) check AndroidPinning, c) ask user
Ge0rG: the first succeeding one will authenticate the connection
_hc: what would be useful is if it would check AndriodPinning before MemorizingTrustManager
Ge0rG: could you please explain why?
_hc: if there is a successful pin, why check anythign else?
_hc: the pinning form is the simplest to get right, so it seems it should be the most trusted
_hc: what happens if something adds a MITM cert for a hostname to the local keystore?
_hc: then the pinning will be ignored
Ge0rG: what should happen if there is no pinning?
_hc: I don't understand
Ge0rG: as long as either MemorizingTrustManager or AndroidPinning will accept the certificate, the order does not matter.
_hc: you mean if AndroidPinning is installed but without pins?
_hc: the order does matter
_hc: say you have a pin for google.com
Ge0rG: AndroidPinning does not allow pinning hostnames. it only has a whitelist of certificates.
_hc: then someone adds a MITM cert for google.com to the local keystore
_hc: ah, ok, I didn't realize that
Ge0rG: so AndroidPinning will only tell you "I don't know this cert, I fail now". and MemorizingTrustManager will happily ask the user
Ge0rG: there is no "this cert does not match what I know about google.com, OMGMITM"
Ge0rG: it would make a useful feature for AndroidPinning though. Or for MemorizingTrustManager
Ge0rG: My goal with MemorizingTrustManager is to integrate all the interesting things you discussed for chained cert trust
Ge0rG: and maybe also DANE
_hc: yeah, the chaining only works with pinning with the hostname
Ge0rG: I'm going to add an option to MemorizingTrustManager to tell the user that a certificate has _changed
.
Ge0rG: but that will only affect certificates stored in MemorizingTrustManager, not the system-approved ones.
Ge0rG: unless you supply null as the defaultTrustManager, which makes MemorizingTrustManager distrust everyone
Ge0rG: so back to your question: with the current design of AndroidPinning, it does not make any sense to check pinning before local trust store.
Ge0rG: if you change AndroidPinning to pin hostnames, you might add a defaultTrustmanager parameter in there and pass MemorizingTrustManager
Ge0rG: that way, if AndroidPinning succeeds, MemorizingTrustManager is queried, and if AndroidPinning fails, the connection fails.
Ge0rG: however, with X509TrustManager you can not easily pin hostnames.
Ge0rG: which is a completely separate issue.
_hc: god this stuff is a mess
Ge0rG: read the link from my mail.... :>
_hc: I skimmed it
Ge0rG: that must suffice then
_hc: for fdroid I think it'll make sense to use only AndroidPinning and MemorizingTrustManager, and distrust everything else
_hc: there is already a tofu dialog for the repo signing key, so that dialog can also function for the HTTPS certs
Ge0rG: AndroidPinning trusts the system by default. or better. AndroidPinning perfoms (pinned AND system_trusted)
Ge0rG: with MemorizingTrustManager it is then (pinned AND system_trusted) OR user_accepted
_hc: ah, that provides the hostname check then
_hc: system_trusted
Ge0rG: you wish.
Ge0rG: that is completely orthogonal. but if you are using the default HTTP AndroidPinningIs, they do check hostnames
Ge0rG: I assume what you want to achieve is (pinned OR user_accepted)
_hc: so does MemorizingTrustManager check hostname-cert?
_hc: well, it should continue to check the system store whenever possible since that is insurance from the lib making security worse than default
_hc: I think it needs to be more complicated than (pinned OR user_accepted)
Ge0rG: but you see how (user_accepted AND system_trusted) is worthless for most private cloud installations?
Ge0rG: you are probably right.
_hc: I think it should be like:(pinned OR user_accepted)
_hc: oops
Ge0rG: "(pinned AND system_trusted) OR user_accepted" is actually pretty reasonable, provided you have hostname-pins.
Ge0rG: which we don't
Ge0rG: actually, it all boils down to "do we trust the user to do the right thing"?
_hc: (pinned AND system_trusted) OR (user_accepted-ca_signed AND system_trusted) OR (user_accepted-self_signed)
Ge0rG: what about signed_by_user_created_ca?
_hc: then user_accepted can be automatically set on the first time if it is system_trusted
Ge0rG: ah, wait.
Ge0rG: you are adding state now.
_hc: you mean like cacert?
Ge0rG: right.
_hc: meh
_hc: does not seem worth supporting, but I suppose it would be possible
Ge0rG: I define "user_accepted" as "there was an MemorizingTrustManager popup and the user clicked 'always'"
_hc: if there is a user-ca, they should import it manually into the system store
_hc: that's the intended model
Ge0rG: so if there is such a popup both with self_signed and (ca_signed AND system_trusted), it does not make sense to differentiate these
Ge0rG: on android 4.4, you get really scary warning popups if you have a CA added
_hc: c'est la vie
Ge0rG: that's exactly what they said when I started developing MemorizingTrustManager.
_hc: that is an issue of android 4.4
_hc: you can't fix all the issues in this library
Ge0rG: that's an issue that is not going to go away magically.
_hc: that is a recipe for security disaster
Ge0rG: like SSLSocket mis-design being an issue of Java.
_hc: that is separate
_hc: the CA system is not really designed to handle user configured CAs
Ge0rG: we can't force google to do "the right thing". especially not if we don't know what the right thing is.
_hc: so trying to force that case in the MemorizingTrustManager library is a mistake
Ge0rG: I don't see the principal difference between self-signed and private-ca-signed.
_hc: the CA?
Ge0rG: from the users perspective, that is.
_hc: that's a huge difference in the eyes of the CA verification system
Ge0rG: the user just wants his private cloud deployment to work, instead of throwing nasty error messages onto him
_hc: sounds like they should get a proper certficiate then
Ge0rG: I see how trusting a CA is more problematic than trusting a single host cert. However, trusting a CA-signed host cert might be acceptable behavior.
Ge0rG: not everybody can get a valid certificate as defined by the CA extortion racket.
_hc: I'm not denying it is a problem, I just don't think it can be solved here without weakening the security for the rest of the cases
_hc: that does not seem worth it
_hc: that sounds like it should be a separate library then
Ge0rG: I don't see how this is a different problem.
_hc: with support for the private-CA, the library uses the CA intact and unchanged
_hc: the CA system
Ge0rG: currently, if you tell MemorizingTrustManager to always accept a CACert-signed certificate, MemorizingTrustManager will from now on accept all CACert-signed certs.
Ge0rG: I suppose this is a security problem.
_hc: yes, that's not good
Ge0rG: so I'll change it to only trust the given cert.
_hc: I think here's the solution: categories certs by trusted signing key (CA) and untrusted (private CA and self-signed) and
Ge0rG: this will mean that self-signed and CACert-signed will be handled the same way.
_hc: MemorizingTrustManager will TOFU prompt the untrusted on first use
Ge0rG: this is how it is done already.
_hc: for trusted ones, the library will check the CA sig and mark as trusted if the CA sig is good, otherwise prompt the user
Ge0rG: the system trust manager performs the CA check already.
_hc: so MemorizingTrustManager trusts the private key?
Ge0rG: I only ask the user if thsat fails.
Ge0rG: MemorizingTrustManager trusts the certificate, not the key.
_hc: the point for us is to make TOFU work like AndroidPinning, so that it is always checking the TOFU and the CA
Ge0rG: so you want an error if the server's cert changed?
_hc: MemorizingTrustManager trusts the signing certificate? or the TLS cert?
Ge0rG: currently, if you tap "always", MemorizingTrustManager will trust the whole chain of the presented cert, including CA and intermediate.
Ge0rG: I can see how this is worse than only trusting the given server cert.
_hc: I think MemorizingTrustManager should trust the SPKI of the certificate itself
_hc: like AndroidPinning
_hc: not the whole chain
_hc: trust the server's private key
_hc: not the CAs
_hc: or signer
_hc: then the server can freely generate new certs as long as the private key is the same
_hc: that is the pinning model
Ge0rG: I need to check how I can store the public key info of a server
Ge0rG: and let a default TrustManager verify that.
Ge0rG: currently, MemorizingTrustManager will re-ask if the certificate changed.
Ge0rG: unless it was signed by the same CA.
_hc: I am pretty sure that AndroidPinning uses the SPKI of the cert, so check there
_hc: https://www.imperialviolet.org/2011/05/04/pinning.html
Ge0rG: yeah, the question is if I can store it in my KeyStore.
Ge0rG: I don't really want to rewrite most of MemorizingTrustManager's backend
_hc: " the SubjectPublicKeyInfo is not just the public key bit string. The SPKI includes the type of the public key and some parameters along with the public key itself."
_hc: you'll just need to implement a check of algorithm and keysize, I beleive
_hc: the public key can be stored in the keystore
Ge0rG: I use the cert's DN as the keystore key.
Ge0rG: so a changed cert will impose some challenges.
_hc: in your implementation?
Ge0rG: right
_hc: it should be straightforward: when there is a new cert, check that the DN and SPKI match, and if so, swap in new for old
Ge0rG: or just ask the user?
_hc: mind if I post this conversation to our public wiki?
Ge0rG: what if the private key was leaked, and Mallory created a new self-signed cert with it?
_hc: asking the user would defeat the purpose of pinning based on SPKI
Ge0rG: do it please.
Ge0rG: silently replacing a cert is the opposite of pinning.
_hc: the pin is based on the key, not the cert
_hc: so the cert can change, i.e.when one expires, but the key must remain the same
Ge0rG: the PKI model implies that a key can be leaked once its certificate is expired
_hc: that's not Google's assumption
_hc: or moxies
Ge0rG: we can't marry PKI and SPKI without creating frankenstein's baby.
_hc: since both of their pinning is based on key
Ge0rG: neither google nor moxie are your typical users.
_hc: millions of people use chrome, which includes pins to google's keys
_hc: who are the "typical users" that you mention here?
Ge0rG: people who can't afford a verisign cert for their owncloud instance hosted on a raspberry pi
_hc: when you get a certificate from a CA, they assume you are reusing the private key
_hc: if people don't know that you should keep private keys secret, they have much bigger problems than a bad pin
Ge0rG: you might be reusing the private key when you are requesting a new certificate, but what do you do with the key once the certificate has expired?
Ge0rG: I'm just saying that a change of the server certificate, even with the same private key, is a noteworthy event
_hc: for some people
_hc: sure
_hc: the vast majority of people using services based on TLS have no idea that there are even certificates, let alone that they expire
Ge0rG: so, what can we do?
_hc: I personally don't see a need to notice when a cert has changed as long as the DN and SPKI are the same,
_hc: and its pinned
_hc: I need to get to writing a proposal due very soon, but good conversation, looking forward to seeing what you come up with
Ge0rG: sure.
Ge0rG: another thing that bothers me is: if I add a cert for a mismatching hostname to my keystore, my local trustmanager will happily accept the certificate itself for any hostname.
Ge0rG: you might want to pull MemorizingTrustManager cd9bbf8
Ge0rG: https://github.com/ge0rg/MemorizingTrustManager/commit/cd9bbf8f7cc3cffa1abe1a7a2c775f345e7c489f
Ge0rG: the same applies for chatsecure.

Also available in: PDF HTML TXT