Merge pull request #8059 from rdmarsh2/rdmarsh2/cpp/insufficient-key-strength

C++: new query for insufficient key strength
This commit is contained in:
Mathias Vorreiter Pedersen
2022-03-04 17:11:44 +00:00
committed by GitHub
7 changed files with 162 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
void encrypt_with_openssl(EVP_PKEY_CTX *ctx) {
// BAD: only 1024 bits for an RSA key
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 1024);
// GOOD: 2048 bits for an RSA key
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
}

View File

@@ -0,0 +1,38 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Using cryptographic algorithms with a small key size can leave data vulnerable to being decrypted.</p>
<p>Many cryptographic algorithms provided by cryptography libraries can be configured with key sizes that are
vulnerable to brute force attacks. Using such a key size means that an attacker may be able to easily decrypt the
encrypted data.</p>
</overview>
<recommendation>
<p>Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048.</p>
</recommendation>
<example>
<p>The following code shows an example of using the <code>openssl</code> library to generate an RSA key.
When creating a key, you must specify which key size to use. The first example uses 1024 bits, which is not
considered sufficient. The second example uses 2048 bits, which is currently considered sufficient.</p>
<sample src="InsufficientKeySize.c" />
</example>
<references>
<li>NIST, FIPS 140 Annex a: <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf">
Approved Security Functions</a>.</li>
<li>NIST, SP 800-131A: <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf">
Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths</a>.</li>
<!-- LocalWords: CWE
-->
</references>
</qhelp>

View File

@@ -0,0 +1,63 @@
/**
* @name Use of a cryptographic algorithm with insufficient key size
* @description Using cryptographic algorithms with too small a key size can
* allow an attacker to compromise security.
* @kind path-problem
* @problem.severity error
* @precision high
* @id cpp/insufficient-key-size
* @tags security
* external/cwe/cwe-326
*/
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.ir.IR
import DataFlow::PathGraph
// Gets the recommended minimum key size (in bits) of `func`, the name of an encryption function that accepts a key size as parameter `paramIndex`
int getMinimumKeyStrength(string func, int paramIndex) {
func =
[
"EVP_PKEY_CTX_set_dsa_paramgen_bits", "DSA_generate_parameters_ex",
"EVP_PKEY_CTX_set_rsa_keygen_bits", "RSA_generate_key_ex", "RSA_generate_key_fips",
"EVP_PKEY_CTX_set_dh_paramgen_prime_len", "DH_generate_parameters_ex"
] and
paramIndex = 1 and
result = 2048
}
class KeyStrengthFlow extends DataFlow::Configuration {
KeyStrengthFlow() { this = "KeyStrengthFlow" }
override predicate isSource(DataFlow::Node node) {
exists(int bits |
node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and
bits < getMinimumKeyStrength(_, _) and
bits > 0 // exclude sentinel values
)
}
override predicate isSink(DataFlow::Node node) {
exists(FunctionCall fc, string name, int param |
node.asExpr() = fc.getArgument(param) and
fc.getTarget().hasGlobalName(name) and
exists(getMinimumKeyStrength(name, param))
)
}
}
from
DataFlow::PathNode source, DataFlow::PathNode sink, KeyStrengthFlow conf, FunctionCall fc,
int param, string name, int minimumBits, int bits
where
conf.hasFlowPath(source, sink) and
sink.getNode().asExpr() = fc.getArgument(param) and
fc.getTarget().hasGlobalName(name) and
minimumBits = getMinimumKeyStrength(name, param) and
bits = source.getNode().asInstruction().(ConstantValueInstruction).getValue().toInt() and
bits < minimumBits and
bits != 0
select fc, source, sink,
"The key size $@ is less than the recommended key size of " + minimumBits.toString() + " bits.",
source, bits.toString()