@@ -4,78 +4,172 @@ import semmle.code.cpp.dataflow.new.DataFlow
4
4
module OpenSSLModel {
5
5
import Language
6
6
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
+ }
8
64
9
- class SHA1Algo extends Crypto:: HashAlgorithm instanceof MacroAccess {
10
- SHA1Algo ( ) { this .getMacro ( ) .getName ( ) = "SN_sha1" }
65
+ override string getRawAlgorithmName ( ) { result = instance .getTargetName ( ) }
11
66
12
- override string getRawAlgorithmName ( ) { result = "SN_sha1" }
67
+ override Crypto :: THashType getHashType ( ) { hash_ref_type_mapping ( instance , _ , result ) }
13
68
14
- override Crypto:: THashType getHashType ( ) { result instanceof Crypto:: SHA1 }
69
+ Element getInstance ( ) { result = instance }
70
+
71
+ override Location getLocation ( ) { result = instance .getLocation ( ) }
15
72
}
16
73
74
+ /**
75
+ * Data-flow configuration for key derivation algorithm flow to EVP_KDF_derive.
76
+ */
17
77
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
+ }
19
81
20
82
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
22
92
}
23
93
}
24
94
25
95
module AlgorithmToEVPKeyDeriveFlow = DataFlow:: Global< AlgorithmToEVPKeyDeriveConfig > ;
26
96
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 ( )
29
99
}
30
100
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
+ }
33
113
34
114
override Crypto:: Algorithm getAlgorithm ( ) { algorithm_to_EVP_KDF_derive ( result , this ) }
35
115
36
- Expr getAlgorithmArg ( ) { result = this .( FunctionCall ) .getArgument ( 3 ) }
116
+ Expr getAlgorithmArg ( ) { result = instance .getArgument ( 3 ) }
117
+
118
+ Expr getContextArg ( ) { result = instance .getArgument ( 0 ) }
37
119
}
38
120
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
+ }
40
127
128
+ /**
129
+ * `EVP_KDF_fetch` returns a key derivation algorithm.
130
+ */
41
131
class EVP_KDF_fetch_Call extends FunctionCall {
42
132
EVP_KDF_fetch_Call ( ) { this .getTarget ( ) .getName ( ) = "EVP_KDF_fetch" }
43
133
44
134
Expr getAlgorithmArg ( ) { result = this .getArgument ( 1 ) }
45
135
}
46
136
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
+ }
51
140
52
- override string toString ( ) { result = this . ( StringLiteral ) . toString ( ) }
141
+ predicate kdf_names ( string algo ) { algo = [ "HKDF" , "PKCS12KDF" , "PBKDF2" ] }
53
142
54
- string getValue ( ) { result = this .( StringLiteral ) .getValue ( ) }
143
+ class KDFAlgorithmStringLiteral extends StringLiteral {
144
+ KDFAlgorithmStringLiteral ( ) { kdf_names ( this .getValue ( ) .toUpperCase ( ) ) }
55
145
}
56
146
57
147
private module AlgorithmStringToFetchConfig implements DataFlow:: ConfigSig {
58
148
predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof KDFAlgorithmStringLiteral }
59
149
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 }
63
151
}
64
152
65
153
module AlgorithmStringToFetchFlow = DataFlow:: Global< AlgorithmStringToFetchConfig > ;
66
154
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 ) )
73
160
}
74
161
75
- class HKDF extends KeyDerivationAlgorithm , Crypto:: HKDF instanceof Expr {
162
+ /**
163
+ * HKDF key derivation algorithm.
164
+ */
165
+ class HKDF extends KeyDerivationAlgorithm , Crypto:: HKDF {
76
166
KDFAlgorithmStringLiteral origin ;
167
+ EVP_KDF_fetch_AlgorithmArg instance ;
77
168
78
- HKDF ( ) { algorithmStringToKDFFetchArgFlow ( "HKDF" , origin , this ) }
169
+ HKDF ( ) {
170
+ this = Crypto:: TKeyDerivationAlgorithm ( instance ) and
171
+ algorithmStringToKDFFetchArgFlow ( "HKDF" , origin , instance )
172
+ }
79
173
80
174
override string getRawAlgorithmName ( ) { result = origin .getValue ( ) }
81
175
@@ -84,19 +178,61 @@ module OpenSSLModel {
84
178
override Crypto:: LocatableElement getOrigin ( string name ) {
85
179
result = origin and name = origin .toString ( )
86
180
}
181
+
182
+ override Expr getInstance ( ) { result = origin }
87
183
}
88
184
89
- class PKCS12KDF extends KeyDerivationAlgorithm , Crypto:: PKCS12KDF instanceof Expr {
185
+ /**
186
+ * PBKDF2 key derivation algorithm.
187
+ */
188
+ class PBKDF2 extends KeyDerivationAlgorithm , Crypto:: PBKDF2 {
90
189
KDFAlgorithmStringLiteral origin ;
190
+ EVP_KDF_fetch_AlgorithmArg instance ;
91
191
92
- PKCS12KDF ( ) { algorithmStringToKDFFetchArgFlow ( "PKCS12KDF" , origin , this ) }
192
+ PBKDF2 ( ) {
193
+ this = Crypto:: TKeyDerivationAlgorithm ( instance ) and
194
+ algorithmStringToKDFFetchArgFlow ( "PBKDF2" , origin , instance )
195
+ }
93
196
94
197
override string getRawAlgorithmName ( ) { result = origin .getValue ( ) }
95
198
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
+ }
97
208
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 ) {
99
233
result = origin and name = origin .toString ( )
100
234
}
235
+
236
+ override Expr getInstance ( ) { result = instance }
101
237
}
102
238
}
0 commit comments