
Tox Handshake Vulnerable to KCI - zx2c4
https://github.com/TokTok/c-toxcore/issues/426
======
lvh
I'm the cryptographer (lvh on GitHub) providing some context on the issue. I'd
be happy to answer any other questions here, although I think the example on
the ticket demonstrates the attack pretty well.

The way you generally fix this is by providing appropriate binding between
long-term and short-term secret. MQV does this with some weird group-breaking,
but another way to do it would be, e.g.:

    
    
      session_key
      = H(l_A*E_B + e_A*L_B)           (as computed by Alice)
      = H(l_B*E_A + e_B*L_A)           (as computer by Bob)
    

Note: DON'T DO THIS! USE NOISE INSTEAD. This is just for insight; although
this how at least one of the KCI-secure AKEs works. H is a secure hash
function; l_X is X's long-term secret, e_X is X's ephemeral secret, L_X is X's
long-term pubkey, E_X is X's ephemeral pubkey. This works because the attack
doesn't simultaneously know e_A and l_B in this model. Off the top of my head,
ISTR this is how OTR's AKE works, but don't quote me on that, it's been a
while since I looked at OTR specifically. This is by no means exhaustive!
There are a handful of secure AKEs like this.

Another classic way to do this is by signing the handshake, but that has its
own share of problems. For example, the KCI attacks on TLS worked because an
certificate was being used as a static DH key.

~~~
runn1ng
I am not saying that as a defense of Tox. More as a question.

Why is KCI a vulnerability? Yes, I understand that the situation is reverse
from a normal crypto; but still, when your keys are stolen, you are screwed
anyway, your messages can be forged, it can lead to MITM, ...

How is that fundamentally so different from KCI. When someone steals your
keys, security doesn't apply anymore; how can a threat model include "but what
if someone steals the private keys".

~~~
lvh
"Screwed" is not a binary thing. Key compromise is not an unrealistic
scenario, here are a lot of things that can happen as a consequence. How bad
the consequences are matters.

Let me illustrate by examples:

Instead of KCI, consider forward secrecy. As long as the secret key is
maintained forever, you don't care about forward secrecy. However, we
generally agree that forward secrecy is a desirable property. If key
compromise doesn't matter, why does Tox bother to get forward secrecy? Because
the outcome of key compromise matters.

Instead of GCM, consider with something like CBC+HMAC-SHA256 and GCM-SIV or
HS1. All take some added data per encryption in addition to a key: either a
nonce or an IV. In the case of GCM, a nonce being reused is catastrophic
failure: trivial forgeries and quite probably ciphertext decryption. With the
other ciphersuites, there is some other failure, but nowhere near as bad. Yes,
you shouldn't have repeated the nonce, but the problem is that that happens,
and the question is how screwed you are when it does. Why do we care about NMR
crypto? Because the outcome of nonce reuse matters.

KCI is just another example. Yes, it only matters when something has gone
wrong. But there is a functional difference between "the attacker gets to
impersonate me" and "the attacker can pretend to be anyone to me" (KCI), just
like there's a difference between "the attacker can impersonate me" and "the
attacker can decrypt all communications, past and present" (PFS).

Just like PFS, not having KCI-resistance as a property is a choice. There is
no downside to having it. So, it is as much of a vuln as not having PFS would
be.

~~~
runn1ng
Thanks for a nice explanation. But I still can't see the functional difference
between

> "the attacker gets to impersonate me" and "the attacker can pretend to be
> anyone to me" (KCI)

Both seem similarly catastrophic to me in a real life scenario. I cannot
imagine a scenario when one is OK and one isn't. I don't see the hierarchy.

Also, thanks a lot for mentioning GCM-SIV to me! I like GCM, but the nonce
reuse is scary :)

~~~
lvh
It's not a tradeoff, so I don't think there needs to be a hierarchy. You
either have that vulnerability or you don't. It gives the attacker
significantly more power (instead of only being able to impersonate one
person, they get to impersonate an infinitude of them), and there is no
downside to preventing the attack.

~~~
makomk
By design, Tox uses NaCl rather than implementing its own crypto, largely due
to all the scary warnings from the crypto community about using NaCl rather
than implementing your own crypto. It appears to be impossible to prevent this
without abandoning NaCl and doing your own crypto. The supposedly misuse-
resistant library that experts have been telling everyone who'll listen to use
seems to inevitably create KCI vulnerabilities, and everyone's blaming the
people who listened.

~~~
lvh
You made the same point on GitHub, so I'm unsurprisingly going to give the
same answer here :)

