11/**
22 * @name Using a non-constant time algorithm for comparing results of a cryptographic operation
33 * @description When comparing results of a cryptographic operation, a constant time algorithm should be used.
4- * Otherwise, an attacker may be able to implement a timing attack.
4+ * Otherwise, attackers may be able to implement a timing attack if they can control input .
55 * A successful attack may result in leaking secrets or authentication bypass.
66 * @kind path-problem
77 * @problem.severity warning
@@ -21,12 +21,15 @@ private class ByteBuffer extends Class {
2121 ByteBuffer ( ) { hasQualifiedName ( "java.nio" , "ByteBuffer" ) }
2222}
2323
24+ /** A method call that produces cryptographic result. */
2425abstract private class ProduceCryptoCall extends MethodAccess {
2526 Expr output ;
2627
28+ /** Return the result of cryptographic operation. */
2729 Expr output ( ) { result = output }
2830}
2931
32+ /** A method call that produces a MAC. */
3033private class ProduceMacCall extends ProduceCryptoCall {
3134 ProduceMacCall ( ) {
3235 getMethod ( ) .hasQualifiedName ( "javax.crypto" , "Mac" , "doFinal" ) and
@@ -38,6 +41,7 @@ private class ProduceMacCall extends ProduceCryptoCall {
3841 }
3942}
4043
44+ /** A method call that produces a signature. */
4145private class ProduceSignatureCall extends ProduceCryptoCall {
4246 ProduceSignatureCall ( ) {
4347 getMethod ( ) .hasQualifiedName ( "java.security" , "Signature" , "sign" ) and
@@ -49,6 +53,7 @@ private class ProduceSignatureCall extends ProduceCryptoCall {
4953 }
5054}
5155
56+ /** A method call that produces a ciphertext. */
5257private class ProduceCiphertextCall extends ProduceCryptoCall {
5358 ProduceCiphertextCall ( ) {
5459 getMethod ( ) .hasQualifiedName ( "javax.crypto" , "Cipher" , "doFinal" ) and
@@ -63,6 +68,10 @@ private class ProduceCiphertextCall extends ProduceCryptoCall {
6368 }
6469}
6570
71+ /**
72+ * A config that tracks data flow from remote user input to a cryptographic operation
73+ * such as cipher, MAC or signature.
74+ */
6675private class UserInputInCryptoOperationConfig extends TaintTracking2:: Configuration {
6776 UserInputInCryptoOperationConfig ( ) { this = "UserInputInCryptoOperationConfig" }
6877
@@ -72,6 +81,7 @@ private class UserInputInCryptoOperationConfig extends TaintTracking2::Configura
7281 exists ( ProduceCryptoCall call | call .getQualifier ( ) = sink .asExpr ( ) )
7382 }
7483
84+ /** Holds if `fromNode` to `toNode` is a dataflow step that updates a cryptographic operation. */
7585 override predicate isAdditionalTaintStep ( DataFlow2:: Node fromNode , DataFlow2:: Node toNode ) {
7686 exists ( MethodAccess call , Method m |
7787 m = call .getMethod ( ) and
@@ -90,6 +100,7 @@ private class UserInputInCryptoOperationConfig extends TaintTracking2::Configura
90100 }
91101}
92102
103+ /** A source that produces result of cryptographic operation. */
93104private class CryptoOperationSource extends DataFlow:: Node {
94105 Expr cryptoOperation ;
95106
@@ -99,6 +110,7 @@ private class CryptoOperationSource extends DataFlow::Node {
99110 )
100111 }
101112
113+ /** Holds if remote user input was used in the cryptographic operation. */
102114 predicate includesUserInput ( ) {
103115 exists (
104116 DataFlow2:: PathNode source , DataFlow2:: PathNode sink , UserInputInCryptoOperationConfig config
@@ -128,6 +140,10 @@ private class NonConstantTimeComparisonCall extends StaticMethodAccess {
128140 }
129141}
130142
143+ /**
144+ * A config that tracks data flow from remote user input to methods
145+ * that compare inputs using a non-constant time algorithm.
146+ */
131147private class UserInputInComparisonConfig extends TaintTracking2:: Configuration {
132148 UserInputInComparisonConfig ( ) { this = "UserInputInComparisonConfig" }
133149
@@ -142,15 +158,14 @@ private class UserInputInComparisonConfig extends TaintTracking2::Configuration
142158 }
143159}
144160
161+ /** Holds if `expr` looks like a constant. */
145162private predicate looksLikeConstant ( Expr expr ) {
146163 expr .isCompileTimeConstant ( )
147164 or
148165 expr .( VarAccess ) .getVariable ( ) .isFinal ( ) and expr .getType ( ) instanceof TypeString
149166}
150167
151- /**
152- * A sink that compares input using a non-constant time algorithm.
153- */
168+ /** A sink that compares input using a non-constant time algorithm. */
154169private class NonConstantTimeComparisonSink extends DataFlow:: Node {
155170 Expr anotherParameter ;
156171
@@ -176,6 +191,7 @@ private class NonConstantTimeComparisonSink extends DataFlow::Node {
176191 not looksLikeConstant ( anotherParameter )
177192 }
178193
194+ /** Holds if remote user input was used in the comparison. */
179195 predicate includesUserInput ( ) {
180196 exists ( UserInputInComparisonConfig config |
181197 config .hasFlowTo ( DataFlow2:: exprNode ( anotherParameter ) )
0 commit comments