Nice and everything, but I somehow cannot imagine people massively jump over it. Maybe it's superstitious, I dunno…
On the other hand, I undoubtedly agree that we should start making and deploying alternatives in more safe modern languages. In fact, I guess we should start step-by-step rewriting everything that's written in C/C++ and OpenSSL is a good thing to start with.
Crypto poses a unique challenge with the threat of timing attacks. A major benitif of using low level languages is that it is easier to assure that your code takes constant time regardless of the input.
So what candidates are there? While C may make it possible to write code that avoids timing attacks, a quick glance at [1] shows one must avoid memcmp and array lookups based on secret data, neither of which would be prevented by the compiler, and both probably similarly easy mistakes as heartbleed.
Can Rust compile to a shared lib the programs can use as easily as a C library? (I think the answer is "not yet", but I'm not sure? At least, I've seen projects for compiling Rust without any runtime library).
Today I learned this is possible with Ada [2], but it seems there is some boilerplate to start/stop the runtime. Does Ada provide the necessary low-level control to implement crypto?
Are there sufficiently strict dialects of C?
NaCl [1] says "There are an increasing number of cases where the C implementations and assembly-language implementations are automatically generated from code that was actually written in another language, such as CAO or qhasm."
CAO is a "a domain specific language for describing cryptographic software" [3], while qhasm [4] is a portable assembly seemingly not focused on safety.
Ada allows much more precise and standardised control of low level details than C or C++ do. You can, in a standardised way, define a record (struct) where the fields are a signed integer taking up 3 bits, followed by a 1 bit bool and then a 4 bit signed integer, followed by two 16 bit unsigned integers, and have them all packed in the order you've specified (including whether it is big or little endian), and only allowed to be used in the specific memory locations you've selected (think memory mapped control registers on a MCU). This is all part of the language spec. Not only that, if you want you can have a pointer (or access type) to that single bit bool if you need to (so obviously access types are more powerful than pointers because almost anything can be addressed, including things on remote machines if memory serves).
You also get the powerful feature of pre and post conditions being part of the language from Ada 2012 onwards, meaning you can even more precisely control what's happening. You can have types for potentially dangerous data and safe data that cannot be intermixed without being very explicit about it (something that would've avoided this bug if I understand it correctly).
I've said it in other threads, and it's worth saying again (as someone whose primary language is Haskell) Ada is absolutely the right choice for this sort of programming. It's just as low level, if not more so, as C, with all the high level constructs of C++ (well most anyway), it encourages writing safe code by making the safe easy and the unsafe hard, and has excellent open source tools backed by commercial compiler writers (AdaCore).
Can Rust compile to a shared lib the programs can use as easily as a C library?
Yes it can! You use the `#[no_std]` if you wish to be rid of the runtime, and the `#[crate_type = "lib"]` for outputting shared libraries (or use the `--crate-type` compiler flag).
To be clear, #[no_std] only "removes" the runtime by ensuring you don't accidentally use any functions that need the runtime. Something like
#![crate_id="basic_lib"]
#![crate_type="dylib"] // for a .so
/* not there's no `no_std` */
#[no_mangle]
pub extern "C" fn add_in_rust(x: i32, y: i32) -> i32 {
x + y
}
Compiling that will give a `libbasic_lib....so` which can be linked against by any C program, and the `add_in_rust` function called without the Rust code needing to touch a runtime. (I imagine that one may have to add some extra linker flags.)
There are many functions/types in libstd etc. that can be used without a runtime (although its still not as great as it will be in future).
Unfortunately, this means giving up the powerful Rust standard library and threads. Fortunately, third-party devs are creating a "zero-runtime" standard library that can be used in situations like this, and in embedded programming:
Right now, rust-core only provides basic collections and io, but more may be in the works. I suspect rust-core will eventually grow into a small but capable standard library.
rust-core has been coasting along in maintenance mode for quite a while now, because it was only intended as a temporary stopgap. Nobody really wants to fragment the community with a third-party standard library.
Instead, the Rust devs intend to restructure the standard library such that it has multiple profiles, and that you can jettison parts of it (such as the parts that require the runtime) without losing all of the other goodies. Here's the most recent RFC for doing so, filed yesterday: https://github.com/rust-lang/rfcs/pull/40/files
> qhasm [4] is a portable assembly seemingly not focused on safety.
When you start to worry about compiler bugs, hand written macro assembly isn't such a crazy idea for algorithms like SHA, MD5, RC4, AES. It is also easier to reason about timing in assembly. The truly paranoid would have to check compiler output anyways.
The truly paranoid worry that the processor will not execute instructions as they think it will. This ranges from timing irregularities from branch prediction and instruction re-order to bugs in CPU microcode or deliberate backdoors in the the design, or even the fab altering the mask to change the design.
https://eprint.iacr.org/2007/039.pdfhttp://www.cl.cam.ac.uk/~sps32/microsemi_re.pdf
With the downside being that things like Heartbleed become possible. Dealing with timing attacks in high-level code is not necessarily hard -- Haskell, for example, has strict evaluation.
I may err, but I don't really think it's that big issue. First off, "low level" isn't exactly synonymous to "efficient machine-code", I guess we well can expect from languages like Rust to become both efficient and predictable after a while. In fact, every non-lazy well designed static typed language implementation makes it very much possible to write code that compiles in pretty predictable way, so you can control execution time as well.
And the last, but not the least, timing attacks aren't chief vulnerability, really. If you expect a timing attack being real hazard you can randomize return time explicitly.
The problem is that a memory unsafe language leaves gaping holes. Protection against timing attacks doesn't help me if one can read my private keys (remotely!) with a simple Python script. Timing attacks at least require colocation in most cases and are much harder to implement and run for meaningful results. It's certainly worth thinking about how we can put memory problems to death in at least crypto code and imho C has proven to be a permanent problem in that regard.
I am still a (interested) Haskell beginner but whenever this discussion comes up the first thing I think is "why not try this in Haskell?" and I never give a thought that I would do this in Java which is my everyday language (and reasonably memory safe).
Why rewrite C and C++ parts? Just because someone doesn't program properly in one language doesn't mean you need to rewrite everything written in that language. Bit like throwing the baby out with the bathwater.
Because this type of mistake is easy to make in C and other programming languages make this class of bugs impossible. By moving the need for careful design from library to language implementation you get greater leverage in preventing bugs.
It isn't just accidental errors you need to worry about. Obfuscated intentional errors are a problem too. If the language design prevents bugs that an NSA mole would try to slip in, then that is a very good reason to rewrite in a new language.
On the other hand, I undoubtedly agree that we should start making and deploying alternatives in more safe modern languages. In fact, I guess we should start step-by-step rewriting everything that's written in C/C++ and OpenSSL is a good thing to start with.
I guess it's a good chance for Rust & friends.