Normally I would be extremely skeptical of a new TLS/SSL/crypto library, but this appears to be from Thomas Pornin, who definitely has the right crypto chops. Seems brand new but definitely something to keep an eye on.
Slightly off-topic, but I wished people would try other languages than C/C++ for implementing TLS. Ada, Rust, OCaml, Haskell, Go, etc. It would be really cool if one of those could break the barrier of “it needs to be in C”. Trading some of the their benefits for type/memory safety, etc. seems rather reasonable.
I know there are some libraries in stdlib in those and I know that Go probably isn’t the thing you want to call from other languages, but Rust for example appears to be a sane option for something that is a new implementation of something like TLS.
Is there something other than knowing the language that really would make you not want to have your TLS library written in Rust? Portability (mostly), size and performance seem to be less of an obstacle here.
And just to not sound like “C isn’t a cool language”. I mean it the way both Google and Mozilla build stuff parsers (Mozilla for video metadata) and renderers (Google for fonts) in Rust to avoid certain types of bugs.
To say something on the actual topic as well: I think it’s really great that the big libraries see some competition. Usually not having monocultures is a good thing and from experience it seems that different implementations make certain problems (design flaws and bugs) more obvious, even when other libraries implementing the same thing have them too.
miTLS is a great example of this, and it’s written in F*, which is a dependently typed version of F#. It’s interesting to see what MS & Inria are doing with this sort of thing.
Also, totally agreed wrt competition. It’s nice to see this corner of infosec getting some love (and I don’t even work in that domain generally).
Check this out:
I’d like to see SPARK and Rust, too. Haskell could probably be derived from miTLS given it compiles to F# or Ocaml. One drawback to high-level languages is one needs covert channel analysis for high-assurance security. That might be hard to do with them. Hence, me preferring things closer to how the assembly works like SPARK.
Yeah, can’t wait to run Haskell and Go on that microcontroller.
Sorry, but I actually did write that Go maybe isn’t a fit in most cases, while Rust might.
Also on a microcontroller you typically use smaller/different SSL libraries already. wolfSSL for example.
The cheapest ICs around these days are full ARM processors that can comfortably run Haskell or Go.
No, they aren’t. While 32-bit microcontrollers are common, most microcontrollers used in new project today have somewhere between 8 and 32kB of memory. Even 2kB are common.
OCaPIC runs on PIC18, so not exactly large.
Great, but OCaml is not Go nor Haskell.
And not everyone runs their software on a microcontoller. I used multiple examples and even wrote a paragraph about Go and Rust for exactly that reason.
Still you have OpenSSL, which also isn’t the typical microcontroller library and various other C implementations (forks such as LibreSSL and PolarSSL and GnuTLS). One would think that it would be a perfect ground for a language that has or claims to have certain guarantees. Yet the only bigger contenders are written in C.
I find the lack of dynamic allocation especially interesting. In what sort of situations would this be necessary?
As an example though, what sort of system requires SSL and does not allow dynamic allocation? Not questioning the purpose of the feature, just curious :)
It’s not about “not allowing dynamic allocation”.
Statically allocating everything is more predictable, since you don’t have to worry about e.g. heap fragmentation. It reduces some amount of security issues, like failing to handle malloc errors, and use-after-frees, and double-frees. It makes it impossible (ish) to have memory leaks, which can also be security-relevant. It makes it easier to write thread-safe code.
Ahhh, that makes a lot of sense. Thank you!
You don’t know how annoying it can be when a library uses something you don’t have in some corner you have backed yourself into. its easier to just be careful from the start.
I can imagine needing to use amazon IOT with client certificates on some bare metal platform for example.
for when you need your refridgerator to make purchases with a credit card
He wrote this book: http://www.prometheusbrother.com/ Which is interesting. All SSL hackers have very varied interests.
On top of embedded, they can be designed to use fewer resources if it’s a fixed-allocation scheme or easier to analyze. In terms of analysis, you might be able to do timing analysis for covert channel mitigation, same analysis for real-time situations, static analysis with tools like Astree Analyzer to show absence of critical errors, or whole app analysis showing it follow your policies in every successful or failed state due to determinism. Always go for static designs when you can. If you can’t, then mix the two so at least portions can be exhaustively shown to be correct with extra eyeballs on the dynamic stuff. Similar to mixing pure and impure components in languages like Ocaml.
Dumb CS question: if you restrict yourself to static allocation, are you Turing-complete?
Individual programs are generally not Turing-complete (what would that even mean?) - the question only makes sense for language implementations. (Admittedly any program that accepts input is in some sense a language implementation, but for something that just decrypts SSL not really).
A Turing-complete language implementation necessarily needs access to unbounded storage. In a sense such storage has to be “dynamic”, but it could e.g. use the C stack and potentially recurse to arbitrary depth (which I believe would qualify as “static allocation only” in the casual sense; it would be limited by stack size but you can set an arbitrarily large stack at runtime). Or use a fixed amount of memory and a file/database/etc. for storage.
Unless you are statically allocating an infinite amount of memory, no
…but this is true whether or not you restrict yourself to static allocation. There’s always an upper bound on memory on physical systems.
What do physical systems have to do with this? The same principle applies to Turing machines, you can’t simulate an arbitrary TM using a predetermined (finite) subset of the tape.
Stack machines with just one stack and no other storage are not turing complete. Turing completeness is not a requirement for certain algorithms, though and sometimes avoided, because non-turing completeness does allow for more interesting proofs about the program at hand (e.g. liveness).
Turing-completeness is also interesting because it is not hard to reach, making some things accidentally turing complete, such as Magic - the gathering.
Could I propose a moratorium on all new security-related software written in C?
What language would you suggest? This library targets embedded platforms. Correct me if I’m wrong, but I haven’t heard much about embedded Rust.
Coming, but we need LLVM targets and LLVM isn’t the best toolchain for a wide array small embedded targets currently.
There is usage of it, for example an operating system written for CortexM targets: https://github.com/helena-project/tock
Check out the rust-embedded GitHub org for a bunch of stuff related to embedded rust. It’s still early days but there’s tons of smart and motivated people working on it.
Rod Chapman at Altran/Praxis found an error in reference implementation of Skein just recoding it from C to SPARK. Ada and SPARK were invented for embedded systems. There’s also DSL’s like Galois' CRYPTOL, Ivory and Tower for embedded work that can generate correct, C code. Finally, COGENT is a functional, systems language that’s already been proven in a filesystem implementation with certified translation to imperative code. Dependently-typed languages like IDRIS and ATS are possible with ATS demo’d in device drivers and an 8-bit microcontroller.
Sensible subsets of C++ :)
The most sensible subset of which is actually C.
Nah, it’s Ironclad C++ or SaferCPlusPlus if you’re talking a subset that’s actually immune to all kinds of memory-related attacks with little work + has C++’s benefits.
There is embedded OCaml, ready to use (if you have a supported embedded platform, but this approach can certainly be extended to other platforms).
You could, but you would be silly to do so. There are tools that mitigate nearly all of the stupid of C…people just need the patience and discipline to use them.
That’s precisely the attitude that continues the status quo: “users are to blame, they need to be more disciplined”.
Those two comments are basically equivalent.
If somebody isn’t disciplined enough to follow best practices in C, they won’t be disciplined enough to follow best practices in any other language, either.
Compilers of more modern languages can be very disciplined and unforgiving of sloppy code.
And so can C compilers, with the added benefit that there are tons of static analysis tools like Lint and Coverity, etc., and it’s portable to far more platforms than anything else, and can easily be called by every other language.
If you want to nitpick other people’s language choice, at least make concrete complaints by pointing out the bugs in their code. “C can be unsafe, so this is bad,” doesn’t help anything and is just nitpicking for the sake of nitpicking.
And so can C compilers
Actually existing C compilers play an ad-hoc game of whack-a-mole with the most commonly exploited issues, that’s all. A C compiler that offers actual safety guarantees is vapourware. (There is principled tooling for languages that are supersets of subsets of C and are represented as C files subject to particular restrictions plus additional information, but these languages lack most of the advantages of C, e.g. they don’t tend to have a wide library or developer ecosystem).
with the added benefit that there are tons of static analysis tools like Lint and Coverity, etc.
They’re not a benefit, they’re a red flag that the language proper is inadequate. And again, all they offer is ad-hoc checks for the common cases. You can’t retrofit principled language design.
“C can be unsafe, so this is bad,” doesn’t help anything and is just nitpicking for the sake of nitpicking.
It’s not a nitpick. The language really is unsuitable for the project, and the project will fail as a result. I wish this weren’t so, but pretending it isn’t isn’t constructive.
Difference being one mistake in a common construct can lead to full, code injection in C where that’s rarely the case in the safe languages. The mistakes will happen. They’re usually more severe with C when they do. It’s intrinsic to how it was designed (or more accurately wasn’t) to handle safety of primitive functions & structures.
That’s just scare mongering, though. Mistakes can happen in any language.
The safety issues of C are well known to anybody who’s paying any attention at all. If a person chooses it for a new project anyway it’s safe to assume they know the downsides but have other reasons for using it. If you want people to use other languages, focus on those other reasons rather than harping on how they may hypothetically make a security mistake one day.
It really isnt scare mongering if even experts make these mistakes as regularly as they do. It means the average case will be much worse than it has to be. Putting an upper bound of damage from mistakes can prevent that. So it’s a good idea.
I’m not patient or disciplined enough to follow best practices if not following them would silently succeed (and on the available evidence neither is anyone else, even C experts). So I use languages that enforce best practices.
This position is undermined by that fact that I know of no security-sensitive C project in widespread use that is actually free of memory safety bugs. OpenSSL’s failures are well-known, but consider OpenSSH: it’s widely held as a high-quality security system, and yet had the roaming vulnerability earlier this year and several others before. If these were written in a safe language, there would still be bugs and crashes, but you would never run into the scenario where an attacker could leak arbitrary data out of a process, and you would never have to deal with with remote code execution vulnerabilities (barring things like web browsers where running attacker code is considered a feature).
A common argument against not-C in libraries is interop, since one of C’s legitimate advantages is it serves as a simple way to describe interfaces. This argument doesn’t hold much water though: consider this library binding, which lets you slot in an OCaml TLS implementation for any program that links against libtls. The only difference you’ll notice is the lack of panicked key-switching when Heartbleed 2 rolls around :).
thoughts on C-dialects like Low* and C-light?
The project includes a compiler for and sources written in something called T0. Is there any documentation on this?
It’s a forth-like language he wrote specifically for this. Docs are supposedly forthcoming.
I appreciate the pun.
written in C. It aims at offering the following features:
Be correct and secure
written in C. It aims at offering the following features:
Be correct and secure
Great to see that OpenSSL is now something people feel they can compete against.