11import semmle.code.java.security.Encryption
2- import semmle.code.java.dataflow.TaintTracking2
3- import semmle.code.java.dataflow.TaintTracking
42import semmle.code.java.dataflow.DataFlow
3+ import semmle.code.java.dataflow.DataFlow2
54
6- // ******* DATAFLOW BELOW *************************************************************************
75/**
86 * Asymmetric (RSA, DSA, DH) key length data flow tracking configuration.
97 */
10- class AsymmetricKeyTrackingConfiguration extends DataFlow2:: Configuration {
11- AsymmetricKeyTrackingConfiguration ( ) { this = "AsymmetricKeyTrackingConfiguration " }
8+ class AsymmetricNonECKeyTrackingConfiguration extends DataFlow2:: Configuration {
9+ AsymmetricNonECKeyTrackingConfiguration ( ) { this = "AsymmetricNonECKeyTrackingConfiguration " }
1210
1311 override predicate isSource ( DataFlow:: Node source ) {
14- // ! may need to change below to still use `keysize` variable as the source, not the spec
15- // ! also need to look into specs for DSA and DH more
16- exists ( ClassInstanceExpr rsaGenParamSpec |
17- rsaGenParamSpec .getConstructedType ( ) instanceof RSAGenParameterSpec and
18- rsaGenParamSpec .getArgument ( 0 ) .( CompileTimeConstantExpr ) .getIntValue ( ) < 2048 and
19- source .asExpr ( ) = rsaGenParamSpec
20- )
21- or
2212 source .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < 2048
2313 }
2414
@@ -34,25 +24,36 @@ class AsymmetricKeyTrackingConfiguration extends DataFlow2::Configuration {
3424 dest .getNode ( ) .asExpr ( ) = ma .getQualifier ( ) and
3525 kpgConfig .hasFlowPath ( source , dest )
3626 ) and
37- sink .asExpr ( ) = ma .getArgument ( 0 ) // ! todo: add spec as a sink
27+ sink .asExpr ( ) = ma .getArgument ( 0 )
28+ )
29+ or
30+ // TODO: combine below three for less duplicated code
31+ exists ( ClassInstanceExpr rsaKeyGenParamSpec |
32+ rsaKeyGenParamSpec .getConstructedType ( ) instanceof RSAKeyGenParameterSpec and
33+ sink .asExpr ( ) = rsaKeyGenParamSpec .getArgument ( 0 )
34+ )
35+ or
36+ exists ( ClassInstanceExpr dsaGenParamSpec |
37+ dsaGenParamSpec .getConstructedType ( ) instanceof DSAGenParameterSpec and
38+ sink .asExpr ( ) = dsaGenParamSpec .getArgument ( 0 )
39+ )
40+ or
41+ exists ( ClassInstanceExpr dhGenParamSpec |
42+ dhGenParamSpec .getConstructedType ( ) instanceof DHGenParameterSpec and
43+ sink .asExpr ( ) = dhGenParamSpec .getArgument ( 0 )
3844 )
3945 }
4046}
4147
4248/**
4349 * Asymmetric (EC) key length data flow tracking configuration.
4450 */
45- class AsymmetricECCKeyTrackingConfiguration extends DataFlow2:: Configuration {
46- AsymmetricECCKeyTrackingConfiguration ( ) { this = "AsymmetricECCKeyTrackingConfiguration " }
51+ class AsymmetricECKeyTrackingConfiguration extends DataFlow2:: Configuration {
52+ AsymmetricECKeyTrackingConfiguration ( ) { this = "AsymmetricECKeyTrackingConfiguration " }
4753
4854 override predicate isSource ( DataFlow:: Node source ) {
49- // ! may need to change below to still use `keysize` variable as the source, not the spec
50- exists ( ClassInstanceExpr ecGenParamSpec |
51- getECKeySize ( ecGenParamSpec .getArgument ( 0 ) .( StringLiteral ) .getValue ( ) ) < 256 and
52- source .asExpr ( ) = ecGenParamSpec
53- )
54- or
55- source .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < 256
55+ source .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < 256 or
56+ getECKeySize ( source .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < 256 // need this for the cases when the key size is embedded in the curve name.
5657 }
5758
5859 override predicate isSink ( DataFlow:: Node sink ) {
@@ -69,14 +70,20 @@ class AsymmetricECCKeyTrackingConfiguration extends DataFlow2::Configuration {
6970 ) and
7071 sink .asExpr ( ) = ma .getArgument ( 0 )
7172 )
73+ or
74+ exists ( ClassInstanceExpr ecGenParamSpec |
75+ ecGenParamSpec .getConstructedType ( ) instanceof ECGenParameterSpec and
76+ //getECKeySize(ecGenParamSpec.getArgument(0).(StringLiteral).getValue()) < 256 and
77+ sink .asExpr ( ) = ecGenParamSpec .getArgument ( 0 )
78+ )
7279 }
7380}
7481
7582/**
7683 * Symmetric (AES) key length data flow tracking configuration.
7784 */
7885class SymmetricKeyTrackingConfiguration extends DataFlow2:: Configuration {
79- SymmetricKeyTrackingConfiguration ( ) { this = "SymmetricKeyTrackingConfiguration2 " }
86+ SymmetricKeyTrackingConfiguration ( ) { this = "SymmetricKeyTrackingConfiguration " }
8087
8188 override predicate isSource ( DataFlow:: Node source ) {
8289 source .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < 128
@@ -99,14 +106,9 @@ class SymmetricKeyTrackingConfiguration extends DataFlow2::Configuration {
99106 }
100107}
101108
102- // ! below predicate doesn't work
103- // predicate hasInsufficientKeySize2(DataFlow::PathNode source, DataFlow::PathNode sink) {
104- // exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlowPath(source, sink))
105- // or
106- // exists(SymmetricKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink))
107- // }
108- // ******** Need the below models for the above configs ********
109- /** Taint configuration tracking flow from a key generator to a `init` method call. */
109+ // ********************** Need the below models for the above configs **********************
110+ // todo: move some/all of below to Encryption.qll or elsewhere?
111+ /** Data flow configuration tracking flow from a key generator to an `init` method call. */
110112private class KeyGeneratorInitConfiguration extends DataFlow:: Configuration {
111113 KeyGeneratorInitConfiguration ( ) { this = "KeyGeneratorInitConfiguration" }
112114
@@ -122,10 +124,7 @@ private class KeyGeneratorInitConfiguration extends DataFlow::Configuration {
122124 }
123125}
124126
125- /**
126- * Taint configuration tracking flow from a keypair generator to
127- * an `initialize` method call.
128- */
127+ /** Data flow configuration tracking flow from a keypair generator to an `initialize` method call. */
129128private class KeyPairGeneratorInitConfiguration extends DataFlow:: Configuration {
130129 KeyPairGeneratorInitConfiguration ( ) { this = "KeyPairGeneratorInitConfiguration" }
131130
@@ -141,28 +140,24 @@ private class KeyPairGeneratorInitConfiguration extends DataFlow::Configuration
141140 }
142141}
143142
144- // ! move some/all of below to Encryption.qll or elsewhere?
145143/** The Java class `java.security.spec.ECGenParameterSpec`. */
146144private class ECGenParameterSpec extends RefType {
147145 ECGenParameterSpec ( ) { this .hasQualifiedName ( "java.security.spec" , "ECGenParameterSpec" ) }
148146}
149147
150- /** The Java class `java.security.spec.ECGenParameterSpec `. */
151- private class RSAGenParameterSpec extends RefType {
152- RSAGenParameterSpec ( ) { this .hasQualifiedName ( "java.security.spec" , "RSAKeyGenParameterSpec" ) }
148+ /** The Java class `java.security.spec.RSAKeyGenParameterSpec `. */
149+ private class RSAKeyGenParameterSpec extends RefType {
150+ RSAKeyGenParameterSpec ( ) { this .hasQualifiedName ( "java.security.spec" , "RSAKeyGenParameterSpec" ) }
153151}
154152
155- /** Returns the key size in the EC algorithm string */
156- bindingset [ algorithm]
157- private int getECKeySize ( string algorithm ) {
158- algorithm .matches ( "sec%" ) and // specification such as "secp256r1"
159- result = algorithm .regexpCapture ( "sec[p|t](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
160- or
161- algorithm .matches ( "X9.62%" ) and //specification such as "X9.62 prime192v2"
162- result = algorithm .regexpCapture ( "X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
163- or
164- ( algorithm .matches ( "prime%" ) or algorithm .matches ( "c2tnb%" ) ) and //specification such as "prime192v2"
165- result = algorithm .regexpCapture ( ".*[a-zA-Z](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
153+ /** The Java class `java.security.spec.DSAGenParameterSpec`. */
154+ private class DSAGenParameterSpec extends RefType {
155+ DSAGenParameterSpec ( ) { this .hasQualifiedName ( "java.security.spec" , "DSAGenParameterSpec" ) }
156+ }
157+
158+ /** The Java class `javax.crypto.spec.DHGenParameterSpec`. */
159+ private class DHGenParameterSpec extends RefType {
160+ DHGenParameterSpec ( ) { this .hasQualifiedName ( "javax.crypto.spec" , "DHGenParameterSpec" ) }
166161}
167162
168163/** The `init` method declared in `javax.crypto.KeyGenerator`. */
@@ -181,21 +176,21 @@ private class KeyPairGeneratorInitMethod extends Method {
181176 }
182177}
183178
184- // ******* DATAFLOW ABOVE *************************************************************************
185- // ************************************************************************************************
186- // ************************************************************************************************
187- // ******* OLD/UNUSED OR EXPERIMENTAL CODE BELOW **************************************************
188- class UnsafeSymmetricKeySize extends IntegerLiteral {
189- UnsafeSymmetricKeySize ( ) { this .getIntValue ( ) < 128 }
190- }
191-
192- class UnsafeAsymmetricKeySize extends IntegerLiteral {
193- UnsafeAsymmetricKeySize ( ) { this .getIntValue ( ) < 2048 }
179+ /** Returns the key size in the EC algorithm string */
180+ bindingset [ algorithm]
181+ private int getECKeySize ( string algorithm ) {
182+ algorithm .matches ( "sec%" ) and // specification such as "secp256r1"
183+ result = algorithm .regexpCapture ( "sec[p|t](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
184+ or
185+ algorithm .matches ( "X9.62%" ) and //specification such as "X9.62 prime192v2"
186+ result = algorithm .regexpCapture ( "X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
187+ or
188+ ( algorithm .matches ( "prime%" ) or algorithm .matches ( "c2tnb%" ) ) and //specification such as "prime192v2"
189+ result = algorithm .regexpCapture ( ".*[a-zA-Z](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
194190}
191+ // ******* DATAFLOW ABOVE *************************************************************************
195192// TODO:
196- // ! todo #0a: find a better way to combine the two needed taint-tracking configs so can go back to having a path-graph...
197- // ! todo #0b: possible to combine the 3 dataflow configs?
198193// todo #1: make representation of source that can be shared across the configs
199194// todo #2: make representation of sink that can be shared across the configs
200195// todo #3: make list of algo names more easily reusable (either as constant-type variable at top of file, or model as own class to share, etc.)
201- // todo #4: refactor to be more like the Python version? (or not possible because of lack of DataFlow::Node for void method in Java?)
196+ // todo #4: refactor to be more like the Python (or C#) version? (or not possible because of lack of DataFlow::Node for void method in Java?)
0 commit comments