review

The disclosure of the recent GnuTLS vulnerability forces me, as if against my will, to retread some tired ground. It’s been a busy week. For serious this time.

This may stretch the definition of one week slightly, but here’s all the required reading.

Apple Secure Transport is not. #gotofail

If you choose to forgo Secure Transport on OS X, there are Apple OpenSSL surprises. Better is worse, or something like that.

GnuTLS fixed a bug by adding “goto fail;”.

As everyone should know, shaking three times considered harmful. Contains this sentence: “None of the mainstream TLS implementations performs a primality test.”

It’s not technically a new issue, but since it was posted recently as well, OpenSSL AES-GCM isn’t constant time on ARM. A variety of other bugs at the end of the post.



fail hard

When I was working on login_pushover, I noticed something about BSD auth. It requires affirmative confirmation. It’s not enough for the authenticator to exit successfully, it must write the string “authorize” to the reply channel. If some bug accidentally causes it to call exit(0) without printing anything, that counts as failure. In a way, it is its very own two factor auth. Status string and exit code.

I wouldn’t call this a coding style; it’s more a coding paradigm. And it’s one that TLS fails to adhere to at all levels, from internal implementation, to library API, to protocol. It’s far too easy to fly right by what should have been a hard error.



error diffusion

Another example. I just added a feature to do checksum verification in signify. It’s so not the unix way, when you could pipeline commands together. Indeed, that’s what the man page suggested to start.

$ signify -V -e -x SHA256.sig -m - | sha256 -C - bsd.rd (SHA256) bsd.rd: OK

Looks good. But what if something goes wrong?

$ (echo catastrophic failure; false) | sha256 -C - bsd.rd $ echo $? 0

No message, and successful exit.

There are two distinct problems revealed here. First, sha256 is all too happy to accept garbage and doesn’t indicate failure when it should. (This is our own damn fault. We added -C in response to -c being too strict.) But second, sh makes it unpossible to get the exit status from the front of a pipeline. The error is there, and then it’s not. In a nutshell, this is the Apple OpenSSL bug.



rules

Inevitably, the discussion turns to coding standards that would prevent these bugs. Perhaps the best known industry standard is MISRA C. I’m not a fan.

1. No trigraphs. Alright, great rule. But when is the last time you heard about a security failure caused by somebody using trigraphs?

2. No visually confusing variable names. It is a violation of the regulation to name two variables tls and t1s because they look the same. Alright, great rule. But who does this? I have never seen anybody do this outside of an obfuscated code contest. What I have seen is people mixing up inputLen and outputLen despite their clear as day names.

3. Source files must end with a newline. What? Never in the history of ever has a security bug been patched by adding a newline to the end of a C file.

This is some serious bean counter shit. “Do all your C files end in newlines?” Yeah, probably. “But how do you know? What is your process for ensuring compliance? When did you last test your process by trying to check in a file without a newline?”

I obviously think the every if must have braces rule is treading close to the above rules, although I’ll admit it’s not quite as outrageous. Why? If there is one computing resource which does not follow Moore’s Law, it’s vertical resolution. I need all the lines I can get.

When I program in Go, I use their required brace style. They want to reduce some of C’s oddities. I get that. But then I notice that the Go designers apparently realized what they’ve done, because they advocate a style like this to collapse vertical lines.

if rv , err := foo ( bar ) ; err != nil { return err; }

I’m not used to it yet, so that looks like a jumbled mess to me.

I’ve seen people contending that one should never use goto. I’ve also seen people contending that every function should only have a single return. I sincerely hope these two groups don’t work together. What a tangled mess of redundant conditionals their code would be.

I recommend considering the base rate fallacy. How many billions of lines of code use braceless if? More importantly, how many bugs will be introduced by mindlessly tossing braces into that code? (And yes, there’s so much code like this, the only way braces would be added is mindlessly.)

On the other hand, if you asked me which a novice programmer was more likely to screw up, if/goto or strcpy , my money is on strcpy every time. Yet entire generations of programmers on GNU Linux toil away without the benefit of strlcpy because real programmers don’t make mistakes. If you’re looking for a conspiracy, I recommend digging under this rock.



CERT

I came across a comment where somebody wrote that these problems wouldn’t happen if people followed the CERT C Coding Standard. I don’t have a strong opinion; some of it’s useful, some of it less so. I will, however, point out its guidance on using goto. The compliant examples are, modulo the bugs, exactly the code structure seen in GnuTLS and Secure Transport.



conspiracies

If I believed in conspiracies, I’d say the GnuTLS project conspired to make their patch include + goto fail; for ironic comedic effect.

What is the problem? One thing that’s suddenly become abundantly clear is nobody tests their TLS stack because nobody has a decent TLS testsuite. That looks suspicious, but when exactly did the the TLS stack I’m using is well tested thought appear in your head? What have you, concerned citizen, done about it? This weekend I watched Futurama: Into the Wild Green Yonder. “We can either chant slogans or we can take action!” ... “What was the first choice again?”