Point being, a Rust library that incorporates these type of safety measures can help significantly reduce programming errors beyond just memory safety issues.
Rust being higher level will prevent errors, yes, but crypto is hard on a whole other level. It's worth "waiting and seeing" what sort of vuln this is before jumping all in on the rust train this time ;-)
That's why I think it's worth calling this out.
Odds are, it's some dumb memory corruption thing. But we don't know yet. OpenSSL sev:hi tends to mean "dubiously exploitable crasher", and good crypto bugs in OpenSSL tend to be sev:med.
Pattern matching has nothing to do with security or program safety.
This is very helpful for not using cryptography libraries incorrectly, or not accidentally using the wrong data at different points of implementing functions.
Generally more applicable to higher level use cases, the ring[1] library is a great example of how the algorithms (same impls as OpenSSL) are exposed to end users.
The challenge in avoiding cryptography mistakes is that you have to understand the errors before you can avoid them. Short of formal analysis with provers, I don't think there's a level of programming rigor that gets you away from most (maybe any?) of the last 10-15 years of (say) {TLS,JWT} bugs.
Evidence of this nature will always be difficult, though, since it’s very difficult to prove a negative. We can only prove that some specific issue hasn’t yet occurred.
https://github.com/jedisct1/libsodium/blob/ae4add868124a32d4...
Edit: I'm not disagreeing that C compilers are free to optimize stuff like this out; this comment is for people who (like me) thought that serious projects always used assembly for constant time operations.
https://docs.rs/subtle/2.4.0/src/subtle/lib.rs.html#226-244 - the impl for [u8], where the per-element ct_eq is
https://docs.rs/subtle/2.4.0/src/subtle/lib.rs.html#259-272 - the impl for u8
(but then the compiler may still do other unrelated transformations that end up making the code non-constant time again)
You can do exactly the same in Rust. Rust isn't any help there, but it doesn't obstruct you either.
Edit: It can turn "b = foo(); c = (mask & a | ~mask & b)" into "if (mask) c = a; else c = foo();"