Skip to content

Commit dbe4770

Browse files
committed
C++: add initial insufficient key size query
1 parent eb10982 commit dbe4770

File tree

5 files changed

+128
-0
lines changed

5 files changed

+128
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Using cryptographic algorithms with a small key size can leave data vulnerable to being decrypted.</p>
7+
8+
<p>Many cryptographic algorithms provided by cryptography libraries can be configured with key sizes that are
9+
vulnerable to brute force attacks. Using such a key size means that an attacker may be able to easily decrypt the
10+
encrypted data.</p>
11+
12+
</overview>
13+
<recommendation>
14+
15+
<p>Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048.</p>
16+
17+
</recommendation>
18+
<example>
19+
20+
21+
22+
</example>
23+
<references>
24+
25+
<li>NIST, FIPS 140 Annex a: <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf">
26+
Approved Security Functions</a>.</li>
27+
<li>NIST, SP 800-131A: <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf">
28+
Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths</a>.</li>
29+
30+
31+
32+
<!-- LocalWords: CWE
33+
-->
34+
35+
</references>
36+
</qhelp>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* @name Use of a cryptographic algorithm with insufficient key size
3+
* @description Using cryptographic algorithms with too small a key size can
4+
* allow an attacker to compromise security.
5+
* @kind problem
6+
* @problem.severity error
7+
* @precision high
8+
* @id cpp/insufficient-key-size
9+
* @tags security
10+
* external/cwe/cwe-326
11+
*/
12+
13+
import cpp
14+
import semmle.code.cpp.ir.dataflow.DataFlow
15+
import semmle.code.cpp.ir.IR
16+
17+
int getMinimumKeyStrength(string func) {
18+
func = "EVP_PKEY_CTX_set_dsa_paramgen_bits" and result = 2048
19+
or
20+
func = "EVP_PKEY_CTX_set_dh_paramgen_prime_len" and result = 2048
21+
or
22+
func = "EVP_PKEY_CTX_set_rsa_keygen_bits" and result = 2048
23+
}
24+
25+
class KeyStrengthFlow extends DataFlow::Configuration {
26+
KeyStrengthFlow() {
27+
this = "KeyStrengthFlow"
28+
}
29+
30+
override predicate isSource(DataFlow::Node node) {
31+
node.asInstruction() instanceof IntegerConstantInstruction
32+
}
33+
34+
override predicate isSink(DataFlow::Node node) {
35+
exists(FunctionCall fc, string name|
36+
node.asExpr() = fc.getArgument(1) and
37+
fc.getTarget().hasGlobalName(name) and
38+
exists(getMinimumKeyStrength(name))
39+
)
40+
}
41+
}
42+
43+
from DataFlow::PathNode source, DataFlow::PathNode sink, KeyStrengthFlow conf, FunctionCall fc, string name, int bits
44+
where
45+
conf.hasFlowPath(source, sink) and
46+
sink.getNode().asExpr() = fc.getArgument(1) and
47+
fc.getTarget().hasGlobalName(name) and
48+
bits = getMinimumKeyStrength(name) and
49+
source.getNode().asInstruction().(ConstantValueInstruction).getValue().toInt() < bits
50+
select fc, source, sink, "The key size $@ is insufficient for security", source, source.toString()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.cpp:32:5:32:38 | call to EVP_PKEY_CTX_set_dsa_paramgen_bits | test.cpp:32:45:32:48 | 1024 | test.cpp:32:45:32:48 | 1024 | The key size $@ is insufficient for security | test.cpp:32:45:32:48 | 1024 | 1024 |
2+
| test.cpp:33:5:33:42 | call to EVP_PKEY_CTX_set_dh_paramgen_prime_len | test.cpp:33:49:33:52 | 1024 | test.cpp:33:49:33:52 | 1024 | The key size $@ is insufficient for security | test.cpp:33:49:33:52 | 1024 | 1024 |
3+
| test.cpp:35:5:35:36 | call to EVP_PKEY_CTX_set_rsa_keygen_bits | test.cpp:35:43:35:46 | 1024 | test.cpp:35:43:35:46 | 1024 | The key size $@ is insufficient for security | test.cpp:35:43:35:46 | 1024 | 1024 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-326/InsufficientKeySize.ql
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
3+
typedef int EVP_CIPHER;
4+
typedef int EVP_MD;
5+
6+
const EVP_CIPHER *EVP_aes_128_ctr();
7+
const EVP_CIPHER *EVP_aes_192_ctr();
8+
const EVP_CIPHER *EVP_aes_256_ctr();
9+
10+
const EVP_MD *EVP_sha224();
11+
const EVP_MD *EVP_sha256();
12+
const EVP_MD *EVP_sha384();
13+
const EVP_MD *EVP_sha512();
14+
15+
16+
class EVP_PKEY_CTX;
17+
18+
// int is a curve ID rather than a bit width
19+
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX*, int);
20+
21+
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX*, int);
22+
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX*, int);
23+
24+
// RSA sets bits per-key rather than with parameters
25+
int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX*, int);
26+
27+
void test1(EVP_PKEY_CTX *ctx) {
28+
EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, 2048);
29+
EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, 2048);
30+
// RSA sets bits per-key rather than with parameters
31+
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
32+
33+
// low key sizes
34+
EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, 1024);
35+
EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, 1024);
36+
// RSA sets bits per-key rather than with parameters
37+
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 1024);
38+
}

0 commit comments

Comments
 (0)