forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenSSL.qll
More file actions
244 lines (186 loc) · 7.79 KB
/
OpenSSL.qll
File metadata and controls
244 lines (186 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
module OpenSSLModel {
import Language
/**
* Hash function references in OpenSSL.
*/
predicate hash_ref_type_mapping_known(string name, Crypto::THashType algo) {
// `ma` name has an LN_ or SN_ prefix, which we want to ignore
// capture any name after the _ prefix using regex matching
name = ["sha1", "sha160"] and algo instanceof Crypto::SHA1
or
name = ["sha224", "sha256", "sha384", "sha512"] and algo instanceof Crypto::SHA2
or
name = ["sha3-224", "sha3-256", "sha3-384", "sha3-512"] and algo instanceof Crypto::SHA3
or
name = "md2" and algo instanceof Crypto::MD2
or
name = "md4" and algo instanceof Crypto::MD4
or
name = "md5" and algo instanceof Crypto::MD5
or
name = "ripemd160" and algo instanceof Crypto::RIPEMD160
or
name = "whirlpool" and algo instanceof Crypto::WHIRLPOOL
}
predicate hash_ref_type_mapping(FunctionCallOrMacroAccess ref, string name, Crypto::THashType algo) {
name = ref.getTargetName().regexpCapture("(?:SN_|LN_|EVP_)([a-z0-9]+)", 1) and
hash_ref_type_mapping_known(name, algo)
}
class FunctionCallOrMacroAccess extends Element {
FunctionCallOrMacroAccess() { this instanceof FunctionCall or this instanceof MacroAccess }
string getTargetName() {
result = this.(FunctionCall).getTarget().getName()
or
result = this.(MacroAccess).getMacroName()
}
}
class HashAlgorithmCallOrMacro extends Crypto::HashAlgorithmInstance instanceof FunctionCallOrMacroAccess
{
HashAlgorithmCallOrMacro() { hash_ref_type_mapping(this, _, _) }
string getTargetName() { result = this.(FunctionCallOrMacroAccess).getTargetName() }
}
class HashAlgorithm extends Crypto::HashAlgorithm {
HashAlgorithmCallOrMacro instance;
HashAlgorithm() { this = Crypto::THashAlgorithm(instance) }
override string getSHA2OrSHA3DigestSize(Location location) {
(
this.getHashType() instanceof Crypto::SHA2 or
this.getHashType() instanceof Crypto::SHA3
) and
exists(string name |
hash_ref_type_mapping(instance, name, this.getHashType()) and
result = name.regexpFind("\\d{3}", 0, _) and
location = instance.getLocation()
)
}
override string getRawAlgorithmName() { result = instance.getTargetName() }
override Crypto::THashType getHashType() { hash_ref_type_mapping(instance, _, result) }
Element getInstance() { result = instance }
override Location getLocation() { result = instance.getLocation() }
}
/**
* Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive.
*/
module AlgorithmToEVPKeyDeriveConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() = any(KeyDerivationAlgorithm a).getInstance()
}
predicate isSink(DataFlow::Node sink) {
exists(EVP_KDF_derive kdo |
sink.asExpr() = kdo.getCall().getAlgorithmArg()
or
sink.asExpr() = kdo.getCall().getContextArg() // via `EVP_KDF_CTX_set_params`
)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
none() // TODO
}
}
module AlgorithmToEVPKeyDeriveFlow = DataFlow::Global<AlgorithmToEVPKeyDeriveConfig>;
predicate algorithm_to_EVP_KDF_derive(KeyDerivationAlgorithm algo, EVP_KDF_derive derive) {
none()
}
/**
* Key derivation operation (e.g., `EVP_KDF_derive`)
*/
class EVP_KDF_derive_FunctionCall extends Crypto::KeyDerivationOperationInstance instanceof FunctionCall
{
EVP_KDF_derive_FunctionCall() { this.getTarget().getName() = "EVP_KDF_derive" }
Expr getAlgorithmArg() { result = super.getArgument(3) }
Expr getContextArg() { result = super.getArgument(0) }
}
class EVP_KDF_derive extends Crypto::KeyDerivationOperation {
EVP_KDF_derive_FunctionCall instance;
EVP_KDF_derive() { this = Crypto::TKeyDerivationOperation(instance) }
override Crypto::Algorithm getAlgorithm() { algorithm_to_EVP_KDF_derive(result, this) }
EVP_KDF_derive_FunctionCall getCall() { result = instance }
}
/**
* Key derivation algorithm nodes
*/
abstract class KeyDerivationAlgorithm extends Crypto::KeyDerivationAlgorithm {
abstract Expr getInstance();
}
/**
* `EVP_KDF_fetch` returns a key derivation algorithm.
*/
class EVP_KDF_fetch_Call extends FunctionCall {
EVP_KDF_fetch_Call() { this.getTarget().getName() = "EVP_KDF_fetch" }
Expr getAlgorithmArg() { result = this.getArgument(1) }
}
class EVP_KDF_fetch_AlgorithmArg extends Crypto::KeyDerivationAlgorithmInstance instanceof Expr {
EVP_KDF_fetch_AlgorithmArg() { exists(EVP_KDF_fetch_Call call | this = call.getAlgorithmArg()) }
}
predicate kdf_names(string algo) { algo = ["HKDF", "PKCS12KDF", "PBKDF2"] }
class KDFAlgorithmStringLiteral extends StringLiteral {
KDFAlgorithmStringLiteral() { kdf_names(this.getValue().toUpperCase()) }
}
private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof KDFAlgorithmStringLiteral }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof EVP_KDF_fetch_AlgorithmArg }
}
module AlgorithmStringToFetchFlow = DataFlow::Global<AlgorithmStringToFetchConfig>;
predicate algorithmStringToKDFFetchArgFlow(
string name, KDFAlgorithmStringLiteral origin, EVP_KDF_fetch_AlgorithmArg arg
) {
origin.getValue().toUpperCase() = name and
AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(origin), DataFlow::exprNode(arg))
}
/**
* HKDF key derivation algorithm.
*/
class HKDF extends KeyDerivationAlgorithm, Crypto::HKDF {
KDFAlgorithmStringLiteral origin;
EVP_KDF_fetch_AlgorithmArg instance;
HKDF() {
this = Crypto::TKeyDerivationAlgorithm(instance) and
algorithmStringToKDFFetchArgFlow("HKDF", origin, instance)
}
override string getRawAlgorithmName() { result = origin.getValue() }
override Crypto::HashAlgorithm getHashAlgorithm() { none() }
override Crypto::LocatableElement getOrigin(string name) {
result = origin and name = origin.toString()
}
override Expr getInstance() { result = origin }
}
/**
* PBKDF2 key derivation algorithm.
*/
class PBKDF2 extends KeyDerivationAlgorithm, Crypto::PBKDF2 {
KDFAlgorithmStringLiteral origin;
EVP_KDF_fetch_AlgorithmArg instance;
PBKDF2() {
this = Crypto::TKeyDerivationAlgorithm(instance) and
algorithmStringToKDFFetchArgFlow("PBKDF2", origin, instance)
}
override string getRawAlgorithmName() { result = origin.getValue() }
override string getIterationCount(Location location) { none() } // TODO
override string getKeyLength(Location location) { none() } // TODO
override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO
override Crypto::LocatableElement getOrigin(string name) {
result = origin and name = origin.toString()
}
override Expr getInstance() { result = instance }
}
/**
* PKCS12KDF key derivation algorithm.
*/
class PKCS12KDF extends KeyDerivationAlgorithm, Crypto::PKCS12KDF {
KDFAlgorithmStringLiteral origin;
EVP_KDF_fetch_AlgorithmArg instance;
PKCS12KDF() {
this = Crypto::TKeyDerivationAlgorithm(instance) and
algorithmStringToKDFFetchArgFlow("PKCS12KDF", origin, instance)
}
override string getRawAlgorithmName() { result = origin.getValue() }
override string getIterationCount(Location location) { none() } // TODO
override string getIDByte(Location location) { none() } // TODO
override Crypto::HashAlgorithm getHashAlgorithm() { none() } // TODO
override Crypto::LocatableElement getOrigin(string name) {
result = origin and name = origin.toString()
}
override Expr getInstance() { result = instance }
}
}