coreinfrastructure / best-practices-badge

🏆Open Source Security Foundation (OpenSSF) Best Practices Badge (formerly Core Infrastructure Initiative (CII) Best Practices Badge)
https://www.bestpractices.dev
MIT License
1.22k stars 202 forks source link

Are crypto requirements too hard? (Stenberg and curl) #224

Closed david-a-wheeler closed 8 years ago

david-a-wheeler commented 8 years ago

On 2016-02-16 Daniel Stenberg posted curl-related comments on the mailing list. Many of them asked about the crypto requirements, possibly suggesting that the requirements are too hard. Here are his initial comments and my initial responses; not sure how to address them.

Then over to specific questions and I had problems with several ones in the security section. In general, many of the questions are so specific they will no doubt lead to many future questions about interpretations or users will just select "Met" and assume (claim) its fine anyway. They're also very one-dimensional. If we support a wide variety of things, like from crap to good algorithms, we still support the crap so we have to state "Unmet" and it will appear as if we don't support the good.

  1. "The project MUST have at least one primary developer who knows how to design secure software". That's just such a vague and subjective question that I can't see what goodness it will bring. In our project we've had lots of security flaws over the years, is that a proof that we should say "Unmet" ? Or is the fact that we fixed the problems perhaps an indication we should select "Met". Perhaps I'm just too old and grumpy, but what "secure software" is, is a really fuzzy grey zone and how to convert that into a binary 1 or 0 is not clear to me.

If you open the details (click the "show details" button), the intent is for this to not be vague. You simply have to be able to point to a primary developer who knows the specific bullet list given in the details. The bigger problem is that figuring out who a "primary developer" can be tricky; we did try to define that too...!

Lots of security flaws is obviously not desirable - but that isn't disqualifying. If we required that people never make mistakes, we'd have a really short list of projects :-). In my mind, what's more important is if you're learning, but that's hard to put into a criterion. But we can require some educational knowledge - that, at least, is checkable and (I think) a useful start.

I suspect that our "Show details" button isn't obvious enough to do its job. We're going to do some UI cleanups, and I hope that'll make this easier to understand.

  1. "If the project software is an application or library, and its primary purpose is not to implement cryptography, then it MUST only call on software specifically designed to implement cryptographic functions; it MUST NOT re-implement its own." What does re-implement its own mean? If we have our own implementation of a popular message digest algorithm, is that an re-implementation?

I would think the answer is "yes" if I understand you correctly.

If we have that re-implementation to be able to provide functionality to users who build our code without a crypto library, is that then a bad practise? What constitutes a "re-implementation" ? Ours is a public domain code we imported into our code base years ago. Is that a re-implementation?

The goal is to encourage people to call on other crypto libraries, instead of embedding one, because people get them wrong so often. For example, most re-implementations don't counter timing attacks at all. But we could reduce that to SHOULD NOT, SUGGEST NOT, reword it, or even remove it.

  1. "All functionality that depends on cryptography MUST be implementable using OSS"

This is really hard to understand. What exactly is "functionality that depends on cryptography" ? If our project provides functionality that is using cryptography, and pieces of that cryptography is provided by a proprietary operating system (lets say Windows), then I assume we must say "Unmet" here? Even if that's the only way to provide said functionality and that functionality is not present on other platforms?

Not at all. The goal here is to prevent depending on cryptography that COULDN'T be legally implemented by OSS. This is basically a patent issue.

If you call Windows on a Windows platform, that's a good thing. But if your system's crypto protocol depends on something patented that CANNOT be reimplemented by FLOSS, that's a problem.

  1. "The default keylengths MUST meet the NIST minimum requirements at least through the year 2030"

That assumes we always speak modern algorithms against modern services. What if we want to provide features that work against existing or legacy services that are still used widely out there? Even if we support the minimum requirements well and beyond for all modern algorithms and uses, we still support those old ones so we'd have to mark that "Unmet" I suppose. Very course-grained and unfortunate methinks.

Agreed. The intent was that the defaults would be the minimums, but it could be configured or told to accept worse than that.

The problem of legacy services is sadly a big problem. Do you have suggested improved wording?

  1. "The project security mechanisms MUST NOT depend on cryptographic algorithms that are broken"

Depend on? We implement features and provide functionality that use some of those algorithms. That is not by choice, that's because stupid people wrote standards and systems using those and we interoperate with them. We do however not use them for things where disabling them is possible, like proper TLS. Does it make us "depend on" md4? Yes, for NTLM.

Hmm, again, the challenge of legacy services.

We may need to change the text to make it clear that it's okay to support legacy services. My thinking is that there needs to be some way to warn users, or require user configuration, to accept broken/highly weakened algorithms.

  1. "The project SHOULD support multiple cryptographic algorithms, so users can quickly switch if one is broken" Again with the binary choice that isn't binary in the real world. That's of course good if the underlying protocol supports that. If we support stuff that somone else designed ages ago with a fixed algorithm AND we support modern protocols with pluggable ciphers, what do we pick? For TLS we can say "Met". For NTLM we cannot.

