

Cryptographic Right Answers (2009) - bshanks
http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html

======
voltagex_
>Client-server application security: Distribute the server's public RSA key
with the client code, and do not use SSL.

I don't understand this part - if I'm not using SSL, what am I doing at this
point?

~~~
tptacek
Alone among these recommendations, this one is indefensible in practice
(though understandable on paper). We see people implementing "simpler" TLS
alternatives somewhat routinely in our practice, and they are virtually always
broken. A fear of TLS --- which is reasonable --- is an insufficient reason to
expose yourself to the risks of a custom crypto protocol.

You'll save yourself time and heartache if you just use SSL. Once every few
years, someone will find a flaw in TLS, and once every few times that happens,
that flaw will be relevant to your application. But on those rare occasions,
you'll also have some of the smartest crypto implementors on the planet
rushing to come up with the best fix, which is something you will never have
with a custom protocol.

It is worth remembering here that the overwhelming majority of TLS security
issues are relevant primarily to browsers, and rely on the BEAST exploit
model, where attackers have extensive and fine-grained control over what
plaintexts victims generate, due to Javascript.

If certificate processing code scares you --- also reasonable! --- and you're
building a client/server backend system, do what enterprise software does:
slurp the whole certificate into your code, fingerprint it with a hash, and
verify it in a whitelist. Your TLS implementation will still verify the
certificate, but you won't care; you'll rely on your whitelist for security
instead.

~~~
Retric
My advice is IMO much simpler. Feel free to write your own crypto code that
uses a SSL connection. It might not be secure on it's own, but in the small
windows where SSL happens to be broken you have a little extra security and
even if you just do XOR your still basically safe in the first place.

~~~
tptacek
You can actually end up _less_ secure by layering additional crypto inside of
SSL, particularly if (as is likely, given what most people are afraid of in
SSL) your crypto involves endpoint authentication.

What Colin wants to say in this document but couldn't at the time (because it
didn't exist yet) and won't now (because of false modesty) is that he thinks
you should use spiped instead of TLS. If he'd say that, I'd agree that was a
reasonable choice.

~~~
cperciva
No, don't use spiped. As awesome as it is, spiped is symmetric -- it's
designed for "I control two servers and want them to talk to each other
securely", _not_ for "I want to publish code which people can use to talk to
my server".

I've been considering writing aspiped though.

