mta.openssl.org uses an invalid security certificate.
The certificate is only valid for the following names:
*.opensslfoundation.net, opensslfoundation.net
The optics of this advisory are bad, of course, but these are probably not operationally important bugs for most people:
* DTLS segmentation fault in dtls1_get_record (only impacts people who use DTLS, and is a null pointer deref, which usually isn't exploitable)
* DTLS memory leak in dtls1_buffer_record (same, and only exhausts memory)
* no-ssl3 configuration sets method to NULL (a non-standard build produces a null pointer crash in SSL3 negotiation)
* ECDHE silently downgrades to ECDH (this looks like a server can in an oddball situation lie about forward secrecy --- also, this only impacts OpenSSL clients, like curl)
* RSA silently downgrades to EXPORT_RSA (a server can sabotage the security of a session, which it can do in a variety of other ways anyways --- also, this only impacts OpenSSL clients, like curl)
* DH client certificates accepted without verification (breaks client authentication, which not many people rely on, but only affects servers that (a) do TLS client auth and (b) trust DH-key-issuing CAs, which are "extremely rare and hardly ever encountered")
* Certificate fingerprints can be modified (this one I actually wonder about the sev:lo on; it's low because it doesn't impact browsers, but certificate blacklists are common in enterprise software)
* Bignum squaring may produce incorrect results (this is just weird)
That bignum one is weird. The patch suggests the character of it: something in the carry logic between 32-bit words, replicated for each assembly architecture as well as C. Here's the C version:
"Bignum squaring (BN_sqr) may produce incorrect results on some
platforms, including x86_64. This bug occurs at random with a very
low probability, and is not known to be exploitable in any way, though
its exact impact is difficult to determine. The following has been
determined:
- The probability of BN_sqr producing an incorrect result at random
is very low: 1/2^64 on the single affected 32-bit platform (MIPS) and
1/2^128 on affected 64-bit platforms.
- On most platforms, RSA follows a different code path and RSA operations are not affected at all. For the remaining platforms (e.g. OpenSSL built without assembly support), pre-existing
countermeasures thwart bug attacks [1].
- Static ECDH is theoretically affected: it is possible to construct elliptic curve points that would falsely appear to be on the given curve. However, there is no known computationally feasible way to construct such points with low order, and so the security of static ECDH private keys is believed to be unaffected.
- Other routines known to be theoretically affected are modular exponentiation, primality testing, DSA, RSA blinding, JPAKE and
SRP. No exploits are known and straightforward bug attacks fail - either the attacker cannot control when the bug triggers, or no private key material is involved.
[...]
This issue was reported to OpenSSL on 2nd November 2014 by Pieter Wuille (Blockstream) who also suggested an initial fix. Further analysis was conducted by the OpenSSL development team and Adam Langley of Google. The final fix was developed by Andy Polyakov of the OpenSSL core team.
"
The issue was that one of the carry propagation conditions was missed.
The bug was discovered as part of the development of libsecp256k1, a high performance (and hopefully high quality: correct, complete, side-channel resistant) implementation of the cryptographic operators used by Bitcoin, developed primarily by Bitcoin Core developer Pieter Wuille along with a number of other people.
Part of our testing involves an automatic test harness that verifies agreement of our code with other implementations with random test data, including OpenSSL; though to reduce the chance of an uncontrolled disclosure we backed out some of the low level testing after discovering this bug.
This randomized testing revealed the flaw in OpenSSL. I suppose it's also a nice example of statistical reasoning (p=2^-128 that a uniform input triggers the misbehaviour) doesn't itself express risk, since while we've put enormous amounts of CPU cycles into tests we've certainly not done 2^128 work. In this case the reason our testing revealed the issue was because we used non-uniform numbers specifically constructed with low transition probability to better trigger improbable branches like carry bugs (https://github.com/bitcoin/secp256k1/blob/master/src/testran...). I used the same technique in the development of the Opus audio codec to good effect.
(Whitebox fuzzing tools like Klee or AFL, or branch coverage analysis, while good tools, seem to not be as effective for errors where the code completely omits a condition rather than having a wrong condition which was not exercised by tests.)
In libsecp256k1 the field operations (nearest parallel, we don't use generic bignums) are augmented with proofs of correctness (e.g. https://github.com/bitcoin/secp256k1/blob/master/src/field_1... ) though only a small part of our provable correctness can be machine checked currently. Of course, correctness proofs are only one part of our strategy. Fortunately, because of the much smaller scope of libsecp256k1 we likely have an easier time hitting a higher level of assurance than OpenSSL does.
We were initially unsure how serious the bug was and came up with several sophisticated attacks that were fortunately prevented by OpenSSL not using its optimized squaring operation in all the places it could have used it.
Perhaps most interesting is that one of the reference implementations of curve25519 had almost exactly the same bug as OpenSSL: https://gist.github.com/CodesInChaos/8374632 but it seems to have gone largely without notice.
It's not really fair to indict this bug on OpenSSL's complexity. Over the last couple of years, both NaCl [1] and TweetNaCl [2] had carry propagation bugs not unlike the above. I'm surprised this kind of bug is not found more often.
I'm only not surprised because of the very poor state of software assurance in the industry as a whole. Indeed, the issue is not OpenSSL specific, similar bugs have been made elsewhere (and I assume also carried forward in "more audited" OpenSSL forks).
But thats the only reason I'm not surprised. Cryptographic code is safety/security critical and as an implementer (In my experience) the potential for this kind of error is very clear. This class of mistake can be found with a strong testing and verification strategy: it can be found with correctly targeted randomized tests (as was the case for this CVE), it can be found via manual review, or it can be found via formal methods.
Widely deployed, high value cryptographic code should be using all these techniques and producing publicly visible evidence of their use.
Of course, serious software issues aren't just cryptographic ones. Systems programming, as an industry needs to up its game. (And the common tropes of higher level languages to save everything is countered by examples like this: Software safety and correctness is more than memory safety. Higher level tools can be useful, but if they get in the way of really rigorous reasoning about the software they may be counter-productive.)
TLS is far too complicated with design-by-committee, special vendor extension sauce nonsense. Heck, the FIPS code was rushed and basically done at the behest of US/Canadian govts. OpenSSL should consider burning their deadwood and stop adding features until it gets its house in order.
There's no telling how large of an attack surface remains at the protocol level, in the codebase and with CAs being compelled to issue rogue certs for MITMs.
Moreover: Can TLS features be narrowed to focus on popular and high-value use-cases instead of SCTP, UDP, oh look a bird feature? It's fine for hacking on, but not production code. (If "TLS" is evolutionarily to "Perl," who's working on a "Python"?)
BTW: What ever happened to the cert WoT overlay 'moxie0 was working on?
It is true that TLS is part of the problem. But, it is also a widely deployed standard that cannot be changed overnight. That's why LibreSSL is necessary.
We need to build simpler protocols that make better use of cryptographic primitives, but first, we have to push back the tide. Eventually, TLS will be superseded by a better standard. But, this is something that even if started today with the most aggressive schedule would take 5 to 10 years to go industry-wide.
It was scaled back to TACK, a TLS extension that decentralizes certificate authority, which competed with HPKP, a similar but less ambitious standard; HPKP seems to have won. It's not optimal but it's progress.
I'm working on a research language with an extra set "explicit math operators" which expose carry in, carry out, etc. explicitly, and doesn't do type promotions and signals errors on under/ overflow.
"+!" If you want C-like behavior.
It'll be imperative with full dependent types as well.
Also interesting: cryptol, Irdis, coq, but the work is on making generic systems programming clear as possible in a static, imperative language without a titanic runtime or crawling along with superfluous assertions.
Carry bugs in limbed bignum code don't usually result in integer overflow (though integer overflow does usually mean the code is busted for sure). Part of the reason for this is that it's common to use 'overcomplete' representations where the limbs are smaller than the underlying type so that multiple operations can be performed before propagating the carries all at once.
This class of error is very much behind all the noise making I did at the Rust development team about treating integer overflow as a first class cause of software disaster as much as they have memory safety. Fortunately, they seem to be moving off the everything-wraps and wrapping-is-always-fine position.
I'm unable to compile this on Win32 (I don't have any problems compiling older versions). I don't understand how the code could compile for anyone, maybe it's a platform specific issue. Take a look here on line 80:
The variable cflags isn't defined. I suspect it should be CFLAGS. I can make it compile locally by changing that, and it would make the code in the function consistent with the other code in the same file.
I thought C defines were case sensitive on all platforms. Anyone knows better than me?
You have to keep in mind that OpenSSL runs several Perl scripts as part of its build process. And it's one of these scripts that generates a header which defines the cflags variable:
I can compile the previous versions. I've used the same script for several years, and its not until this version today I have an issue. When seeing the issue, I actually tried compiling the old versions again and those still worked.
It would seem odd if they actually change the build process in a security patch, right? The instructions on how to build OpenSSL on Windows has not been changed in 2 years.
> It would seem odd if they actually change the build process in a security patch, right?
No release of OpenSSL has ever been "the previous release plus the minimal patches for a security fix". This isn't a security patch. It's a new release that happens to include some security patches.
It's a security patch in the sense that the only way to get the security patches is to install the new version.
But thanks for the info. That seems like a pretty bad practice when it comes to a lib such as OpenSSL. Having to do changes to the build process to integrate an urgent security fix seems less than optimal.
While this particular vulnerability in OpenSSL isn't nearly as bad as some of the other recent ones, it drives me crazy that we still have NULL pointer dereferences in something this critical. The worst part of this library is that the way it is organized makes it difficult to find these problems, or to use tools such as static analyzers to help. There are some amazing static analysis tools out there for C, but they are rendered useless by some of the hackery used in this library, such as their custom allocators. I don't mean to sound negative -- the OpenSSL team has done a great job making this library available in the first place -- but given how heavily this library is relied upon, better discipline is needed in this code base.
LibreSSL is a step in the right direction, and I commend the OpenBSD team for taking on this alternative. However, it's only a starting point. The entire approach of OpenSSL is dated, and it has not done a good job keeping up with our modern understanding of solid security engineering. The code base needs to be overhauled from the ground up with modern security and software development practices in mind. If ever there were a library that should be designed using formal proofs in software, it's this one. Even basic TDD with good code coverage would catch the majority of the bugs that have been discovered in OpenSSL over the past ten years.
I did not realize that one must have money to voice an opinion.
Yes, I have money. No, it wouldn't be a wise investment to throw it at OpenSSL. Some problems are subtle enough that merely throwing money at them won't make them go away. I also have the requisite talent and experience to make a sizable dent in rectifying the problems I have expressed in this library. However, that is also useless unless attitudes around the project are shifted so that such efforts would be maintained.
Fixing the project requires changes at the very top of their organization all the way down. At this point, nothing short of a fork -- which OpenBSD has done with LibreSSL -- may be enough to drive this sort of change. Which is, not coincidentally, why I donate money to the OpenBSD project.
LibreSSL, once it is mature, may be a good launching point for some of the ideas I have expressed here. However, I would have to see how that code base matures before making such a determination. It's a largely meaningless exercise unless people start moving to that library and away from OpenSSL.
My point is that it's trivially easy to call for something to be done. It's easy to ask other people to do things, especially when it requires nothing whatsoever of you.
This approach is notorious for not producing good software.
Rust would also eliminate these bugs, as a class. And Rust has inline asm, for those cases where you need platform specific. Finally, Rust van export a C ABI library, so you could make a drop-in replacement.
It absolutely would not eliminate CVE-2014-3570 or many other of the cryptographic bugs that show up in OpenSSL and other TLS implementations.
This kind of axiomatic thinking that memory safety equals all safety almost resulted in Rust being less safe (IMO) than C in these other respects: the normal types in rust are all defined to overflow even though overflow is almost always a bug, and so you couldn't use static analysis on arbitrary rust codebases to warn you about these issues (where you can in C because signed overflow is undefined, so an analysis tool can always flag that as an error without it being a false positive). Fortunately, it sounds like Rust is moving to fix this ( http://discuss.rust-lang.org/t/a-tale-of-twos-complement/106... ), which is a big improvement.
But it's important to not be fuzzy about the risks. There is a well established link between safety equipment and risky behavior in driving and bicycling; (http://en.wikipedia.org/wiki/Risk_compensation). I don't mean to suggest that better isn't better and we shouldn't use safer tools, but if our response to safer tools is to lower our vigilance, even the slightest, we may get worse results.
I agree with this assessment. There is nothing inherently wrong with C. While alternative languages have certain advantages, there are clear reasons why core foundational libraries like OpenSSL are written in C: portability, age of the code base, knowledge of the contributors, etc.
While I would personally like to see a pragmatic move towards C++ in many of these low level libraries for some of the additional type safety and mechanics the language provides, this is a normative idea only, and I am under no delusion that it would necessarily result in better code. Good software transcends language.
I would, however, like to see enhancements to the style of code being written in this library so that tools like static analyzers and contract verifiers can provide meaningful results. A craftsman is only as good as how well he/she can make use of the available tools. Much of OpenSSL defies analysis, which is why the more bone-headed of these vulnerabilities, such as Heartbleed, are so hard to find.
It's impossible to eliminate all bugs. But, it is possible to build code in such a way that when there is the suspicion of a bug, one has a fairly good idea of how and why it is occurring. It is also possible to structure code -- even C and assembler -- so that it's easier to read and analyze, be this by eye or using tools. Finally, it's possible to structure code so that automated unit testing provides meaningful results regarding boundary conditions and contracts between functions. This latter point isn't meant to find bugs on its own, but rather to codify the more subtle bits of contracts between functions and data structures in a defensive way to ensure that future patches -- like the one that caused Heartbleed -- don't stomp on assumptions made in software.
Let me assure you that this is true regardless of language or platform.
I've done vulnerability analysis on codebases written in C++, Java, C#, Objective C, Ruby, and Python. I've found bugs in each of these platforms. The biggest differentiator I found was experience. More experienced software developers, on average, made fewer bugs resulting in vulnerabilities than less experienced software developers.
There is no magic language or platform that makes writing secure software easy. There are tools, techniques, and training that can help. But, these can only help. Writing quality software -- of which security is an important part -- is a difficult process that requires a lot of experience and discipline.
Please point to the CVEs for the plethora of remote code execution bugs in apps written in Java and C#, for instance.
I went through every single security bulletin MS published over the past couple years. The vast majority of the serious ones were 100% due to memory safety issues. The biggest exception was due to trying to sandbox arbitrary code (their .NET equivalent to Java applets).
If you have some counter-evidence, showing C to be even remotely as safe as, say, Java, please step forward. If you are actually saying "Well I found a lot of SQL injection bugs in code written in Java", that's a different issue. And I'm sure you're aware of it.
There's probably a name for the use of rhetoric of the form "Nothing's perfect. Therefore X and Y are just as good, since they are both imperfect."
Luckily, I don't have to respond by your goalposts.
You are hammering on a single class of security vulnerability out of hundreds of potential vulnerabilities. How does Rust prevent a confused deputy vulnerability? How about SQL Injection? Okay... well, what about all of the potential side channel attacks?
People in higher level languages tend to believe that the relative safety of their position means that they have to be less vigilant about vulnerabilities. That is often what I have found. The number of vulnerabilities overall were similar, but the type of vulnerabilities were different. Because there was a completely mistaken belief that these platforms were "more secure", security practices were often sloppy. Most of these vulnerabilities were at the application level. So, looking for Microsoft CVEs isn't going to help you.
The C++ code bases tended to have more senior level people working on them, who were more careful about both defects and vulnerabilities. Code bases in higher level languages, in general, had more junior level people working on them. Largely, the number of vulnerabilities were similar.
Again, I'm speaking of my own experience. But, I think that many researchers in the field would give you a similar story. I'm always wary of people promising silver bullets over hard work.
So by your own logic, if experienced C++ developers wrote in, say, Rust, they would not make mistakes like SQL injection, and they wouldn't be making all the memory-safety mistakes, either.
Edit: If your overall point is that systems are laughably insecure, and most app devs just leave gigantic holes open, sure, great. But let's not compound that by making their OSes and low-level network stuff run arbitrary code for anyone on the Internet.
It's not nearly that simple. Look, I get it: you're a fan of Rust. That's great. Use whatever language floats your boat.
But, it takes more than language features to solve security issues. Memory vulnerabilities are only a small piece of the wide range of potential defects that exist in software. These are also defects that largely go away with training and experience.
I can teach most C / C++ developers how to manage memory and pointers in a way that avoids all of the pitfalls that Rust is designed to prevent. It is absolutely possible to write reasonably secure software in most general purpose programming languages. This is true for C, C++, and even Rust. Don't believe me? Spend some time studying the formal proof behind the se implementation of L4, written in C.
All of this being said, I am a big fan of high-level languages. For my personal work, I write 80% of my software in Literate Haskell and around 20% in a lower level language like C++. But, I also understand the limitations that comes with abstraction, and they are big. System level code operates under a lot of constraints, and the abstraction that come with "safe" languages can come at the cost of this code working at all.
A good software engineer uses whichever tool he / she needs to build good software. If the process is followed, then there is no reason why we can't have an ecosystem that uses whichever languages are best for the problem. For most system level stuff, C/C++ are perfectly fine. If you want to use Rust, great. But, don't delude yourself into believing that your language choice trumps good engineering practice. It never will. Don't believe me? Write some software that can work around the Halting Problem in Rust, and get back to me. Because, that's the sort of intelligence you would need in a compiler or a tool to replace good practice.
If you can teach people how to write safe C code, you should setup a site and rake it in. Meanwhile, Mozilla, Microsoft, Google, and others have tried to build safe applications and simply fail due to memory safety issues. When such high profile teams cannot deliver, then at some point you gotta say "hmm, maybe the language is at fault".
I understand you like C/C++ and want to point out that if people delivery on a superhuman effort, then we can have nice things. Meanwhile, in reality, so far, this just doesn't happen. Lemme know when we can go a year without a memory safety issue getting tons of systems owned.
When Rust has been around long enough, and people have started adopting it, then we'll see vulnerability reports in systems developed in Rust too. As I said, there are no silver bullets in security.
52 comments
[ 4.1 ms ] story [ 113 ms ] threadAnd for future releases, it may be worthwhile to watch this URL to find unpatched vulnerabilities:
https://github.com/openssl/openssl/compare/OpenSSL_1_0_1k......
;)
Oh, whew!
https://mta.opensslfoundation.net/pipermail/openssl-announce...
1.0.2 includes important fixes (e.g. support for ALPN which is mandatory in HTTP/2, adds support for cross-root certificate validation).
* DTLS segmentation fault in dtls1_get_record (only impacts people who use DTLS, and is a null pointer deref, which usually isn't exploitable)
* DTLS memory leak in dtls1_buffer_record (same, and only exhausts memory)
* no-ssl3 configuration sets method to NULL (a non-standard build produces a null pointer crash in SSL3 negotiation)
* ECDHE silently downgrades to ECDH (this looks like a server can in an oddball situation lie about forward secrecy --- also, this only impacts OpenSSL clients, like curl)
* RSA silently downgrades to EXPORT_RSA (a server can sabotage the security of a session, which it can do in a variety of other ways anyways --- also, this only impacts OpenSSL clients, like curl)
* DH client certificates accepted without verification (breaks client authentication, which not many people rely on, but only affects servers that (a) do TLS client auth and (b) trust DH-key-issuing CAs, which are "extremely rare and hardly ever encountered")
* Certificate fingerprints can be modified (this one I actually wonder about the sev:lo on; it's low because it doesn't impact browsers, but certificate blacklists are common in enterprise software)
* Bignum squaring may produce incorrect results (this is just weird)
Can anybody locate in the sources the lines that correct this (before/after)? I'd like to learn from the error.
If you were wondering whether OpenSSL code has really gotten too complicated, wonder no more.
Full patch: https://github.com/openssl/openssl/commit/e078642ddea29bbb6b...
"Bignum squaring (BN_sqr) may produce incorrect results on some platforms, including x86_64. This bug occurs at random with a very low probability, and is not known to be exploitable in any way, though its exact impact is difficult to determine. The following has been determined:
- The probability of BN_sqr producing an incorrect result at random is very low: 1/2^64 on the single affected 32-bit platform (MIPS) and 1/2^128 on affected 64-bit platforms.
- On most platforms, RSA follows a different code path and RSA operations are not affected at all. For the remaining platforms (e.g. OpenSSL built without assembly support), pre-existing countermeasures thwart bug attacks [1].
- Static ECDH is theoretically affected: it is possible to construct elliptic curve points that would falsely appear to be on the given curve. However, there is no known computationally feasible way to construct such points with low order, and so the security of static ECDH private keys is believed to be unaffected.
- Other routines known to be theoretically affected are modular exponentiation, primality testing, DSA, RSA blinding, JPAKE and SRP. No exploits are known and straightforward bug attacks fail - either the attacker cannot control when the bug triggers, or no private key material is involved.
[...]
This issue was reported to OpenSSL on 2nd November 2014 by Pieter Wuille (Blockstream) who also suggested an initial fix. Further analysis was conducted by the OpenSSL development team and Adam Langley of Google. The final fix was developed by Andy Polyakov of the OpenSSL core team. "
The bug was discovered as part of the development of libsecp256k1, a high performance (and hopefully high quality: correct, complete, side-channel resistant) implementation of the cryptographic operators used by Bitcoin, developed primarily by Bitcoin Core developer Pieter Wuille along with a number of other people.
Part of our testing involves an automatic test harness that verifies agreement of our code with other implementations with random test data, including OpenSSL; though to reduce the chance of an uncontrolled disclosure we backed out some of the low level testing after discovering this bug.
This randomized testing revealed the flaw in OpenSSL. I suppose it's also a nice example of statistical reasoning (p=2^-128 that a uniform input triggers the misbehaviour) doesn't itself express risk, since while we've put enormous amounts of CPU cycles into tests we've certainly not done 2^128 work. In this case the reason our testing revealed the issue was because we used non-uniform numbers specifically constructed with low transition probability to better trigger improbable branches like carry bugs (https://github.com/bitcoin/secp256k1/blob/master/src/testran...). I used the same technique in the development of the Opus audio codec to good effect.
(Whitebox fuzzing tools like Klee or AFL, or branch coverage analysis, while good tools, seem to not be as effective for errors where the code completely omits a condition rather than having a wrong condition which was not exercised by tests.)
In libsecp256k1 the field operations (nearest parallel, we don't use generic bignums) are augmented with proofs of correctness (e.g. https://github.com/bitcoin/secp256k1/blob/master/src/field_1... ) though only a small part of our provable correctness can be machine checked currently. Of course, correctness proofs are only one part of our strategy. Fortunately, because of the much smaller scope of libsecp256k1 we likely have an easier time hitting a higher level of assurance than OpenSSL does.
We were initially unsure how serious the bug was and came up with several sophisticated attacks that were fortunately prevented by OpenSSL not using its optimized squaring operation in all the places it could have used it.
Perhaps most interesting is that one of the reference implementations of curve25519 had almost exactly the same bug as OpenSSL: https://gist.github.com/CodesInChaos/8374632 but it seems to have gone largely without notice.
[1] http://tweetnacl.cr.yp.to/tweetnacl-20140917.pdf
[2] http://blog.skylable.com/2014/05/tweetnacl-carrybit-bug/
But thats the only reason I'm not surprised. Cryptographic code is safety/security critical and as an implementer (In my experience) the potential for this kind of error is very clear. This class of mistake can be found with a strong testing and verification strategy: it can be found with correctly targeted randomized tests (as was the case for this CVE), it can be found via manual review, or it can be found via formal methods.
Widely deployed, high value cryptographic code should be using all these techniques and producing publicly visible evidence of their use.
Of course, serious software issues aren't just cryptographic ones. Systems programming, as an industry needs to up its game. (And the common tropes of higher level languages to save everything is countered by examples like this: Software safety and correctness is more than memory safety. Higher level tools can be useful, but if they get in the way of really rigorous reasoning about the software they may be counter-productive.)
TLS is far too complicated with design-by-committee, special vendor extension sauce nonsense. Heck, the FIPS code was rushed and basically done at the behest of US/Canadian govts. OpenSSL should consider burning their deadwood and stop adding features until it gets its house in order.
There's no telling how large of an attack surface remains at the protocol level, in the codebase and with CAs being compelled to issue rogue certs for MITMs.
Moreover: Can TLS features be narrowed to focus on popular and high-value use-cases instead of SCTP, UDP, oh look a bird feature? It's fine for hacking on, but not production code. (If "TLS" is evolutionarily to "Perl," who's working on a "Python"?)
BTW: What ever happened to the cert WoT overlay 'moxie0 was working on?
We need to build simpler protocols that make better use of cryptographic primitives, but first, we have to push back the tide. Eventually, TLS will be superseded by a better standard. But, this is something that even if started today with the most aggressive schedule would take 5 to 10 years to go industry-wide.
"+!" If you want C-like behavior.
It'll be imperative with full dependent types as well.
Also interesting: cryptol, Irdis, coq, but the work is on making generic systems programming clear as possible in a static, imperative language without a titanic runtime or crawling along with superfluous assertions.
This class of error is very much behind all the noise making I did at the Rust development team about treating integer overflow as a first class cause of software disaster as much as they have memory safety. Fortunately, they seem to be moving off the everything-wraps and wrapping-is-always-fine position.
https://github.com/openssl/openssl/blob/master/crypto/cversi...
The variable cflags isn't defined. I suspect it should be CFLAGS. I can make it compile locally by changing that, and it would make the code in the function consistent with the other code in the same file.
I thought C defines were case sensitive on all platforms. Anyone knows better than me?
https://github.com/openssl/openssl/blob/103b171d8fc282ef435f...
Apparently this is done to work around potential length limitations in C string literals.
It would seem odd if they actually change the build process in a security patch, right? The instructions on how to build OpenSSL on Windows has not been changed in 2 years.
No release of OpenSSL has ever been "the previous release plus the minimal patches for a security fix". This isn't a security patch. It's a new release that happens to include some security patches.
But thanks for the info. That seems like a pretty bad practice when it comes to a lib such as OpenSSL. Having to do changes to the build process to integrate an urgent security fix seems less than optimal.
LibreSSL is a step in the right direction, and I commend the OpenBSD team for taking on this alternative. However, it's only a starting point. The entire approach of OpenSSL is dated, and it has not done a good job keeping up with our modern understanding of solid security engineering. The code base needs to be overhauled from the ground up with modern security and software development practices in mind. If ever there were a library that should be designed using formal proofs in software, it's this one. Even basic TDD with good code coverage would catch the majority of the bugs that have been discovered in OpenSSL over the past ten years.
</rant>
I trust you have money to put behind them?
Yes, I have money. No, it wouldn't be a wise investment to throw it at OpenSSL. Some problems are subtle enough that merely throwing money at them won't make them go away. I also have the requisite talent and experience to make a sizable dent in rectifying the problems I have expressed in this library. However, that is also useless unless attitudes around the project are shifted so that such efforts would be maintained.
Fixing the project requires changes at the very top of their organization all the way down. At this point, nothing short of a fork -- which OpenBSD has done with LibreSSL -- may be enough to drive this sort of change. Which is, not coincidentally, why I donate money to the OpenBSD project.
LibreSSL, once it is mature, may be a good launching point for some of the ideas I have expressed here. However, I would have to see how that code base matures before making such a determination. It's a largely meaningless exercise unless people start moving to that library and away from OpenSSL.
This approach is notorious for not producing good software.
It absolutely would not eliminate CVE-2014-3570 or many other of the cryptographic bugs that show up in OpenSSL and other TLS implementations.
This kind of axiomatic thinking that memory safety equals all safety almost resulted in Rust being less safe (IMO) than C in these other respects: the normal types in rust are all defined to overflow even though overflow is almost always a bug, and so you couldn't use static analysis on arbitrary rust codebases to warn you about these issues (where you can in C because signed overflow is undefined, so an analysis tool can always flag that as an error without it being a false positive). Fortunately, it sounds like Rust is moving to fix this ( http://discuss.rust-lang.org/t/a-tale-of-twos-complement/106... ), which is a big improvement.
But it's important to not be fuzzy about the risks. There is a well established link between safety equipment and risky behavior in driving and bicycling; (http://en.wikipedia.org/wiki/Risk_compensation). I don't mean to suggest that better isn't better and we shouldn't use safer tools, but if our response to safer tools is to lower our vigilance, even the slightest, we may get worse results.
While I would personally like to see a pragmatic move towards C++ in many of these low level libraries for some of the additional type safety and mechanics the language provides, this is a normative idea only, and I am under no delusion that it would necessarily result in better code. Good software transcends language.
I would, however, like to see enhancements to the style of code being written in this library so that tools like static analyzers and contract verifiers can provide meaningful results. A craftsman is only as good as how well he/she can make use of the available tools. Much of OpenSSL defies analysis, which is why the more bone-headed of these vulnerabilities, such as Heartbleed, are so hard to find.
It's impossible to eliminate all bugs. But, it is possible to build code in such a way that when there is the suspicion of a bug, one has a fairly good idea of how and why it is occurring. It is also possible to structure code -- even C and assembler -- so that it's easier to read and analyze, be this by eye or using tools. Finally, it's possible to structure code so that automated unit testing provides meaningful results regarding boundary conditions and contracts between functions. This latter point isn't meant to find bugs on its own, but rather to codify the more subtle bits of contracts between functions and data structures in a defensive way to ensure that future patches -- like the one that caused Heartbleed -- don't stomp on assumptions made in software.
The fact that almost no teams on Earth seem to be able to ship large codebases without severe vulnerabilities rather disputes that idea.
I've done vulnerability analysis on codebases written in C++, Java, C#, Objective C, Ruby, and Python. I've found bugs in each of these platforms. The biggest differentiator I found was experience. More experienced software developers, on average, made fewer bugs resulting in vulnerabilities than less experienced software developers.
There is no magic language or platform that makes writing secure software easy. There are tools, techniques, and training that can help. But, these can only help. Writing quality software -- of which security is an important part -- is a difficult process that requires a lot of experience and discipline.
I went through every single security bulletin MS published over the past couple years. The vast majority of the serious ones were 100% due to memory safety issues. The biggest exception was due to trying to sandbox arbitrary code (their .NET equivalent to Java applets).
If you have some counter-evidence, showing C to be even remotely as safe as, say, Java, please step forward. If you are actually saying "Well I found a lot of SQL injection bugs in code written in Java", that's a different issue. And I'm sure you're aware of it.
There's probably a name for the use of rhetoric of the form "Nothing's perfect. Therefore X and Y are just as good, since they are both imperfect."
You are hammering on a single class of security vulnerability out of hundreds of potential vulnerabilities. How does Rust prevent a confused deputy vulnerability? How about SQL Injection? Okay... well, what about all of the potential side channel attacks?
People in higher level languages tend to believe that the relative safety of their position means that they have to be less vigilant about vulnerabilities. That is often what I have found. The number of vulnerabilities overall were similar, but the type of vulnerabilities were different. Because there was a completely mistaken belief that these platforms were "more secure", security practices were often sloppy. Most of these vulnerabilities were at the application level. So, looking for Microsoft CVEs isn't going to help you.
The C++ code bases tended to have more senior level people working on them, who were more careful about both defects and vulnerabilities. Code bases in higher level languages, in general, had more junior level people working on them. Largely, the number of vulnerabilities were similar.
Again, I'm speaking of my own experience. But, I think that many researchers in the field would give you a similar story. I'm always wary of people promising silver bullets over hard work.
Edit: If your overall point is that systems are laughably insecure, and most app devs just leave gigantic holes open, sure, great. But let's not compound that by making their OSes and low-level network stuff run arbitrary code for anyone on the Internet.
But, it takes more than language features to solve security issues. Memory vulnerabilities are only a small piece of the wide range of potential defects that exist in software. These are also defects that largely go away with training and experience.
I can teach most C / C++ developers how to manage memory and pointers in a way that avoids all of the pitfalls that Rust is designed to prevent. It is absolutely possible to write reasonably secure software in most general purpose programming languages. This is true for C, C++, and even Rust. Don't believe me? Spend some time studying the formal proof behind the se implementation of L4, written in C.
All of this being said, I am a big fan of high-level languages. For my personal work, I write 80% of my software in Literate Haskell and around 20% in a lower level language like C++. But, I also understand the limitations that comes with abstraction, and they are big. System level code operates under a lot of constraints, and the abstraction that come with "safe" languages can come at the cost of this code working at all.
A good software engineer uses whichever tool he / she needs to build good software. If the process is followed, then there is no reason why we can't have an ecosystem that uses whichever languages are best for the problem. For most system level stuff, C/C++ are perfectly fine. If you want to use Rust, great. But, don't delude yourself into believing that your language choice trumps good engineering practice. It never will. Don't believe me? Write some software that can work around the Halting Problem in Rust, and get back to me. Because, that's the sort of intelligence you would need in a compiler or a tool to replace good practice.
I understand you like C/C++ and want to point out that if people delivery on a superhuman effort, then we can have nice things. Meanwhile, in reality, so far, this just doesn't happen. Lemme know when we can go a year without a memory safety issue getting tons of systems owned.
Here's another OpenSSL flaw that was found with Coq, a formal prover: http://ccsinjection.lepidum.co.jp/blog/2014-06-05/CCS-Inject...