Skip to content

Commit 874e3b5

Browse files
committed
Modify model to use newtypes, expand modeling
1 parent 4d44755 commit 874e3b5

File tree

4 files changed

+665
-156
lines changed

4 files changed

+665
-156
lines changed

cpp/ql/lib/experimental/Quantum/OpenSSL.qll

Lines changed: 170 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,172 @@ import semmle.code.cpp.dataflow.new.DataFlow
44
module OpenSSLModel {
55
import Language
66

7-
abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { }
7+
class FunctionCallOrMacroAccess extends Element {
8+
FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess }
9+
10+
string getTargetName() {
11+
result = this.(FunctionCall).getTarget().getName()
12+
or
13+
result = this.(MacroAccess).getMacroName()
14+
}
15+
}
16+
17+
/**
18+
* Hash function references in OpenSSL.
19+
*/
20+
predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) {
21+
// `ma` name has an LN_ or SN_ prefix, which we want to ignore
22+
// capture any name after the _ prefix using regex matching
23+
name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1
24+
or
25+
name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2
26+
or
27+
name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3
28+
or
29+
name = "md2" and algo instanceof Crypto::MD2
30+
or
31+
name = "md4" and algo instanceof Crypto::MD4
32+
or
33+
name = "md5" and algo instanceof Crypto::MD5
34+
or
35+
name = "ripemd160" and algo instanceof Crypto::RIPEMD160
36+
or
37+
name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL
38+
}
39+
40+
predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) {
41+
name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and
42+
hash_ref_type_mapping_known(name, algo)
43+
}
44+
45+
class HashAlgorithmRef extends Crypto::HashAlgorithm {
46+
FunctionCallOrMacroAccess instance;
47+
48+
HashAlgorithmRef() {
49+
this = Crypto::THashAlgorithm(instance) and
50+
hash_ref_type_mapping(instance, _, _)
51+
}
52+
53+
override string getSHA2OrSHA3DigestSize(Location location) {
54+
(
55+
this.getHashType() instanceof Crypto::SHA2 or
56+
this.getHashType() instanceof Crypto::SHA3
57+
) and
58+
exists(string name |
59+
hash_ref_type_mapping(instance, name, this.getHashType()) and
60+
result = name.regexpFind("\\d{3}", 0, _) and
61+
location = instance.getLocation()
62+
)
63+
}
864

9-
class SHA1Algo extends Crypto::HashAlgorithm instanceof MacroAccess {
10-
SHA1Algo() { this.getMacro().getName() = "SN_sha1" }
65+
override string getRawAlgorithmName() { result = instance.getTargetName() }
1166

12-
override string getRawAlgorithmName() { result = "SN_sha1" }
67+
override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) }
1368

14-
override Crypto::THashType getHashType() { result instanceof Crypto::SHA1 }
69+
Element getInstance() { result = instance }
70+
71+
override Location getLocation() { result = instance.getLocation() }
1572
}
1673

74+
/**
75+
* Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive.
76+
*/
1777
module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig {
18-
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof KeyDerivationAlgorithm }
78+
predicate isSource(DataFlow::Node source) {
79+
source.asExpr() = any(KeyDerivationAlgorithm a).getInstance()
80+
}
1981

2082
predicate isSink(DataFlow::Node sink) {
21-
exists(EVP_KDF_derive kdo | sink.asExpr() = kdo.getAlgorithmArg())
83+
exists(EVP_KDF_derive kdo |
84+
sink.asExpr() = kdo.getAlgorithmArg()
85+
or
86+
sink.asExpr() = kdo.getContextArg() // via `EVP_KDF_CTX_set_params`
87+
)
88+
}
89+
90+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
91+
none() // TODO
2292
}
2393
}
2494

2595
module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global<AlgorithmToEVPKeyDeriveConfig>;
2696

27-
predicate algorithm_to_EVP_KDF_derive(Crypto::Algorithm algo, EVP_KDF_derive derive) {
28-
algo.(Expr).getEnclosingFunction() = derive.(Expr).getEnclosingFunction()
97+
predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) {
98+
none()
2999
}
30100

31-
class EVP_KDF_derive extends KeyDerivationOperation instanceof FunctionCall {
32-
EVP_KDF_derive() { this.getTarget().getName() = "EVP_KDF_derive" }
101+
/**
102+
* Key derivation operation (e.g., `EVP_KDF_derive`)
103+
*/
104+
abstract class KeyDerivationOperation extends Crypto::KeyDerivationOperation { }
105+
106+
class EVP_KDF_derive extends KeyDerivationOperation {
107+
FunctionCall instance;
108+
109+
EVP_KDF_derive() {
110+
this = Crypto::TKeyDerivationOperation(instance) and
111+
instance.getTarget().getName() = "EVP_KDF_derive"
112+
}
33113

34114
override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) }
35115

