@@ -15,13 +15,10 @@ import java
15
15
import semmle.code.java.controlflow.Guards
16
16
import semmle.code.java.dataflow.TaintTracking
17
17
import semmle.code.java.dataflow.TaintTracking2
18
+ import semmle.code.java.dataflow.DataFlow3
18
19
import semmle.code.java.dataflow.FlowSources
19
20
import DataFlow:: PathGraph
20
21
21
- private class ByteBuffer extends Class {
22
- ByteBuffer ( ) { hasQualifiedName ( "java.nio" , "ByteBuffer" ) }
23
- }
24
-
25
22
/** A method call that produces cryptographic result. */
26
23
abstract private class ProduceCryptoCall extends MethodAccess {
27
24
Expr output ;
@@ -54,23 +51,51 @@ private class ProduceSignatureCall extends ProduceCryptoCall {
54
51
}
55
52
}
56
53
54
+ /**
55
+ * A config that tracks data flow from initializing a cipher for encryption
56
+ * to producing a ciphertext using this cipher.
57
+ */
58
+ private class InitializeEncryptorConfig extends DataFlow3:: Configuration {
59
+ InitializeEncryptorConfig ( ) { this = "InitializeEncryptorConfig" }
60
+
61
+ override predicate isSource ( DataFlow:: Node source ) {
62
+ exists ( MethodAccess ma |
63
+ ma .getMethod ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "init" ) and
64
+ ma .getArgument ( 0 ) .( VarAccess ) .getVariable ( ) .hasName ( "ENCRYPT_MODE" ) and
65
+ ma .getQualifier ( ) = source .asExpr ( )
66
+ )
67
+ }
68
+
69
+ override predicate isSink ( DataFlow:: Node sink ) {
70
+ exists ( MethodAccess ma |
71
+ ma .getMethod ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "doFinal" ) and
72
+ ma .getQualifier ( ) = sink .asExpr ( )
73
+ )
74
+ }
75
+ }
76
+
57
77
/** A method call that produces a ciphertext. */
58
78
private class ProduceCiphertextCall extends ProduceCryptoCall {
59
79
ProduceCiphertextCall ( ) {
60
- getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" ) and
61
- (
62
- getMethod ( ) .hasStringSignature ( [ "doFinal()" , "doFinal(byte[])" , "doFinal(byte[], int, int)" ] ) and
63
- this = output
64
- or
65
- getMethod ( ) .hasStringSignature ( "doFinal(byte[], int)" ) and getArgument ( 0 ) = output
66
- or
67
- getMethod ( )
68
- .hasStringSignature ( [
69
- "doFinal(byte[], int, int, byte[])" , "doFinal(byte[], int, int, byte[], int)"
70
- ] ) and
71
- getArgument ( 3 ) = output
72
- or
73
- getMethod ( ) .hasStringSignature ( "doFinal(ByteBuffer, ByteBuffer)" ) and getArgument ( 1 ) = output
80
+ exists ( Method m | m = this .getMethod ( ) |
81
+ m .getDeclaringType ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" ) and
82
+ (
83
+ m .hasStringSignature ( [ "doFinal()" , "doFinal(byte[])" , "doFinal(byte[], int, int)" ] ) and
84
+ this = output
85
+ or
86
+ m .hasStringSignature ( "doFinal(byte[], int)" ) and getArgument ( 0 ) = output
87
+ or
88
+ m .hasStringSignature ( [
89
+ "doFinal(byte[], int, int, byte[])" , "doFinal(byte[], int, int, byte[], int)"
90
+ ] ) and
91
+ getArgument ( 3 ) = output
92
+ or
93
+ m .hasStringSignature ( "doFinal(ByteBuffer, ByteBuffer)" ) and
94
+ getArgument ( 1 ) = output
95
+ )
96
+ ) and
97
+ exists ( InitializeEncryptorConfig config |
98
+ config .hasFlowTo ( DataFlow3:: exprNode ( this .getQualifier ( ) ) )
74
99
)
75
100
}
76
101
}
@@ -168,6 +193,7 @@ private class CryptoOperationSource extends DataFlow::Node {
168
193
}
169
194
}
170
195
196
+ /** Methods that use a non-constant-time algorithm for comparing inputs. */
171
197
private class NonConstantTimeEqualsCall extends MethodAccess {
172
198
NonConstantTimeEqualsCall ( ) {
173
199
getMethod ( )
@@ -176,6 +202,7 @@ private class NonConstantTimeEqualsCall extends MethodAccess {
176
202
}
177
203
}
178
204
205
+ /** Static methods that use a non-constant-time algorithm for comparing inputs. */
179
206
private class NonConstantTimeComparisonCall extends StaticMethodAccess {
180
207
NonConstantTimeComparisonCall ( ) {
181
208
getMethod ( ) .hasQualifiedName ( "java.util" , "Arrays" , [ "equals" , "deepEquals" ] ) or
0 commit comments