mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #8059 from rdmarsh2/rdmarsh2/cpp/insufficient-key-strength
C++: new query for insufficient key strength
This commit is contained in:
8
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.c
Normal file
8
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.c
Normal 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);
|
||||
}
|
||||
38
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.qhelp
Normal file
38
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.qhelp
Normal 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>
|
||||
63
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql
Normal file
63
cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql
Normal 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()
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* A new `cpp/insufficient-key-size` query has been added to the default query suite for C/C++. The query finds uses of certain cryptographic algorithms where the key size is too small to provide adequate encryption strength.
|
||||
@@ -0,0 +1,10 @@
|
||||
edges
|
||||
nodes
|
||||
| test.cpp:34:45:34:48 | 1024 | semmle.label | 1024 |
|
||||
| test.cpp:35:49:35:52 | 1024 | semmle.label | 1024 |
|
||||
| test.cpp:37:43:37:46 | 1024 | semmle.label | 1024 |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:34:5:34:38 | call to EVP_PKEY_CTX_set_dsa_paramgen_bits | test.cpp:34:45:34:48 | 1024 | test.cpp:34:45:34:48 | 1024 | The key size $@ is less than the recommended key size of 2048 bits. | test.cpp:34:45:34:48 | 1024 | 1024 |
|
||||
| test.cpp:35:5:35:42 | call to EVP_PKEY_CTX_set_dh_paramgen_prime_len | test.cpp:35:49:35:52 | 1024 | test.cpp:35:49:35:52 | 1024 | The key size $@ is less than the recommended key size of 2048 bits. | test.cpp:35:49:35:52 | 1024 | 1024 |
|
||||
| test.cpp:37:5:37:36 | call to EVP_PKEY_CTX_set_rsa_keygen_bits | test.cpp:37:43:37:46 | 1024 | test.cpp:37:43:37:46 | 1024 | The key size $@ is less than the recommended key size of 2048 bits. | test.cpp:37:43:37:46 | 1024 | 1024 |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-326/InsufficientKeySize.ql
|
||||
38
cpp/ql/test/query-tests/Security/CWE/CWE-326/test.cpp
Normal file
38
cpp/ql/test/query-tests/Security/CWE/CWE-326/test.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
typedef int EVP_CIPHER;
|
||||
typedef int EVP_MD;
|
||||
|
||||
const EVP_CIPHER *EVP_aes_128_ctr();
|
||||
const EVP_CIPHER *EVP_aes_192_ctr();
|
||||
const EVP_CIPHER *EVP_aes_256_ctr();
|
||||
|
||||
const EVP_MD *EVP_sha224();
|
||||
const EVP_MD *EVP_sha256();
|
||||
const EVP_MD *EVP_sha384();
|
||||
const EVP_MD *EVP_sha512();
|
||||
|
||||
|
||||
class EVP_PKEY_CTX;
|
||||
|
||||
// int is a curve ID rather than a bit width
|
||||
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX*, int);
|
||||
|
||||
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX*, int);
|
||||
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX*, int);
|
||||
|
||||
// RSA sets bits per-key rather than with parameters
|
||||
int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX*, int);
|
||||
|
||||
void test1(EVP_PKEY_CTX *ctx) {
|
||||
EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, 2048);
|
||||
EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, 2048);
|
||||
// RSA sets bits per-key rather than with parameters
|
||||
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
|
||||
|
||||
// low key sizes
|
||||
EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, 1024);
|
||||
EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, 1024);
|
||||
// RSA sets bits per-key rather than with parameters
|
||||
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 1024);
|
||||
}
|
||||
Reference in New Issue
Block a user