36-
Expr getAlgorithmArg() { result = this.(FunctionCall).getArgument(3) }
116+
Expr getAlgorithmArg() { result = instance.getArgument(3) }
117+
118+
Expr getContextArg() { result = instance.getArgument(0) }
37119
}
38120

39-
abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm { }
121+
/**
122+
* Key derivation algorithm nodes
123+
*/
124+
abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm {
125+
abstract Expr getInstance();
126+
}
40127

128+
/**
129+
* `EVP_KDF_fetch` returns a key derivation algorithm.
130+
*/
41131
class EVP_KDF_fetch_Call extends FunctionCall {
42132
EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" }
43133

44134
Expr getAlgorithmArg() { result = this.getArgument(1) }
45135
}
46136

47-
predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF"] }
48-
49-
class KDFAlgorithmStringLiteral extends Crypto::NodeBase instanceof StringLiteral {
50-
KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) }
137+
class EVP_KDF_fetch_AlgorithmArg extends Expr {
138+
EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) }
139+
}
51140

52-
override string toString() { result = this.(StringLiteral).toString() }
141+
predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] }
53142

54-
string getValue() { result = this.(StringLiteral).getValue() }
143+
class KDFAlgorithmStringLiteral extends StringLiteral {
144+
KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) }
55145
}
56146

57147
private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig {
58148
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral }
59149

60-
predicate isSink(DataFlow::Node sink) {
61-
exists(EVP_KDF_fetch_Call call | sink.asExpr() = call.getAlgorithmArg())
62-
}
150+
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg }
63151
}
64152

65153
module AlgorithmStringToFetchFlow = DataFlow::Global<AlgorithmStringToFetchConfig>;
66154

67-
predicate algorithmStringToKDFFetchArgFlow(string name, KDFAlgorithmStringLiteral origin, Expr arg) {
68-
exists(EVP_KDF_fetch_Call sinkCall |
69-
origin.getValue().toUpperCase() = name and
70-
arg = sinkCall.getAlgorithmArg() and
71-
AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg))
72-
)
155+
predicate algorithmStringToKDFFetchArgFlow(
156+
string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg
157+
) {
158+
origin.getValue().toUpperCase() = name and
159+
AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg))
73160
}
74161

75-
class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF instanceof Expr {
162+
/**
163+
* HKDF key derivation algorithm.
164+
*/
165+
class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF {
76166
KDFAlgorithmStringLiteral origin;
167+
EVP_KDF_fetch_AlgorithmArg instance;
77168

78-
HKDF() { algorithmStringToKDFFetchArgFlow("HKDF", origin, this) }
169+
HKDF() {
170+
this = Crypto::TKeyDerivationAlgorithm(instance) and
171+
algorithmStringToKDFFetchArgFlow("HKDF", origin, instance)
172+
}
79173

80174
override string getRawAlgorithmName() { result = origin.getValue() }
81175

@@ -84,19 +178,61 @@ module OpenSSLModel {
84178
override Crypto::LocatableElement getOrigin(string name) {
85179
result = origin and name = origin.toString()
86180
}
181+
182+
override Expr getInstance() { result = origin }
87183
}
88184

89-
class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF instanceof Expr {
185+
/**
186+
* PBKDF2 key derivation algorithm.
187+
*/
188+
class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 {
90189
KDFAlgorithmStringLiteral origin;
190+
EVP_KDF_fetch_AlgorithmArg instance;
91191

92-
PKCS12KDF() { algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, this) }
192+
PBKDF2() {
193+
this = Crypto::TKeyDerivationAlgorithm(instance) and
194+
algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance)
195+
}
93196

94197
override string getRawAlgorithmName() { result = origin.getValue() }
95198

96-
override Crypto::HashAlgorithm getHashAlgorithm() { none() }
199+
override string getIterationCount(Location location) { none() } // TODO
200+
201+
override string getKeyLength(Location location) { none() } // TODO
202+
203+
override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO
204+
205+
override Crypto::LocatableElement getOrigin(string name) {
206+
result = origin and name = origin.toString()
207+
}
97208

98-
override Crypto::NodeBase getOrigin(string name) {
209+
override Expr getInstance() { result = instance }
210+
}
211+
212+
/**
213+
* PKCS12KDF key derivation algorithm.
214+
*/
215+
class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF {
216+
KDFAlgorithmStringLiteral origin;
217+
EVP_KDF_fetch_AlgorithmArg instance;
218+
219+
PKCS12KDF() {
220+
this = Crypto::TKeyDerivationAlgorithm(instance) and
221+
algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance)
222+
}
223+
224+
override string getRawAlgorithmName() { result = origin.getValue() }
225+
226+
override string getIterationCount(Location location) { none() } // TODO
227+
228+
override string getIDByte(Location location) { none() } // TODO
229+
230+
override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO
231+
232+
override Crypto::LocatableElement getOrigin(string name) {
99233
result = origin and name = origin.toString()
100234
}
235+
236+
override Expr getInstance() { result = instance }
101237
}
102238
}

0 commit comments

Comments
 (0)