Skip to content

Commit b0514de

Browse files
committed
C++: Add cpp/crypto-primitive query to experimental.
1 parent e79ad3b commit b0514de

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* @name Implementation of a cryptographic primitive
3+
* @description Writing your own cryptographic primitives is prone to errors and omissions that weaken cryptographic protection.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @security-severity 7.5
7+
* @precision medium
8+
* @id cpp/crypto-primitive
9+
* @tags security
10+
* external/cwe/cwe-1240
11+
*/
12+
13+
import cpp
14+
15+
/**
16+
* A word that might be in the name of an encryption function.
17+
*/
18+
string encryptionWord() {
19+
exists(string word |
20+
// `(?<!P)` is negative lookbehind, i.e. the match is not preceeded by `P`.
21+
// `(?!P)` is negative lookahead, i.e. the match is not followed by `P`.
22+
word =
23+
[
24+
"Crypt", "Cipher", "Aes", "Rijndael",
25+
//"(?<!Wi|Co|No)Des(?!truct)",
26+
"(?<!C)Rc[0-9]", "(?<!Cha|Unive)Rsa", "Blowfish", "Twofish", "Idea", "Kyber", "(?<!V)Aria",
27+
//"Asn[0-9]",
28+
"Camellia",
29+
//"(?<!Bit|Type)Cast",
30+
"Chacha", "ChaCha", "Idea", "Poly[0-9]", "Ripemd", "Whirlpool", "Sbox", "SBox", "Cblock",
31+
"CBlock", "Sub.?Byte", "Mix.?Column", "ECDH", "ECDSA", "EdDSA", "ECMQV", "ECQV",
32+
"Curve[0-9][0-9]"
33+
] and
34+
(
35+
result = word or
36+
result = word.toLowerCase() + "(?![a-z])" or // avoid matching middles of words
37+
result = word.toUpperCase() + "(?![A-Z])" // avoid matching middles of words
38+
)
39+
)
40+
}
41+
42+
/**
43+
* A function whose name suggests it may be doing encryption (but may or may
44+
* not actually implement an encryption primitive itself).
45+
*/
46+
predicate likelyEncryptionFunction(Function f) {
47+
exists(string fName | fName = f.getName() |
48+
fName.regexpMatch(".*(" + concat(encryptionWord(), "|") + ").*")
49+
)
50+
}
51+
52+
/**
53+
* A type that is common in encryption-like computations. That is, an integral
54+
* type or array of integral type elements.
55+
*/
56+
predicate computeHeuristicType(Type t) {
57+
t instanceof IntegralType or
58+
computeHeuristicType(t.(ArrayType).getBaseType().getUnspecifiedType())
59+
}
60+
61+
/**
62+
* An operation that is common in encryption-like computations. Looking for
63+
* clusters of these tends to find things like encrpytion, compression, random
64+
* number generation, graphics processing and other compute heavy algoritms.
65+
*/
66+
predicate computeHeuristic(Expr e) {
67+
(
68+
e instanceof BitwiseXorExpr or
69+
e instanceof AssignXorExpr or
70+
e instanceof LShiftExpr or
71+
e instanceof AssignLShiftExpr or
72+
e instanceof RShiftExpr or
73+
e instanceof AssignRShiftExpr or
74+
e instanceof ArrayExpr
75+
) and
76+
computeHeuristicType(e.getUnspecifiedType())
77+
}
78+
79+
from Function f, int amount
80+
where
81+
likelyEncryptionFunction(f) and
82+
amount = strictcount(Expr e | computeHeuristic(e) and e.getEnclosingFunction() = f) and
83+
amount >= 8 and
84+
exists(f.getFile().getRelativePath()) // exclude library files
85+
select f, "This may be a custom implementation of a cryptographic primitive."

0 commit comments

Comments
 (0)