Protocols aren't primitives. Secure primitives certainly do not imply secure
protocols (Example: AES is a secure block cipher, but AES-ECB is clearly not a
secure way to encrypt messages). Secure protocols mostly imply secure
primitives. (Counterexample: a protocol using HMAC-MD5 doesn't have forgery
issues even though MD5 is not a secure hash function.)

There are several levels of "homebrew" of "roll-your-own" cryptography:

\- Designing your own block ciphers or hash functions. \- Designing your own
compositions of primitives, like AE or MAC. \- Designing your own protocols,
like TLS or Noise.

This vulnerability exists on that third level. As a consequence, this isn't a
repudiation of NaCl or libsodium. They're excellent libraries. Curve25519 is a
DH primitive, and there's no DH vulnerability here. The problem is that it's
not an AKE, and that's what you're using it as. The docs clearly enumerate
what it does and does not do:

    
    
        Security model
    
        crypto_scalarmult is designed to be strong as a component of various
        well-known "hashed Diffie–Hellman" applications. In particular, it is
        designed to make the "computational Diffie–Hellman" problem (CDH) difficult
        with respect to the standard base.
        
        crypto_scalarmult is also designed to make CDH difficult with respect to
        other nontrivial bases. In particular, if a represented group element has
        small order, then it is annihilated by all represented scalars. This feature
        allows protocols to avoid validating membership in the subgroup generated by
        the standard base.
    
        NaCl does not make any promises regarding the "decisional Diffie–Hellman"
        problem (DDH), the "static Diffie–Hellman" problem (SDH), etc. Users are
        responsible for hashing group elements.
    

