What I read him as saying (and agree with) is that he's surprised that GnuTLS isn't tested against known-bad certificates in a simple integration test that doesn't require a Ph.D. to set up, as you imply.
What I read him as saying (and agree with) is that he's surprised that GnuTLS isn't tested against known-bad certificates in a simple integration test that doesn't require a Ph.D. to set up, as you imply.
The fallacy that you could have easily written a test case for this bug appears neatly encapsulates the weakness of "TDD" as a mitigation for programming flaws.
Your résumé is well-known around here and you don't have to set the terms of the discussion about every security-related issue on Hacker News, particularly when it's this heavy-handed and you get recognition upvotes. All I'm saying.
Him: Can't you test for this somehow? Even without TDD...
You: TDD is bad because math and wall of text.
Go read a book and realize why you can't, Web hacker.
Me: You jumped on TDD unnecessarily, there.
You: Now I'm going to redirect the argument to you!
You're browbeating anybody that comments here, rather unnecessarily, almost as a display of expertise. - Testing distributed cryptography is difficult.
- Read a book.
- You're a web developer and don't know the first thing about
testing TLS stacks, clearly.
- Testing does not improve systems security, as evidenced by
Ruby on Rails: Rails uses testing and it's insecure.
Seriously, re-read your comment. More than half of it is just unnecessary and dilutes what little point you've made into something unrecognizable in the snark.This is an important and valuable point. He wasn't discouraging new ideas, but rather pointing out how hard it is to make new ideas practical in the security arena.
It's hard to see how that test suite couldn't help improve the reliability (and therefore "reduce the insecurity") of said new implementation (say a library with only support for a subset of tls1.2 -- without any support for fallback).
Define "known-bad" in a general enough way that a specific test can be created to cover the entire range of "bad" certs. That's quite difficult, and, probably isn't realistically possible to go through all the "known-bad" if you want your tests to run quickly.
Realistically, all you can do is have regression tests to make sure that the found bugs aren't repeated in future releases.
Any known-bad cert at all would have been quite sufficient to catch this bug apparently. A simple ARE WE ACCEPTING BAD CERTIFICATES LOL sanity-check would have found it, which is the kind of unit test it should be possible to think of in advance rather than in response to a specific bug found earlier. A little can go a long way.
EDIT: Additionally, the difficulty of catching all bad certs is good reason to develop and continually update a torture-test of invalid certs (and valid ones) to test SSL clients against. The suite would be much too slow to check against once per recompile, but testing once before each point release should be useful enough...
Feature: *Certificate Validation*
In order to *keep NSA from reading my emai*
As a *TLS X.509 validation library*
I want *to never erroneously validate a certificate*
What are the "Scenarios"? Given: *???*
And: *???*
When: *???*
Then: *the certificate should be rejected*
Remember, if we're switching topics to the "goto fail" bug: that bug didn't affect every instance of certificate validation. You had to be in a particular set of ciphersuites.But I agree that you & I are better off not discussing things.
If you'd permit me a brief bit of my own concern trolling: I remember when I looked forward to reading your comments, several years ago. Now I see your nickname and say "bah, again?" What changed? Was it me or you?
Compared to that:
- Better unit testing is much easier to integrate into existing projects. Yes, it can only prevent a bug if the developer generally thought of the class of error, but at least it sort of forces them to spend some time thinking about possible failure cases, and can detect cases where their mental model was wrong. Also, it helps detect regressions: "goto fail" wasn't a strange edge case the developer didn't think of, it was a copy paste error which good unit tests could have caught.
- Functional testing can be independent of the implementation and written by someone unrelated. They can only do so much in general, but they might have caught both of these bugs.
Yes, audits are another option, but I'd say they should complement tests, not replace them.
ed: oh, and if you want to be really intellectually rigorous, you could try to formally verify your C code; model could have bugs but could also be implementation independent. But I hear that's rather difficult...
Stipulate that we're just talking about X.509 validation. (You can still have "goto fail" with working X.509, but whatever).
Assume we can permute every field of an ASN.1 X.509 certificate. That's easy.
Assume we're looking for bugs that only happen when specific fields take specific values. That's less easy; now we're in fuzzer territory.
Now assume we're looking for bugs that only happen when specific combinations of fields take specific combinations of values. Now you're in hit-tracer fuzzer coverage testing territory, at best. The current state of the art in fault injection can trigger these types of flaws (ie, when Google builds a farm to shake out bugs in libpng or whatever).
Does standard unit testing? Not so much!
Would any level of additional testing help? Absolutely.
But when we talk about building test tooling to the standard of trace-enabled coverage fuzzers, and compare it to the cost of adapting the runtime of a more rigorous language --- sure, Haskell is hard to integrate now, but must it be? --- I'm not so sure the cost/benefit lines up for testing our way to security.
For whatever it's worth to you: I totally do not think code audits are the best way to exterminate these bugs.
Also note that Haskell doesn't exactly help in avoiding timing attacks. In a sane cryptosystem, you might be able to implement AES, ECDSA and some other primitives in a low-level language and use Haskell for the rest; but as you know, TLS involves steps like "now check the padding, in constant time" (https://www.imperialviolet.org/2013/02/04/luckythirteen.html). You could certainly implement those parts in C, too, and then carefully ensure that no input to e.g. your X509 parser can consume hundreds of MB of memory, and so forth, but you're going to lose some elegance in the process. (Those problems would admittedly be smaller in OCaml, ADA or somesuch.)
I'd be more interested in something like Colin's spiped - competently-written C implementing a much simpler cryptosystem. If only because even a perfect implementation of TLS would still have lots of vulnerabilities. ;-)
(I think the case for writing applications in not-C is considerably stronger, if only because TLS stack maintainers tend to be better at secure coding than your average application programmer. Like you, I do like writing in C, though.)
I don't all together disagree with your points, however I'd like to pint out that Haskell has a great C FFI:
http://www.haskell.org/haskellwiki/GHC/Using_the_FFI http://book.realworldhaskell.org/read/interfacing-with-c-the...