Message ID | 20180417165000.3872-1-Jason@zx2c4.com |
---|---|
State | Superseded |
Headers | show |
Series | [Openvpn-devel] Support fingerprint authentication | expand |
Hi Jason, [ Dumping my thoughts so this doesn't remain completely unanswered for even longer. ] On 17-04-18 18:50, Jason A. Donenfeld wrote: > OpenVPN traditionally works around CAs. However many TLS-based protocols also > allow an alternative simpler mode in which rather than verify certificates > against CAs, the certificate itself is hashed and compared against a > pre-known set of acceptable hashes. This is usually referred to as > "fingerprint verification". It's popular across SMTP servers, IRC servers, > XMPP servers, and even in the context of HTTP with pinning. > > So, I'd like to propose an extremely simple and non-invasive way of > supporting this in OpenVPN, by re-using several features that already > basically support it. Namely, what I propose is: > > * Allow specifying 'none' to the --ca parameter, to specify that > certificates should not be checked against a CA. Note that 'none' > is already used in other similar options as a special placeholder. > > * When '--ca none' is in use, --verify-hash checks all depths instead > of just level 1. > > With these very simple changes, fingerprint authentication is easily achieved > via the --tls-verify script on the server and via --verify-hash on the client. Adding support for fingerprint authentication sounds like a good idea to me. Even if it was just to simplify config for peer-to-peer and small (home) setups by getting rid of the need to create and maintain a CA. So: feature Ack. However, if we were to add this, I think I'd rather make it a first-class citizen. For example by adding a peer fingerprint verification option that works in both client and server configs, and is mutually exclusive with --ca. I'd expect such an option to accept an (inline-able) file that contains a list of fingerprints, so one can make a config like: <allowed-peers> AA:BB:CC:DD:.. AA:BB:CC:DE:.. </allowed-peers> Or maybe base64 fingerprints, because a lot of people have been trained by SSH to recognize short base64 strings as fingerprints. Anyone else from the community that has some thoughts on this? As for implementation: I'm already having problems getting to my review queue, so am not promising to implement this. I would definitely put a patch for this on my review queue though :) -Steffan ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi Steffan, On 17/05/18 20:31, Steffan Karger wrote: > Hi Jason, > > [ Dumping my thoughts so this doesn't remain completely unanswered for > even longer. ] > > On 17-04-18 18:50, Jason A. Donenfeld wrote: >> OpenVPN traditionally works around CAs. However many TLS-based protocols also >> allow an alternative simpler mode in which rather than verify certificates >> against CAs, the certificate itself is hashed and compared against a >> pre-known set of acceptable hashes. This is usually referred to as >> "fingerprint verification". It's popular across SMTP servers, IRC servers, >> XMPP servers, and even in the context of HTTP with pinning. >> >> So, I'd like to propose an extremely simple and non-invasive way of >> supporting this in OpenVPN, by re-using several features that already >> basically support it. Namely, what I propose is: >> >> * Allow specifying 'none' to the --ca parameter, to specify that >> certificates should not be checked against a CA. Note that 'none' >> is already used in other similar options as a special placeholder. >> >> * When '--ca none' is in use, --verify-hash checks all depths instead >> of just level 1. >> >> With these very simple changes, fingerprint authentication is easily achieved >> via the --tls-verify script on the server and via --verify-hash on the client. > Adding support for fingerprint authentication sounds like a good idea to > me. Even if it was just to simplify config for peer-to-peer and small > (home) setups by getting rid of the need to create and maintain a CA. > So: feature Ack. > > However, if we were to add this, I think I'd rather make it a > first-class citizen. For example by adding a peer fingerprint > verification option that works in both client and server configs, and is > mutually exclusive with --ca. I'd expect such an option to accept an > (inline-able) file that contains a list of fingerprints, so one can make > a config like: > > <allowed-peers> > AA:BB:CC:DD:.. > AA:BB:CC:DE:.. > </allowed-peers> > > Or maybe base64 fingerprints, because a lot of people have been trained > by SSH to recognize short base64 strings as fingerprints. > > Anyone else from the community that has some thoughts on this? > > As for implementation: I'm already having problems getting to my review > queue, so am not promising to implement this. I would definitely put a > patch for this on my review queue though :) > > I have some strong thoughts on this, mostly related to: can someone explain to me why this is safe? I've seen that OpenSSH 7.7 now implements something similar (xmss hash-based signatures, https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12, disabled by default) but that works entirely differently from what is proposed here; amongst other things, it uses *one time private keys* to maximize security - do we want to add something like that to our TLS stuff (my gut answer: no). How can a hash replace a public key, cryptographically speaking? if you are not replacing public keys, then who generates, stores, maintains these public keys? What about accounting in such a setup? with certificates, you normally hand out a certificate to a person, with the name of the person/entity in it. If that person misbehaves, you revoke the certificate and presto. Is it sufficient to remove the hash from the config? if so, wouldn't it be better to have a directory with hash-files, so that you can add and remove hashes without having to update the server config and/or restart the server to pick up new hashes? JM2CW, JJK ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>> > I have some strong thoughts on this, mostly related to: can someone > explain to me why this is safe? > > I've seen that OpenSSH 7.7 now implements something similar (xmss > hash-based signatures, > https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12, > disabled by default) but that works entirely differently from what is > proposed here; amongst other things, it uses *one time private keys* to > maximize security - do we want to add something like that to our TLS > stuff (my gut answer: no). > > How can a hash replace a public key, cryptographically speaking? if you > are not replacing public keys, then who generates, stores, maintains > these public keys? What about accounting in such a setup? with > certificates, you normally hand out a certificate to a person, with the > name of the person/entity in it. If that person misbehaves, you revoke > the certificate and presto. Is it sufficient to remove the hash from the > config? if so, wouldn't it be better to have a directory with > hash-files, so that you can add and remove hashes without having to > update the server config and/or restart the server to pick up new hashes? > When you sign a certificate you are actually singing the hash of the certificate. So you essentially are saying: "This certificate with the hash xxxyyy is trusted by my CA". Traditionally we used the MD5 of the certificate, then SHA1 and now SHA256 which we signed. (See the weak md5 discussion). The reason that the hash is signed instead of the public is that this way you are also signing the other properties of the certificate (e.g. CN, extensions, etc.). If you can the public key (or any other property of the certificate) also the hash of the certificate changes. If you just have a list of hashes that you trust you just cut out the middle man (the CA) that establishes the trust relationship for you. Arne ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi Arne, On 23/05/18 16:46, Arne Schwabe wrote: >> I have some strong thoughts on this, mostly related to: can someone >> explain to me why this is safe? >> >> I've seen that OpenSSH 7.7 now implements something similar (xmss >> hash-based signatures, >> https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12, >> disabled by default) but that works entirely differently from what is >> proposed here; amongst other things, it uses *one time private keys* to >> maximize security - do we want to add something like that to our TLS >> stuff (my gut answer: no). >> >> How can a hash replace a public key, cryptographically speaking? if you >> are not replacing public keys, then who generates, stores, maintains >> these public keys? What about accounting in such a setup? with >> certificates, you normally hand out a certificate to a person, with the >> name of the person/entity in it. If that person misbehaves, you revoke >> the certificate and presto. Is it sufficient to remove the hash from the >> config? if so, wouldn't it be better to have a directory with >> hash-files, so that you can add and remove hashes without having to >> update the server config and/or restart the server to pick up new hashes? >> > When you sign a certificate you are actually singing the hash of the > certificate. So you essentially are saying: "This certificate with the > hash xxxyyy is trusted by my CA". Traditionally we used the MD5 of the > certificate, then SHA1 and now SHA256 which we signed. (See the weak md5 > discussion). > > The reason that the hash is signed instead of the public is that this > way you are also signing the other properties of the certificate (e.g. > CN, extensions, etc.). If you can the public key (or any other property > of the certificate) also the hash of the certificate changes. > > If you just have a list of hashes that you trust you just cut out the > middle man (the CA) that establishes the trust relationship for you. > > I understand that part - it's how certificate pinning etc work. However, for a "regular" TLS connection (or any assymmetric encryprion scheme) you normally need a public key and a private key in order to establish a connection. However, with certificate pinning all you do is *ADD* an extra check, not replace a check. You will need and use both the public and the private key to establish security. How is this done in the proposed patch? JJK ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>> When you sign a certificate you are actually singing the hash of the >> certificate. So you essentially are saying: "This certificate with the >> hash xxxyyy is trusted by my CA". Traditionally we used the MD5 of the >> certificate, then SHA1 and now SHA256 which we signed. (See the weak md5 >> discussion). >> >> The reason that the hash is signed instead of the public is that this >> way you are also signing the other properties of the certificate (e.g. >> CN, extensions, etc.). If you can the public key (or any other property >> of the certificate) also the hash of the certificate changes. >> >> If you just have a list of hashes that you trust you just cut out the >> middle man (the CA) that establishes the trust relationship for you. >> >> > I understand that part - it's how certificate pinning etc work. However, > for a "regular" TLS connection (or any assymmetric encryprion scheme) > you normally need a public key and a private key in order to establish a > connection. However, with certificate pinning all you do is *ADD* an > extra check, not replace a check. You will need and use both the public > and the private key to establish security. How is this done in the > proposed patch? Private and public key are still used. The patch stil uses certificates and TLS, it only replaces the check certificate of the peer's certificate against the CA with a hash check (certificate pinning if you want). So basically instead of saying that you trust all certificates signed by a CA, you only trust only those certifcates of which have hashes. A certificate pinning of an unknown CA is exactly the same. Since you cannot verify that certificate you add a one off certificate in your list of trusted certificates. Arne ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
On 24/05/18 12:17, Arne Schwabe wrote: > >>> When you sign a certificate you are actually singing the hash of the >>> certificate. So you essentially are saying: "This certificate with the >>> hash xxxyyy is trusted by my CA". Traditionally we used the MD5 of the >>> certificate, then SHA1 and now SHA256 which we signed. (See the weak md5 >>> discussion). >>> >>> The reason that the hash is signed instead of the public is that this >>> way you are also signing the other properties of the certificate (e.g. >>> CN, extensions, etc.). If you can the public key (or any other property >>> of the certificate) also the hash of the certificate changes. >>> >>> If you just have a list of hashes that you trust you just cut out the >>> middle man (the CA) that establishes the trust relationship for you. >>> >>> >> I understand that part - it's how certificate pinning etc work. However, >> for a "regular" TLS connection (or any assymmetric encryprion scheme) >> you normally need a public key and a private key in order to establish a >> connection. However, with certificate pinning all you do is *ADD* an >> extra check, not replace a check. You will need and use both the public >> and the private key to establish security. How is this done in the >> proposed patch? > > Private and public key are still used. The patch stil uses certificates > and TLS, it only replaces the check certificate of the peer's > certificate against the CA with a hash check (certificate pinning if you > want). > > So basically instead of saying that you trust all certificates signed by > a CA, you only trust only those certifcates of which have hashes. A > certificate pinning of an unknown CA is exactly the same. Since you > cannot verify that certificate you add a one off certificate in your > list of trusted certificates. Correct me if I'm wrong, but this approach allows for self-signed certificates too, right?
Hi, > > Private and public key are still used. The patch stil uses > > certificates and TLS, it only replaces the check certificate of the > > peer's certificate against the CA with a hash check (certificate > > pinning if you want). > > > > So basically instead of saying that you trust all certificates signed > > by a CA, you only trust only those certifcates of which have hashes. A > > certificate pinning of an unknown CA is exactly the same. Since you > > cannot verify that certificate you add a one off certificate in your > > list of trusted certificates. > > Correct me if I'm wrong, but this approach allows for self-signed certificates > too, right? Exactly! Client and server can use whatever certificate they like or make a self-signed one. All they need to do is to exchange their fingerprints over some trustworthy channel. Simple. Like SSH. Best regards, Simon ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
On 25/05/18 09:41, Simon Rozman wrote: > Hi, > >>> Private and public key are still used. The patch stil uses >>> certificates and TLS, it only replaces the check certificate of the >>> peer's certificate against the CA with a hash check (certificate >>> pinning if you want). >>> >>> So basically instead of saying that you trust all certificates signed >>> by a CA, you only trust only those certifcates of which have hashes. A >>> certificate pinning of an unknown CA is exactly the same. Since you >>> cannot verify that certificate you add a one off certificate in your >>> list of trusted certificates. >> >> Correct me if I'm wrong, but this approach allows for self-signed > certificates >> too, right? > > Exactly! Client and server can use whatever certificate they like or make a > self-signed one. All they need to do is to exchange their fingerprints over > some trustworthy channel. > > Simple. Like SSH. As a side note, this approach might not need to disable the CA: a preliminary check against the trusted fingerprints can be performed and then fallback to the normal CA check in case of failure (but I'd make openvpn *clearly* log what is happening to avoid debug nightmares). Regards,
Hi, On 25/05/18 03:41, Simon Rozman wrote: >>> Private and public key are still used. The patch stil uses >>> certificates and TLS, it only replaces the check certificate of the >>> peer's certificate against the CA with a hash check (certificate >>> pinning if you want). >>> >>> So basically instead of saying that you trust all certificates signed >>> by a CA, you only trust only those certifcates of which have hashes. A >>> certificate pinning of an unknown CA is exactly the same. Since you >>> cannot verify that certificate you add a one off certificate in your >>> list of trusted certificates. >> Correct me if I'm wrong, but this approach allows for self-signed > certificates >> too, right? > Exactly! Client and server can use whatever certificate they like or make a > self-signed one. All they need to do is to exchange their fingerprints over > some trustworthy channel. > > Simple. Like SSH. > > for the record: this is not entirely the same as SSH. What happens when establishing an SSH connection to a new server is that you send the *public key* to the server, not a hash; similarly the server sends its public key to the client. The client needs to accept this new key, otherwise the connection is aborted. For public/priv authentication to work, the server must know the public key of the client (listed in the authorized_keys file) , otherwise the user is prompted for a password. Thus, for SSH a 'trustworthy channel' consists of the user typing 'y' when connecting to a new server and the server accepting a username+password upon first connection from a client. To implement a similar feature in OpenVPN would require a way to send only the public key upon TLS initialisation, and these public keys would then need to be stored/listed on the server somewhere. Probably possible, but a different approach then to what is proposed above. I'd be (slightly) in favour of sending public keys instead of hashes, BTW, as it them more closely mimicks what SSH does. JM2CW, JJK ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi, On Fri, May 25, 2018 at 9:51 AM, Jan Just Keijser <janjust@nikhef.nl> wrote: > Hi, > > On 25/05/18 03:41, Simon Rozman wrote: >>>> >>>> Private and public key are still used. The patch stil uses >>>> certificates and TLS, it only replaces the check certificate of the >>>> peer's certificate against the CA with a hash check (certificate >>>> pinning if you want). >>>> >>>> So basically instead of saying that you trust all certificates signed >>>> by a CA, you only trust only those certifcates of which have hashes. A >>>> certificate pinning of an unknown CA is exactly the same. Since you >>>> cannot verify that certificate you add a one off certificate in your >>>> list of trusted certificates. >>> >>> Correct me if I'm wrong, but this approach allows for self-signed >> >> certificates >>> >>> too, right? >> >> Exactly! Client and server can use whatever certificate they like or make >> a >> self-signed one. All they need to do is to exchange their fingerprints >> over >> some trustworthy channel. >> >> Simple. Like SSH. >> >> > for the record: this is not entirely the same as SSH. What happens when > establishing an SSH connection to a new server is that you send the *public > key* to the server, not a hash; similarly the server sends its public key to > the client. The client needs to accept this new key, otherwise the > connection is aborted. For public/priv authentication to work, the server > must know the public key of the client (listed in the authorized_keys file) > , otherwise the user is prompted for a password. Thus, for SSH a > 'trustworthy channel' consists of the user typing 'y' when connecting to a > new server and the server accepting a username+password upon first > connection from a client. > > To implement a similar feature in OpenVPN would require a way to send only > the public key upon TLS initialisation, and these public keys would then > need to be stored/listed on the server somewhere. Probably possible, but a > different approach then to what is proposed above. I'd be (slightly) in > favour of sending public keys instead of hashes, BTW, as it them more > closely mimicks what SSH does. Me too chiming in :) JJK, I think you are misreading this proposal. No hash is being sent as a part of the handshake -- its still client and server certificates that are exchanged and checked during handshake. The hash is exchanged by a separate channel (say snail mail:) in advance, and serves the purpose of establishing trust (ie., the prior knowledge of hash replaces the prior knowledge of a trusted CA). How the hash is exchanged is beyond the scope of openvpn or TLS handshake in this case. Selva ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi Selva, On 25/05/18 16:07, Selva Nair wrote: > On Fri, May 25, 2018 at 9:51 AM, Jan Just Keijser <janjust@nikhef.nl> wrote: >> On 25/05/18 03:41, Simon Rozman wrote: >>>>> Private and public key are still used. The patch stil uses >>>>> certificates and TLS, it only replaces the check certificate of the >>>>> peer's certificate against the CA with a hash check (certificate >>>>> pinning if you want). >>>>> >>>>> So basically instead of saying that you trust all certificates signed >>>>> by a CA, you only trust only those certifcates of which have hashes. A >>>>> certificate pinning of an unknown CA is exactly the same. Since you >>>>> cannot verify that certificate you add a one off certificate in your >>>>> list of trusted certificates. >>>> Correct me if I'm wrong, but this approach allows for self-signed >>> certificates >>>> too, right? >>> Exactly! Client and server can use whatever certificate they like or make >>> a >>> self-signed one. All they need to do is to exchange their fingerprints >>> over >>> some trustworthy channel. >>> >>> Simple. Like SSH. >>> >>> >> for the record: this is not entirely the same as SSH. What happens when >> establishing an SSH connection to a new server is that you send the *public >> key* to the server, not a hash; similarly the server sends its public key to >> the client. The client needs to accept this new key, otherwise the >> connection is aborted. For public/priv authentication to work, the server >> must know the public key of the client (listed in the authorized_keys file) >> , otherwise the user is prompted for a password. Thus, for SSH a >> 'trustworthy channel' consists of the user typing 'y' when connecting to a >> new server and the server accepting a username+password upon first >> connection from a client. >> >> To implement a similar feature in OpenVPN would require a way to send only >> the public key upon TLS initialisation, and these public keys would then >> need to be stored/listed on the server somewhere. Probably possible, but a >> different approach then to what is proposed above. I'd be (slightly) in >> favour of sending public keys instead of hashes, BTW, as it them more >> closely mimicks what SSH does. > Me too chiming in :) > > JJK, I think you are misreading this proposal. No hash is being sent > as a part of the handshake -- its still client and server > certificates that are exchanged and checked during handshake. The hash > is exchanged by a separate channel (say snail mail:) in advance, and > serves the purpose of establishing trust (ie., the prior knowledge of > hash replaces the prior knowledge of a trusted CA). How the hash is > exchanged is beyond the scope of openvpn or TLS handshake in this > case. > > no, I've heard a lot and talked a lot about this proposal before it ended up on the list. I do know what the purpose is, it's just that I have serious doubts about replacing ( pub/priv key plus 'trust anchors' such as CA certificates ) by ( we all trust each other because we know each other's SHA2 hashes ) There are downsides to a PKI with certificates but I think we're throwing out too much of the good stuff by allowing "just a hash" as the basis for trust. And one of my main concerns is that people keep comparing it to "that's just like how SSH does it" - *THAT* is simply not true. JM2CW, JJK ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi, > > JJK, I think you are misreading this proposal. No hash is being sent > > as a part of the handshake -- its still client and server > > certificates that are exchanged and checked during handshake. The hash > > is exchanged by a separate channel (say snail mail:) in advance, and > > serves the purpose of establishing trust (ie., the prior knowledge of > > hash replaces the prior knowledge of a trusted CA). How the hash is > > exchanged is beyond the scope of openvpn or TLS handshake in this > > case. Right to the point, Selva. This is the best description of this proposal. > no, I've heard a lot and talked a lot about this proposal before it ended up > on > the list. I do know what the purpose is, it's just that I have serious > doubts > about replacing > ( pub/priv key plus 'trust anchors' such as CA certificates ) by > ( we all trust each other because we know each other's SHA2 hashes ) > There are downsides to a PKI with certificates but I think we're throwing > out > too much of the good stuff by allowing "just a hash" as the basis for > trust. And one of my main concerns is that people keep comparing it to > "that's just like how SSH does it" - *THAT* is simply not true. JJK, I am sorry I brought SSH as an example. I didn't mean "exactly" like SSH. Just, "kind of like" SSH. In this proposal, we leave the TLS handshake to handle public key exchange as usual. No need to modify client<->server communication. The only difference is how server and client verify peer's certificate validity. Normally, they check peer's certificate fields like "Not valid before", "Not valid after", "Issued By" etc. In this proposal, they'd only check peer certificate by its SHA thumbprint - and skip all other standard certificate checks. This would allow you to have a CA-less OpenVPN setup: - Make self-signed certificate on server and each client (with like 100 years validity), - Deploy server certificate hash in client.ovpn, - List acceptable client certificate hashes in server.ovpn (Or use an external script to do the hash lookup) Best regards, Simon ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
What does this accomplish you can’t just basically do with —client-cert-not-required? Eric Crist > On May 25, 2018, at 3:56 PM, Simon Rozman <simon@rozman.si> wrote: > > Hi, > >>> JJK, I think you are misreading this proposal. No hash is being sent >>> as a part of the handshake -- its still client and server >>> certificates that are exchanged and checked during handshake. The hash >>> is exchanged by a separate channel (say snail mail:) in advance, and >>> serves the purpose of establishing trust (ie., the prior knowledge of >>> hash replaces the prior knowledge of a trusted CA). How the hash is >>> exchanged is beyond the scope of openvpn or TLS handshake in this >>> case. > > Right to the point, Selva. This is the best description of this proposal. > >> no, I've heard a lot and talked a lot about this proposal before it ended up >> on >> the list. I do know what the purpose is, it's just that I have serious >> doubts >> about replacing >> ( pub/priv key plus 'trust anchors' such as CA certificates ) by >> ( we all trust each other because we know each other's SHA2 hashes ) >> There are downsides to a PKI with certificates but I think we're throwing >> out >> too much of the good stuff by allowing "just a hash" as the basis for >> trust. And one of my main concerns is that people keep comparing it to >> "that's just like how SSH does it" - *THAT* is simply not true. > > JJK, I am sorry I brought SSH as an example. I didn't mean "exactly" like SSH. > Just, "kind of like" SSH. > > In this proposal, we leave the TLS handshake to handle public key exchange as > usual. No need to modify client<->server communication. > The only difference is how server and client verify peer's certificate > validity. Normally, they check peer's certificate fields like "Not valid > before", "Not valid after", "Issued By" etc. In this proposal, they'd only > check peer certificate by its SHA thumbprint - and skip all other standard > certificate checks. > > This would allow you to have a CA-less OpenVPN setup: > - Make self-signed certificate on server and each client (with like 100 years > validity), > - Deploy server certificate hash in client.ovpn, > - List acceptable client certificate hashes in server.ovpn (Or use an external > script to do the hash lookup) > > Best regards, > Simon > > ------------------------------------------------------------------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > Openvpn-devel mailing list > Openvpn-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/openvpn-devel <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">What does this accomplish you can’t just basically do with —client-cert-not-required?<br><br><div id="AppleMailSignature"><div style="direction: inherit;">Eric Crist</div></div><div><br>On May 25, 2018, at 3:56 PM, Simon Rozman <<a href="mailto:simon@rozman.si">simon@rozman.si</a>> wrote:<br><br></div><blockquote type="cite"><div><span>Hi,</span><br><span></span><br><blockquote type="cite"><blockquote type="cite"><span>JJK, I think you are misreading this proposal. No hash is being sent</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>as a part of the handshake -- its still client and server</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>certificates that are exchanged and checked during handshake. The hash</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>is exchanged by a separate channel (say snail mail:) in advance, and</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>serves the purpose of establishing trust (ie., the prior knowledge of</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>hash replaces the prior knowledge of a trusted CA). How the hash is</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>exchanged is beyond the scope of openvpn or TLS handshake in this</span><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span>case.</span><br></blockquote></blockquote><span></span><br><span>Right to the point, Selva. This is the best description of this proposal.</span><br><span></span><br><blockquote type="cite"><span>no, I've heard a lot and talked a lot about this proposal before it ended up </span><br></blockquote><blockquote type="cite"><span>on</span><br></blockquote><blockquote type="cite"><span>the list. I do know what the purpose is, it's just that I have serious </span><br></blockquote><blockquote type="cite"><span>doubts</span><br></blockquote><blockquote type="cite"><span>about replacing</span><br></blockquote><blockquote type="cite"><span> ( pub/priv key plus 'trust anchors' such as CA certificates ) by</span><br></blockquote><blockquote type="cite"><span> ( we all trust each other because we know each other's SHA2 hashes )</span><br></blockquote><blockquote type="cite"><span>There are downsides to a PKI with certificates but I think we're throwing </span><br></blockquote><blockquote type="cite"><span>out</span><br></blockquote><blockquote type="cite"><span>too much of the good stuff by allowing "just a hash" as the basis for</span><br></blockquote><blockquote type="cite"><span>trust. And one of my main concerns is that people keep comparing it to</span><br></blockquote><blockquote type="cite"><span>"that's just like how SSH does it" - *THAT* is simply not true.</span><br></blockquote><span></span><br><span>JJK, I am sorry I brought SSH as an example. I didn't mean "exactly" like SSH. </span><br><span>Just, "kind of like" SSH.</span><br><span></span><br><span>In this proposal, we leave the TLS handshake to handle public key exchange as </span><br><span>usual. No need to modify client<->server communication.</span><br><span>The only difference is how server and client verify peer's certificate </span><br><span>validity. Normally, they check peer's certificate fields like "Not valid </span><br><span>before", "Not valid after", "Issued By" etc. In this proposal, they'd only </span><br><span>check peer certificate by its SHA thumbprint - and skip all other standard </span><br><span>certificate checks.</span><br><span></span><br><span>This would allow you to have a CA-less OpenVPN setup:</span><br><span>- Make self-signed certificate on server and each client (with like 100 years </span><br><span>validity),</span><br><span>- Deploy server certificate hash in client.ovpn,</span><br><span>- List acceptable client certificate hashes in server.ovpn (Or use an external </span><br><span>script to do the hash lookup)</span><br><span></span><br><span>Best regards,</span><br><span>Simon</span><br><span></span><br></div></blockquote><blockquote type="cite"><div><span>------------------------------------------------------------------------------</span><br><span>Check out the vibrant tech community on one of the world's most</span><br><span>engaging tech sites, <a href="http://Slashdot.org">Slashdot.org</a>! <a href="http://sdm.link/slashdot">http://sdm.link/slashdot</a></span></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Openvpn-devel mailing list</span><br><span><a href="mailto:Openvpn-devel@lists.sourceforge.net">Openvpn-devel@lists.sourceforge.net</a></span><br><span><a href="https://lists.sourceforge.net/lists/listinfo/openvpn-devel">https://lists.sourceforge.net/lists/listinfo/openvpn-devel</a></span><br></div></blockquote></body></html> ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi, > What does this accomplish you can’t just basically do with —client-cert-not- > required? I am using --client-cert-not-required already. :) But that simplifies only the client half of the equation. TLS server will always need a certificate. And client will always need to verify it to prevent MITM attacks. So, you still need CA. The idea is to have a choice to drop CA completely. Of course, like JJK said: PKI is great and has its advantages. However, for small setups and some use-cases I'd be willing to live without it and have some simpler mean to validate mutual trust. Best regards, Simon ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Hi all, On 25/05/18 22:56, Simon Rozman wrote: >>> JJK, I think you are misreading this proposal. No hash is being sent >>> as a part of the handshake -- its still client and server >>> certificates that are exchanged and checked during handshake. The hash >>> is exchanged by a separate channel (say snail mail:) in advance, and >>> serves the purpose of establishing trust (ie., the prior knowledge of >>> hash replaces the prior knowledge of a trusted CA). How the hash is >>> exchanged is beyond the scope of openvpn or TLS handshake in this >>> case. > Right to the point, Selva. This is the best description of this proposal. > >> no, I've heard a lot and talked a lot about this proposal before it ended up >> on >> the list. I do know what the purpose is, it's just that I have serious >> doubts >> about replacing >> ( pub/priv key plus 'trust anchors' such as CA certificates ) by >> ( we all trust each other because we know each other's SHA2 hashes ) >> There are downsides to a PKI with certificates but I think we're throwing >> out >> too much of the good stuff by allowing "just a hash" as the basis for >> trust. And one of my main concerns is that people keep comparing it to >> "that's just like how SSH does it" - *THAT* is simply not true. > JJK, I am sorry I brought SSH as an example. I didn't mean "exactly" like SSH. > Just, "kind of like" SSH. > > In this proposal, we leave the TLS handshake to handle public key exchange as > usual. No need to modify client<->server communication. > The only difference is how server and client verify peer's certificate > validity. Normally, they check peer's certificate fields like "Not valid > before", "Not valid after", "Issued By" etc. In this proposal, they'd only > check peer certificate by its SHA thumbprint - and skip all other standard > certificate checks. > > This would allow you to have a CA-less OpenVPN setup: > - Make self-signed certificate on server and each client (with like 100 years > validity), > - Deploy server certificate hash in client.ovpn, > - List acceptable client certificate hashes in server.ovpn (Or use an external > script to do the hash lookup) > > this discussion has muddled along both off and on this mailing list. I apologize in advance for being nitpicky, but when touching the "core" security layer of OpenVPN I think we need to be very careful and express very carefully and precisely what it is we want to add/change/remove. As far as I can now oversee, what the original (off-list) proposal has boiled down (or watered down) to now, is 1. wouldn't it be great to allow users to specify self-signed certificates instead of having to use a full-blown PKI or CA certificate? For this, an option like "ca none" would useful, esp since this is explicitly allowed since the TLV v1.1 spec (before that, it was not clear whether it was allowed or not). Therefore, I tend to ACK the feature request to allow an 'empty' CA list, so that people can more easily use self-signed certs. Note that it currently is possible to come close to using self-signed certs, by creating CA certificates and use those as host/client certs as well (I will need to test this a bit further on different platforms, and I have no clue how mbedTLS likes this) 2. instead of storing a certificate on each side, wouldn't it be nice to be able to store the public key only of the certificate, or perhaps even a hash of the public key of the certificate? To me, storing either the certificate itself is not a problem (I recall Jason Donenfeld wanting to get rid of X509 certs altogether - something I strongly disagree with), but storing its public key should also be good - this mimicka SSH pub/priv key, so we could even re-use parts of the SSH code for this. One could even imagine getting the public key for a particular user out of his/her ~/.ssh/authorized_keys file. Then, to make things even shorter, it was proposed to add *hashes* of public keys of certificates. To me, the added value of using a 256 bit hash instead of a 1024/2048 bit pubkey is limited, and I would like some assurance that this indeed foolproof. Other than that, I wouldn't NACK this feature, as long as it remains optional. 3. how a person gets the public key or hash of the client or server side certificate to the "other side" is pretty much out of scope: it simply requires "a secure channel". I am fine with that. Note that browser certificate pinning is something else entirely: that is an *extra* check , on top of the cert chain check, to ensure that a server certificate (for, e.g. google.com) was signed by one of the "pinned" CA certificates. Browsers tend to trust a large number of CA certs, so this extra check makes sense there. As long as OpenVPN is not configured to trust 100+ CA's then this check does not make a lot fo sense in OpenVPN. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> > 2. instead of storing a certificate on each side, wouldn't it be nice to > be able to store the public key only of the certificate, or perhaps even > a hash of the public key of the certificate? > To me, storing either the certificate itself is not a problem (I recall > Jason Donenfeld wanting to get rid of X509 certs altogether - something > I strongly disagree with), but storing its public key should also be > good - this mimicka SSH pub/priv key, so we could even re-use parts of > the SSH code for this. One could even imagine getting the public key for > a particular user out of his/her ~/.ssh/authorized_keys file. > Then, to make things even shorter, it was proposed to add *hashes* of > public keys of certificates. To me, the added value of using a 256 bit > hash instead of a 1024/2048 bit pubkey is limited, and I would like some > assurance that this indeed foolproof. Other than that, I wouldn't NACK > this feature, as long as it remains optional. There seem to be some confusion about what is secure here and what not. I will give a bite more detailed example here to explain the pubkey vs hash check. Simplified a X509 looks like this: X509Cert { CN=foo.example.net PUBKEY=00:aa:bb:cc usage="TLSServer" other attributes } Signature { SigningCAHash=00:bb:cc SHA1Signature=binarysting } On a normal CA Check, the client will do a hash over the whole of the X509Cert (including CN and all other attributes). Then it will fetch the CA that signed the certificate, gets its public key and checks if the signature that is appended to the certifcate is valid and signs the hash it calculated before. The reason that we hash the whole certificate and sign the hash and also check the hash against the signature instead of the pubkey is that we want to have the other attributes to be validated as well. If we only signed the pubkey, a malicious party could just edit the CN of the certificate and the certificate would still be valid. What is proposed here is that instead of taking the signature of the certificate and checking if the signature sign that hash, we just look if we can find the hash in our list of trusted hash. I have not check the proposol in detail but if we implment something like this (especially with server side support), I would strongly suggest verify the hash/fingerprint of the certificate instead of using only the pubkey. Then there are no surprises for people that are not intimate with X509/SSL that client can fake the CN. > > 3. how a person gets the public key or hash of the client or server side > certificate to the "other side" is pretty much out of scope: it simply > requires "a secure channel". I am fine with that. > > Note that browser certificate pinning is something else entirely: that > is an *extra* check , on top of the cert chain check, to ensure that a > server certificate (for, e.g. google.com) was signed by one of the > "pinned" CA certificates. Browsers tend to trust a large number of CA > certs, so this extra check makes sense there. As long as OpenVPN is not > configured to trust 100+ CA's then this check does not make a lot fo > sense in OpenVPN. For self signed certificates checking the hash against the well known exception list (add this certificate as exception) also becomes the only check. Arne ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
On 04/17/2018 06:50 PM, Jason A. Donenfeld wrote: > * Allow specifying 'none' to the --ca parameter, to specify that > certificates should not be checked against a CA. Note that 'none' > is already used in other similar options as a special placeholder. > > * When '--ca none' is in use, --verify-hash checks all depths instead > of just level 1. > > With these very simple changes, fingerprint authentication is easily achieved > via the --tls-verify script on the server and via --verify-hash on the client. This is a great idea! I already played around with it, and it works as advertised :) I recently thought about how to integrate this properly. The thing that is still missing is using fingerprints as CNs. The --status command, and management interface (--management) use CNs to identify clients when certificates are used. This would then also need to be modified to use 'fingerprints' as identifiers so you would see the fingerprints when you use --status and can use fingerprints when you do "kill" through the management interface. An option similar to --username-as-common-name, e.g. --fingerprint-as-common-name could be introduced to accomplish this in an easy way, although it is a bit "hacky". Cheers, François ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
============ Make self-signed cert: $ openssl req -x509 -newkey ec:<(openssl ecparam -name secp384r1) -keyout key.pem -out cert.pem -nodes -sha256 -days 3650 -subj '/CN=server' Record our fingerprint in an environment variable for the client to use later: $ server_fingerprint="$(openssl x509 -in cert.pem -noout -sha256 -fingerprint | sed 's/.*=//;s/\(.*\)/\L\1/')" Start openvpn with tls verify script: $ sudo openvpn --server 10.66.0.0 255.255.255.0 --dev tun --dh none --ca none --cert cert.pem --key key.pem --tls-verify $(readlink -f tls-verify.sh) --script-security 2 TLS Verify Script: ================== #!/bin/sh [ -n "$tls_digest_sha256_0" -a -e "/tmp/allowed-openvpn-fingerprints/$tls_digest_sha256_0" ] Client side: ============ Make self-signed cert: $ openssl req -x509 -newkey ec:<(openssl ecparam -name secp384r1) -keyout key.pem -out cert.pem -nodes -sha256 -days 3650 -subj '/CN=client' "Tell" the server about our fingerprint: $ mkdir -p /tmp/allowed-openvpn-fingerprints; touch "/tmp/allowed-openvpn-fingerprints/$(openssl x509 -in cert.pem -noout -sha256 -fingerprint | sed 's/.*=//;s/\(.*\)/\L\1/')" Start openvpn with server fingerprint verification: $ sudo openvpn --client --remote 127.0.0.1 --dev tun --ca none --cert cert.pem --key key.pem --verify-hash "$server_fingerprint" SHA256 --nobind Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> --- Sorry for the double post. Somebody suggested I submit this as an actual git patch instead of as just part of the goofy email I sent earlier. So here's that email turned into a proper patch that you can apply. Feel free to hack the patch to pieces or discard it and start over. src/openvpn/init.c | 1 + src/openvpn/options.c | 9 ++++++++- src/openvpn/options.h | 1 + src/openvpn/ssl.c | 2 +- src/openvpn/ssl_common.h | 1 + src/openvpn/ssl_verify.c | 2 +- src/openvpn/ssl_verify_mbedtls.c | 2 +- src/openvpn/ssl_verify_openssl.c | 2 +- 8 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 36c1a4c4..4da994d8 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2722,6 +2722,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) to.remote_cert_eku = options->remote_cert_eku; to.verify_hash = options->verify_hash; to.verify_hash_algo = options->verify_hash_algo; + to.ca_file_none = options->ca_file_none; #ifdef ENABLE_X509ALTUSERNAME to.x509_username_field = (char *) options->x509_username_field; #else diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 426057ab..dad706d9 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -3259,7 +3259,10 @@ options_postprocess_filechecks(struct options *options) /* ** SSL/TLS/crypto related files ** */ errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->dh_file, R_OK, "--dh"); - errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca"); + if (!options->ca_file_none) + { + errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca"); + } errs |= check_file_access_chroot(options->chroot_dir, CHKACC_FILE, options->ca_path, R_OK, "--capath"); errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->cert_file, R_OK, "--cert"); errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK, @@ -7638,6 +7641,10 @@ add_option(struct options *options, { options->ca_file_inline = p[2]; } + else if (streq(p[1], "none")) + { + options->ca_file_none = true; + } } #ifndef ENABLE_CRYPTO_MBEDTLS else if (streq(p[0], "capath") && p[1] && !p[2]) diff --git a/src/openvpn/options.h b/src/openvpn/options.h index f7d0145a..6ccdca49 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -489,6 +489,7 @@ struct options /* TLS (control channel) parms */ bool tls_server; bool tls_client; + bool ca_file_none; const char *ca_file; const char *ca_path; const char *dh_file; diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 669f941b..0ef0f31f 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -693,7 +693,7 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx) } } - if (options->ca_file || options->ca_path) + if ((!options->ca_file_none && options->ca_file) || options->ca_path) { tls_ctx_load_ca(new_ctx, options->ca_file, options->ca_file_inline, options->ca_path, options->tls_server); diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 08ef6ffa..e9ac5271 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -270,6 +270,7 @@ struct tls_options uint8_t *verify_hash; hash_algo_type verify_hash_algo; char *x509_username_field; + bool ca_file_none; /* allow openvpn config info to be * passed over control channel */ diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 25395b27..61873e6f 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -720,7 +720,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep } /* verify level 1 cert, i.e. the CA that signed our leaf cert */ - if (cert_depth == 1 && opt->verify_hash) + if ((opt->ca_file_none || cert_depth == 1) && opt->verify_hash) { struct buffer ca_hash = {0}; diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c index fd31bbbd..147fb983 100644 --- a/src/openvpn/ssl_verify_mbedtls.c +++ b/src/openvpn/ssl_verify_mbedtls.c @@ -63,7 +63,7 @@ verify_callback(void *session_obj, mbedtls_x509_crt *cert, int cert_depth, cert_hash_remember(session, cert_depth, &cert_fingerprint); /* did peer present cert which was signed by our root cert? */ - if (*flags != 0) + if (*flags != 0 && !session->opt->ca_file_none) { int ret = 0; char errstr[512] = { 0 }; diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index 9b984751..10d351f4 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -66,7 +66,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) cert_hash_remember(session, X509_STORE_CTX_get_error_depth(ctx), &cert_hash); /* did peer present cert which was signed by our root cert? */ - if (!preverify_ok) + if (!preverify_ok && !session->opt->ca_file_none) { /* get the X509 name */ char *subject = x509_get_subject(current_cert, &gc);