For example, this clearly states that you're responsible for hashing group
elements, which ostensibly the Tox AKE does not do. If you build an AKE, there
are other documented aspects of Curve25519 to consider; for example, some AKE
protocols require contributory behavior, which means that in Curve25519 you're
(exceptionally) required to consider representations of points of low order
(see [https://cr.yp.to/ecdh.html](https://cr.yp.to/ecdh.html)).

The claim that libsodium doesn't give you the tools to produce a secure AKE is
incorrect. Firstly, you can do a traditional signing key exchanges. Secondly,
Noise is a proof from construction; there are implementations of the Noise
protocol available on the site, and you'll see that it defines a KCI-secure
AKE that you can implement using nothing but NaCl/libsodium.

Finally, as much as I try to draw this conversation away from individuals and
towards technical discussion, I hope you'll find that I've tried pretty hard
both here and in general to provide constructive contributions, and trying to
educate those who'll listen. And, I tell people to consult a cryptographer,
although you could do a lot worse than NaCl as a set of solid primitives :)

If a chainsaw does a bad job of cutting an apple, it's not a bad chainsaw.

~~~
makomk
The scary warnings from cryptographers specifically pointed people at NaCl's
high-level APIs like crypto_box and warned of the dangers of rolling your own
compositions of primitives. You can do that just as well or badly with almost
any major crypto library, but the point of the NaCl advocacy was to steer
inexperienced people away from that towards higher-level constructions. So
that's what the Tox developers did: they used the high-level, safe, supposedly
misuse resistant crypto_box API's implementation of public-key authenticated
encryption. And it blew up in their faces, and then you accused them of
incompetently rolling their own crypto because, essentially, they didn't roll
their own crypto and the pre-baked version turned out to be horrifically
unsuitable for actual use. They do not use crypto_scalarmult directly
anywhere, and stuff like hashing group elements is done however DJB felt
appropriate when he was writing the high-level composition of primitives.

~~~
detaro
For context for other readers:

[https://nacl.cr.yp.to/box.html](https://nacl.cr.yp.to/box.html) and I assume
the relevant quote is _The crypto_box function is not meant to provide non-
repudiation. On the contrary: the crypto_box function guarantees
repudiability. A receiver can freely modify a boxed message, and therefore
cannot convince third parties that this particular message came from the
sender. The sender and receiver are nevertheless protected against forgeries
by other parties. In the terminology
of[https://groups.google.com/group/sci.crypt/msg/ec5c18b23b11d8...](https://groups.google.com/group/sci.crypt/msg/ec5c18b23b11d82c),
crypto_box uses "public-key authenticators" rather than "public-key
signatures."

Users who want public verifiability (or receiver-assisted public
verifiability) should instead use signatures (or signcryption). Signature
support is a high priority for NaCl; a signature API will be described in
subsequent NaCl documentation._

------
tptacek
In addition to being a really succinct and well-written summary of how KCI
attacks work and a good motivator for reading on modern AKE constructions like
SIGMA work, this is also kind of the best possible Github bug report; in
particular, I'm stealing this:

 _Is this an accurate representation of the handshake? If so, keep reading. If
not, you may safely stop reading here, close the issue, and accept my
apologies for the misunderstanding._

~~~
CiPHPerCoder
Jason's report was excellent and the discussion contributed by azet and lvh
was also very on-point.

In contrast, some of the Tox team's response makes me want to take up
drinking. The "crypto secret club gimmick" remark in particular.

~~~
iphy
Note that kebolio is in no way affiliated with Tox or TokTok, just a random
person contributing to the discussion.

I take full responsibility for everything I said, but I hope I don't need to
take responsibility for other people's posts. As nbraud (who is in fact a
contributor) noted, this has nothing to do with a secret club. I like to think
that all actual contributors are open for discussion and willing to learn what
they do not yet know.

~~~
CiPHPerCoder
> I take full responsibility for everything I said, but I hope I don't need to
> take responsibility for other people's posts.

I would never ask you to do so! Thanks for clarifying.

------
eeZah7Ux
"I found this source code confusingly written (and downright scary at times)
and the specification woefully underspecified and inexplicit"

People, please stay away from Tox.

~~~
snvzz
> People, please stay away from Tox.

By actually following the thread, I got the opposite idea. Its current active
developers are well aware of Tox's flaws, do actually know what they're doing,
and have a plan. They're being addressed.

This is a much better attitude than seen elsewhere (such as in Telegram).

And, in the first place, this is being overblown. As GrayHatter succintly puts
it:

> For anyone reading this, without a crypto background. The assertions being
> made are the same as saying: the lock on your house is broken because if
> someone steals your keys they can unlock your door.

~~~
lvh
I'm a cryptographer, and I replied to that issue on the ticket. The analogy is
flawed; and it later becomes clear that GrayHatter ostensibly didn't
understand KCI specifically.

[https://github.com/TokTok/c-toxcore/issues/426#issuecomment-...](https://github.com/TokTok/c-toxcore/issues/426#issuecomment-272524045)

~~~
grayhatter
Same grayhatter, here and there. In talking with another person who
understands the system, we both are unable to determine how that attack is
possible. Could you explain how, by stealing Alice's key, you could
impersonate Bob to Alice?

~~~
lvh
I'm writing this up, and then I realized I asked Jason to put an example in
his opening post, and I'm not sure I can do much better. In the original issue
description, there's an interaction where Mallory successfully dupes Alice. Is
there a specific step you feel doesn't work?

~~~
grayhatter
Sorry, I must have spaced out half way through writing that reply. I
originally intended to write something along the lines of, "How is the attack
solved by your example." I'm trying to wrap my head around the fix for this
attack without key signing. (Short of reading the source for noise)

~~~
lvh
Which example are you referring to? The HN comment with the AKE?

~~~
grayhatter
Your top comment on HN.

What's part am I missing that if we used hash(long_key pair + emp_key pair)
protects us if the long term is known by an attacker? Why couldn't the
attacker intercept the emp_keys.

I'm assuming there's no key signing done here.

------
doctorfoo
As a Tox user, I'd love to see some of these cryptographers calling it out
actually contribute lines of code. Tox fills a niche. It might not be
perfectly secure, but there is also far more to software than the crypto. UI
stuff takes a lot of grunt work.

Please, improve this. As a user I want Tox to be secure. But also, as a user,
I'll use it rather than Skype even if it does have some concerns. It's a
genuine, open source, Skype replacement that more-or-less works. The
encryption stuff is just the icing on the cake.

It would be a great project even with zero encryption.

/ramblerant

~~~
lvh
Specific recommendations for a different protocol that does not have this
concern were made, and a detailed bug report with repeated explanations of the
issue were provided. Why is the onus on me to also go fix the problem, when
it's repeated in the issue that the authors are mostly interested in
stabilizing the codebase first? (That is not a criticism, but rather: not only
do I not feel this is my responsibility, the way I read it, the maintainers
don't want that contribution right now.)

~~~
grayhatter
No, every Toxcore and Tox client welcome any contributions of any kind. Toktok
especially. The sentiment I think we were going for is that we don't have the
time when we're already working on the road map we started with.

I think it's a recurring comment (If you know the problem, why don't you fix
it), because it's really easy to drive by, shit all over someone's project
(that they've put a lot of time into) then move on, leaving everyone who still
cares about the project to feel shitty. This is in to way directed at you.
You've been nothing but helpful, supportive, and understanding! You're most
certainly one of the good ones. But not everyone else got that award for
today.

------
SlySherZ
Me and a friend of mine are discussing what the actual vulnerability is. What
I got from the report was that you can impersonate anyone when talking to A if
you have A's key.

He says that is impossible and you need B's key to impersonate B when talking
to A.

Could anyone that knows more about this than I do step in to clarify? Thanks!

~~~
aseipp
The trick is this: in a traditional DH based key exchange, you need A) your
private key and B) the other person's public key. Let's say your keypair is
a/A and my key is b/B (the lowercase identifier is the private key, the
uppercase one is the public key).

To do an exchange, you send me A, and I send you B. You compute the DH
exchange with B and a, and I compute it with A and b. The important property
of the DH function is that computing DH(B,a) is the same thing as computing
DH(A,b).

Now, if I steal your secret key 'a', I can do two things. One, I can obviously
impersonate you. But two, I can impersonate _anyone else_ , because I can
calculate the shared secret. The reason for this is that I need _your_ private
key, but I only need the other parties _public_ key.

Let's say you try to communicate with me now and someone has stolen 'a'. They
can already have my public key, B, because it is public. Thus, when the
exchange happens, you send me A. The attacker knows the secret key, 'a',
already. So the attacker can intercept the communication, calculate the DH
exchange of 'a' (which they stole) and 'B' (my public key), and they have
calculated the shared secret. It is not possible for you to tell you have
exchanged with the attacker, and not me. They never need _my_ private key,
only my public key, which will come through during the handshake. So it can
always be intercepted. Remember, DH(B,a) and DH(A,b) are the same, so if both
sides calculate DH(B,a), that's completely legitimate.

This is a very simplified view (and I haven't looked at the bug report in
detail, TBQH, so the case for Tox is probably slightly different), but it
explains why if your keys are stolen, anyone can be impersonated to you:
because the impersonator only needs public information (public keys) from that
point on to forge any exchange.

~~~
hexafluoride
Alright, how about this situation:

    
    
      Alice's long-term static keypair is S_A/s_a
      Alice's long-term static public key signature(signed by a trusted third party) is sign_A
      
      Bob's long-term static keypair is S_B/s_b
      Bob's long-term static public key signature(signed by a trusted third party) is sign_B
      
      Alice's per-session ephemeral keypair is E_A/e_a
      Bob's per-session ephemeral keypair is E_B/e_b
      
      Alice sends S_A|sign_A|E_A|sign(data=E_A, key=s_a)
      Bob sends S_B|sign_B|E_B|sign(data=E_B, key=s_b)
      
      Shared key is generated with kdf(ecdh(E_A, e_b)) == kdf(ecdh(E_B, e_a))
      
    

Would this be vulnerable to KCI?

~~~
lvh
No. This is roughly how TLS ephemeral suites work with mutual auth. Reusing a
key pair for signing and DH (or at least being able to) is why TLS KCI attacks
worked against static DH ciphersuites. Static DH certs basically don't exist,
but ECDSA does. The important distinction here is that the long-term keys are
signing keys, not DH keys.

------
EnjoyTomato
So if I'm understanding this correctly, this exploit is only possible if
someone gets a hold of your private key? This sounds more like an
academic/theoretical worry than anything that would concern the average user.
Realistically, if someone has your private key, you are compromised, end of
story. If damage mitigation is possible it should definitely be looked into as
a matter of principle, but trying to discourage people from using Tox or even
from developing it over such a tiny flaw seems like little more than
hubris/concern trolling. I'm sure it would look great on your blog or resume
to be able to say that you, the crypto expert, found a fatal flaw in a well-
established security project that forced it to shut down. Luckily it seems the
actual developers of Tox have more common sense than some of these "experts",
whose standards of perfection, if ever realized, would see that we all stop
using technology altogether.

------
zitterbewegung
A lot of these supposed "secure messaging" applications seem to roll their own
crypto systems and hope that is secure. And then there users seem to promote
the insecure protocol. I think we need to make a new word for this like
cryptohipster .

------
kevin_b_er
From the FAQ: "No, really, what's Tox? It's a VERY secure Instant Messenger
...."

So they acknowledged this is not true in their issue tracker, but not
publicly? Further, they internally claim they don't know what threats it
faces, don't understand what those threats are, and don't want to worry at
this time about what insecurity they have?

Also: "a largely undocumented, untested, and not well-understood code base of
about 19 ksloc (C)" from one of their own developers.

This is quite disappointing.

~~~
lightedman
You'll find that most 'secure' projects rely upon external marketing while
their internal tracking says otherwise.

Man can make it, man can break it.

~~~
iphy
I don't believe that marketing like that is the right thing to do. I want to
help people _be_ more secure, not just _feel_ more secure through some snake
oil security software. Because of that, we (in TokTok) have so far avoided any
marketing, and are purely focussed on making the Tox protocol we inherited
from the now mostly dormant Tox project properly secure.