~~~
pja
NaCl? [http://nacl.cr.yp.to/](http://nacl.cr.yp.to/)

------
orthecreedence
Can anyone explain why GCM is more attackable than CTR+HMAC? Is it because the
signature is encoded in the ciphertext and can't be verified until some or all
of the decryption occurs?

~~~
tptacek
It's not, really, but the problem people are referring to is actually not too
hard to explain.

An HMAC authenticator is conceptually very simple. You start with a secure
hash (even MD5 still qualifies, barely, when we're talking about HMAC), and,
given a "key" and a "message", apply the hash function twice: an inner hash of
the key and the message, and an outer hash of the key and the inner hash (the
inner and outer hashes are distinguished by an "inner pad" and "outer pad"
constant). Doing this produces a secure message authenticator for a message
assuming the hash and key is secure (with SHA3, you don't even need HMAC, and
can create a secure authenticator out of a simple keyed hash).

You understand a secure hash, you understand what a keyed hash is (concatenate
the key and the message and now only people who know the key can replicate
that hash), and now you get what HMAC is.

GCM is CTR mode, like Colin says you should use with HMAC, plus a GHASH
authenticator. GHASH is a little trickier to understand than HMAC, but you can
get most of the way there by thinking of it as a thermonuclear CRC algorithm:
it's (at root) polynomial multiplication and reduction.

The problem with GCM is that fast polynomial multiplication and reduction in
software is table-driven. When software verifies a GHASH MAC, it is forced to
look up elements in a table at locations determined by a secret. Those lookups
end up configuring the system's cache; future memory references at addresses
that collide with the secret table indices will be measurably faster than
references that don't collide. Attackers can write software that profiles
cache hits and from that information potentially recover secrets.

Modern implementations of GCM on X64 hardware get hardware-accelerated
multiplication optimized for this operation, mitigating the table lookup
problem. But GCM is still potentially a concern for platforms that don't have
these instructions.

The plus side of GCM is that you'll never implement it yourself: it's gnarly
enough that everyone uses one of a few library implementations of it. As a
library interface, GCM is very nice: you're getting a "seal" and "unseal"
operation that securely verifies authentication and then handles decryption,
in the correct order of operations. On recent server hardware, that
implementation is likely not to have side channel problems; the same is
_rarely_ true of HMAC implementations, which tend (annoyingly) to be hand-
hacked, particularly for verification.

The "cool kids" replace GCM with Salsa20+Poly1305, which replaces AES-CTR with
a native stream cipher (Salsa20, which is actually a hash core running in CTR
mode) and a polynomial MAC that is very fast in secret-table-free software. If
you use Nacl, that's what you're getting; it's something much closer to GCM
than to AES-CTR+HMAC.

~~~
cperciva
_On recent server hardware, that implementation is likely not to have side
channel problems; the same is rarely true of HMAC implementations, which tend
(annoyingly) to be hand-hacked, particularly for verification._

Disagree. Hashes and HMACs are very safe against side channel attacks. Heck, I
don't think I could insert a side channel if I tried!

On a 1-10 scale of side channel attackiness, hashes and HMACs are 0, block
ciphers are 3-4, and asymmetric crypto is 6-8.

~~~
tptacek
Come on. You mean apart from virtually every web stack's implementation of
HMAC? They all start with a version that uses string comparison.

~~~
sillysaurus3
In case anyone is wondering the proper way to compare two HMACs, it's to xor
the strings and check whether the result is zero. If string A xor string B is
zero, then they're equal. If it's nonzero, then they're not equal. This will
prevent timing attacks, because the entirety of both strings are compared.

When you compare the two HMACs using standard string comparison, you expose
yourself to a timing attack because the algorithm will likely stop comparing
after finding the first difference in the strings.

~~~
cperciva
_In case anyone is wondering the proper way to compare two HMACs, it 's to xor
the strings and check whether the result is zero_

You've just punted the problem. How are you checking whether the result is
zero?

The correct code (copy and paste from libcperciva):

    
    
        /**
         * crypto_verify_bytes(buf0, buf1, len):
         * Return zero if and only if buf0[0 .. len - 1] and buf1[0 .. len - 1] are
         * identical.  Do not leak any information via timing side channels.
         */
        uint8_t
        crypto_verify_bytes(const uint8_t * buf0, const uint8_t * buf1, size_t len)
        {
                uint8_t rc = 0;
                size_t i;
    
                for (i = 0; i < len; i++)
                        rc = rc | (buf0[i] ^ buf1[i]);
    
                return (rc);
        }

~~~
TheLoneWolfling
A question.

What prevents a compiler from optimizing that function to non-constant time?
For example, by inserting a bailout condition (rc == 255) into the loop? (I am
aware that it probably wouldn't, but "probably" in cryptographic contexts
isn't generally good enough...)

~~~
cperciva
Theoretically? Nothing at all. You could have a compiler which produces code
which revs the CPU in such a way to output the complete works of Shakespeare
in Morse code via the fluctuations in your laptop's fan speed, and it would be
perfectly standard-compliant.

Worse than that, there's things compilers actually do in practice, like
optimizing away

    
    
        memset(sensitivedate, 0, sizeof(sensitivedata))
    

and you can't even protect yourself against that properly by using a (volatile
*) cast since the compiler is perfectly within its rights to make extra copies
of that data and even without optimization the memset will only zero one of
the copies. (gcc in particular loves to copy data onto the stack, due to a
broken register allocator.)

I've been trying to convince some clang developers that we need to have a C
language extension for "we're handling sensitive data here, don't optimize it
in dangerous ways", but it's difficult to define exactly what optimizations
could be problematic...

------
X-Istence
This is from 2009.

~~~
cperciva
And everything I said five years ago is still true! I'm proud of how well
those recommendations have stood the test of time.

~~~
tptacek
The past 5 years have not aged your aversion to elliptic curves very well. New
modern designs by crypto specialists tend to be curve based. Curves also have
a nice property in practice of tilting designs towards forward secrecy.

Naturally, we agree that devs shouldn't implement curves themselves --- but
then, neither should they implement RSA-PSS. The right answer is to use Nacl,
which is curve-based, but who cares? You're not interacting with that level of
the design.

~~~
cperciva
_The past 5 years have not aged your aversion to elliptic curves very well.
New modern designs by crypto specialists tend to be curve based._

The first of those statements does not follow from the second. I agree that
there has been an increase in the usage of elliptic curves; but I've also seen
a _lot_ more attacks on elliptic curves recently than on RSA or DH(Z_p).
Unless you have a particular need for small signatures (e.g., bitcoin) or
maximal performance, I maintain that using elliptic curves is an unnecessary
risk.

 _Curves also have a nice property in practice of tilting designs towards
forward secrecy._

I'm not sure why you say this. DH has exactly the same PFS properties
regardless of the group being used.

~~~
tptacek
Reverse order:

My claim about forward secrecy is easy to understand: ECC software doesn't
encrypt directly, but RSA software easily can, and developers (for instance:
Paul Kocher) give in to the temptation to use RSA encryption directly. RSA
practically begs developers to create systems that aren't forward secure.

There is a lot of new attack research on ECC. But how much of that research
implicates (a) common implementations of (b) the popular curves (NIST-Px,
secpx, and Curve25519)? Inquiring minds, who have been implementing a lot of
attack papers on artificially vulnerable curve software, want to know!

(Also, curve attacks that target DSA tend to be the fault of the DSA
construction. I'm guessing this isn't the level at which you're thinking of
curves being attack in the literature, though.)

~~~
cperciva
Wasn't there an ECC side channel attack in OpenSSL just a week or two ago?

As for the more theoretical research -- none of it has been relevant to widely
deployed systems _yet_ , but this is the nature of research. Elliptic curves
have a lot of structure which is still being explored, and as long as people
continue to find attacks against new variants, I'm not going to bet that
they'll never find attacks against the widely deployed systems.

I put being wary of ECC right now in the same category as being wary of SHA256
in 2006. It's not broken but there's a worrying amount of progress on related
systems.

~~~
pbsd
If you're referring to the recent FLUSH+RELOAD attacks, that is hardly ECC-
specific. They also owned GnuPG's RSA earlier with the same technique [1]. On
the other hand, if your argument is that ECC implementations are generally
less mature, I can't disagree with that. I believe that ECC (using Edwards or
Montgomery forms; debatable when using general Weierstrass form) is easier to
get right with respect to solid implementations than RSA is.

With respect to theoretical attacks, it is of course impossible to know what
the future brings. But as long as we're sticking with conservative prime
fields, I think it's probably either going to be fine or all of ECC is dead.
It's also not like integer factorization or discrete logs have reached some
kind of complexity lower bound; it's certainly not impossible that we'll get a
L(1/4) method in the future as well. I look forward to see how it plays out.

[1] [http://eprint.iacr.org/2013/448](http://eprint.iacr.org/2013/448)

~~~
cperciva
_It 's also not like integer factorization or discrete logs have reached some
kind of complexity lower bound; it's certainly not impossible that we'll get a
L(1/4) method in the future as well._

Not impossible, no. But the fact that people have spent much longer looking
for improved integer factorization attacks without making progress makes me
more optimistic that integer factorization will continue to hold up to further
scrutiny.