There's been argument about this criterion, so we're dropping this one entirely. One problem gone :-).

  1. "The project MUST generate all cryptographic keys and nonces using a cryptographically secure random number generator, and MUST NOT do so using generators that are not cryptographically secure" That's not possible for us to guarantee. We provide a library that builds with one out of 11 TLS libraries and that run on numerous embedded systems or even RTOSes. You say that we MUST remove the code that makes it possible to build it without one of our own strong crypto backends for random sources? We will certainly use that for the vast majority of machines and configurations, but not for all possible setups. So I guess that's an "Unmet" which will look really scary to people who'd use our project on a system with a really safe setup.

Hmm... so it's safe in normal circumstances, but not in specialized ones, right? Hmm. That's tricky. Many formal certification systems document the required conditions. We hadn't planned on doing that, but maybe we can't avoid that.

izar commented 8 years ago

"The project SHOULD support multiple cryptographic algorithms, so users can quickly switch if one is broken" Again with the binary choice that isn't binary in the real world. That's of course good if the underlying protocol supports that. If we support stuff that somone else designed ages ago with a fixed algorithm AND we support modern protocols with pluggable ciphers, what do we pick? For TLS we can say "Met". For NTLM we cannot.

There's been argument about this criterion, so we're dropping this one entirely. One problem gone :-).

A question about the original intent of this requirement - wasn't it to provide crypto agility in the same way that, for example, SSLCipherSuite gives the ability to be selective in the ciphers available? If that is the case I respectfully disagree with the point that it is a binary choice, and that legacy protocols break it; the final product should be able to specify which ciphers it will work with, and it becomes a decision of the user if they will then accept the risk of using a known-weak cipher in their deployment. So in the case of a project that uses pluggable ciphers and fixed ones (like md4 for NTLM) then the answer is "Met", since the software does support multiple crypto algorithms, but the choice is left to the final user in what to implement. If the user disables md4 but tries to implement NTLM functionality, then an error message should inform that those two decisions are incompatible.

david-a-wheeler commented 8 years ago

@izar - for details about removing the requirement for supporting alternative crypto algorithms (crypto_alternatives), see issue #215.

You're quite right that a project that uses pluggable ciphers absolutely does meet the old crypto_alternatives requirement. However, there were objections, e.g., some cryptographers do not agree that agility is a good thing. I think agility is a good thing, but if there's that much pushback, then this kind of requirement doesn't really belong in an entry-level badge. We hope to add higher badge levels in the future, and we can re-discuss it then.

That said, do other crypto requirements need to removed? Downgraded? Changed? If so, how?

dankohn commented 8 years ago

I definitely think we need to loosen the rule about including your own crypto algorithm. https://github.com/linuxfoundation/cii-best-practices-badge/blob/master/doc/criteria.md#crypto_call

As an example, libgit2 seems to rely on OpenSSL while git includes its own SHA1 implementation, which is originally from Mozilla. We might want to distinguish between protocols and algorithms, or just make it a suggested.

david-a-wheeler commented 8 years ago

There are many ways to loosen the rule about including your own crypto implementation, which is currently: "If the project software is an application or library, and its primary purpose is not to implement cryptography, then it MUST only call on software specifically designed to implement cryptographic functions; it MUST NOT re-implement its own. [crypto_call]"

We could try to problem is in implementations that handle secret keys. It's really tricky to implement crypto algorithms in ways that don't leak secret keys via timing, electromagnetic leakage, etc. So perhaps if you handle secret keys, you want to call out to external libraries, otherwise it's not a big deal.

But on further reflection, that isn't enough either. Oftentimes you hash a password (e.g., as part of a salted iterated hash).

We could say it's okay to use your own hash functions (they're small!). But some other implementations are small also.

At this point, I think it might be best to just downgrade "crypto_call" to SHOULD. It allows alternatives without the complexity.

Also: It seems to me that it'd be okay to get a badge if you make an assertion about its conditions. E.G., "These answers require an x86_64; answers may be different on other platforms."

david-a-wheeler commented 8 years ago

Okay, I'm convinced, let's just downgrade "crypto_call" to SHOULD. This is a typical example of a SHOULD: Something you SHOULD normally do, but there are special cases where it's not. We've dropped the "switchable crypto" requirement, and hopefully it's clear that the keylength requirements are for the defaults - users can configure for worse if needed (e.g., to support insecure legacy protocols). We can add "by default" in a few other places to make it clear that you CAN support insecure legacy protocols, just don't support them by default.

I think with those changes we'll have addressed this issue.