This one has been on my mind for quite a while and finally I've managed
to get it going. Let's throw a security fuzzer into the breach and see
what it finds for us. (Oh boy, some crashes does it find! I've got 7 of
them reported in 5 minutes.)
Here we add "american fuzzy lop" because I like how little tweaking and
configuration it requires. Basically, you feed it an example input data
and it uses -- high technology from 1960s -- artificial intelligence (!)
and machine learning (!!) to work through big data queue (!!!) of tests
trying to invent ones that crash your application.
You can read user manual (of a sort) in the README. In order to run the
fuzzer you need to install it and then do "make fuzz FUZZ_BIN=something"
to build and run the tools.
Implementation-wise, we make a custom build of Themis (by recursively
calling make because that's the easiest way) which is instrumented by
a special compiler. This allows the fuzzer to monitor the behavior of
Themis and the tools and see how the input influences the control flow
in the program.
Only two tools are implemented for starters:
- Round-trip through a Secure Cell in sealing mode. This makes sure
that user input cannot be used to produce a secure container which
crashes the application during processing.
- Decrypting a presumable container with Secure Cell in sealing mode.
This makes sure that data corruption cannot cause the application
to crash when receiving messages encrypted with Secure Cell.
It should be easy to add more tools in the future. For example, Secure
Message could use a fuzzer for key files. Other components use the same
containers as Secure Cell so fuzzing the encrypted data may not be so
fruitful, but it may still be worth a shot.
I admit that error handling and memory management in the tools is a bit
sloppy but that should be fine unless it crashes in unexpected places.
It's just too verbose to do *everything* right.
Finally, we add a "make fuzz" step to the CI build in order to keep up
with API changes. We don't run the fuzzing automatically but let's at
least ensure that the tools can be compiled. (We can also check that
they can handle the input data but it's not *that* important.)