@@ -8,6 +8,7 @@ private import semmle.code.java.dataflow.DataFlow
88abstract class InsufficientKeySizeSource extends DataFlow:: Node {
99 /** Holds if this source has the specified `state`. */
1010 predicate hasState ( DataFlow:: FlowState state ) { state instanceof DataFlow:: FlowStateEmpty }
11+ //int getIntValue() { result = this.asExpr().(IntegerLiteral).getIntValue() }
1112}
1213
1314/** A sink for an insufficient key size. */
@@ -17,17 +18,17 @@ abstract class InsufficientKeySizeSink extends DataFlow::Node {
1718}
1819
1920/** A source for an insufficient key size (asymmetric-non-ec: RSA, DSA, DH). */
20- private class AsymmetricNonECSource extends InsufficientKeySizeSource {
21- AsymmetricNonECSource ( ) { getNodeIntValue ( this ) < 2048 }
21+ private class AsymmetricNonEcSource extends InsufficientKeySizeSource {
22+ AsymmetricNonEcSource ( ) { getNodeIntValue ( this ) < 2048 }
2223
2324 override predicate hasState ( DataFlow:: FlowState state ) { state = "2048" }
2425}
2526
2627/** A source for an insufficient key size (asymmetric-ec: EC%). */
27- private class AsymmetricECSource extends InsufficientKeySizeSource {
28- AsymmetricECSource ( ) {
28+ private class AsymmetricEcSource extends InsufficientKeySizeSource {
29+ AsymmetricEcSource ( ) {
2930 getNodeIntValue ( this ) < 256 or
30- getECKeySize ( this .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < 256 // for cases when the key size is embedded in the curve name
31+ getEcKeySize ( this .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < 256 // for cases when the key size is embedded in the curve name
3132 }
3233
3334 override predicate hasState ( DataFlow:: FlowState state ) { state = "256" }
@@ -40,15 +41,14 @@ private class SymmetricSource extends InsufficientKeySizeSource {
4041 override predicate hasState ( DataFlow:: FlowState state ) { state = "128" }
4142}
4243
43- // TODO: use `typeFlag` like with sinks below to include the size numbers in this predicate?
4444private int getNodeIntValue ( DataFlow:: Node node ) {
4545 result = node .asExpr ( ) .( IntegerLiteral ) .getIntValue ( )
4646}
4747
4848// TODO: check if any other regex should be added based on some MRVA results.
4949/** Returns the key size in the EC algorithm string */
5050bindingset [ algorithm]
51- private int getECKeySize ( string algorithm ) {
51+ private int getEcKeySize ( string algorithm ) {
5252 algorithm .matches ( "sec%" ) and // specification such as "secp256r1"
5353 result = algorithm .regexpCapture ( "sec[p|t](\\d+)[a-zA-Z].*" , 1 ) .toInt ( )
5454 or
@@ -60,96 +60,144 @@ private int getECKeySize(string algorithm) {
6060}
6161
6262/** A sink for an insufficient key size (asymmetric-non-ec). */
63- private class AsymmetricNonECSink extends InsufficientKeySizeSink {
64- AsymmetricNonECSink ( ) {
65- hasKeySizeInInitMethod ( this , "asymmetric-non-ec" )
63+ private class AsymmetricNonEcSink extends InsufficientKeySizeSink {
64+ AsymmetricNonEcSink ( ) {
65+ // hasKeySizeInInitMethod(this, "asymmetric-non-ec")
66+ // or
67+ //hasKeySizeInSpec(this, "asymmetric-non-ec")
68+ exists ( AsymmInitMethodAccess ma , AsymmKeyGen kg |
69+ kg .getAlgoName ( ) .matches ( [ "RSA" , "DSA" , "DH" ] ) and
70+ DataFlow:: localExprFlow ( kg , ma .getQualifier ( ) ) and
71+ this .asExpr ( ) = ma .getKeySizeArg ( )
72+ )
6673 or
67- hasKeySizeInSpec ( this )
74+ exists ( AsymmetricNonEcSpec s | this . asExpr ( ) = s . getKeySizeArg ( ) )
6875 }
6976
7077 override predicate hasState ( DataFlow:: FlowState state ) { state = "2048" }
7178}
7279
73- private class AsymmetricNonECSpec extends RefType {
74- AsymmetricNonECSpec ( ) {
75- this instanceof RsaKeyGenParameterSpec or
76- this instanceof DsaGenParameterSpec or
77- this instanceof DhGenParameterSpec
78- }
79- }
80-
8180/** A sink for an insufficient key size (asymmetric-ec). */
82- private class AsymmetricECSink extends InsufficientKeySizeSink {
83- AsymmetricECSink ( ) {
84- hasKeySizeInInitMethod ( this , "asymmetric-ec" )
81+ private class AsymmetricEcSink extends InsufficientKeySizeSink {
82+ AsymmetricEcSink ( ) {
83+ // hasKeySizeInInitMethod(this, "asymmetric-ec")
84+ // or
85+ //hasKeySizeInSpec(this, "asymmetric-ec")
86+ exists ( AsymmInitMethodAccess ma , AsymmKeyGen kg |
87+ kg .getAlgoName ( ) .matches ( "EC%" ) and
88+ DataFlow:: localExprFlow ( kg , ma .getQualifier ( ) ) and
89+ this .asExpr ( ) = ma .getKeySizeArg ( )
90+ )
8591 or
86- hasKeySizeInSpec ( this )
92+ exists ( AsymmetricEcSpec s | this . asExpr ( ) = s . getKeySizeArg ( ) )
8793 }
8894
8995 override predicate hasState ( DataFlow:: FlowState state ) { state = "256" }
9096}
9197
9298/** A sink for an insufficient key size (symmetric). */
9399private class SymmetricSink extends InsufficientKeySizeSink {
94- SymmetricSink ( ) { hasKeySizeInInitMethod ( this , "symmetric" ) }
100+ SymmetricSink ( ) {
101+ //hasKeySizeInInitMethod(this, "symmetric")
102+ exists ( SymmInitMethodAccess ma , SymmKeyGen kg |
103+ kg .getAlgoName ( ) = "AES" and
104+ DataFlow:: localExprFlow ( kg , ma .getQualifier ( ) ) and
105+ this .asExpr ( ) = ma .getKeySizeArg ( )
106+ )
107+ }
95108
96109 override predicate hasState ( DataFlow:: FlowState state ) { state = "128" }
97110}
98111
99112// TODO: rethink the predicate name; also think about whether this could/should be a class instead; or a predicate within the sink class so can do sink.predicate()...
100113// TODO: can prbly re-work way using the typeFlag to be better and less repetitive
101- private predicate hasKeySizeInInitMethod ( DataFlow:: Node node , string typeFlag ) {
102- exists ( MethodAccess ma , JavaxCryptoAlgoSpec jcaSpec |
103- (
104- ma .getMethod ( ) instanceof KeyGeneratorInitMethod and typeFlag = "symmetric"
105- or
106- ma .getMethod ( ) instanceof KeyPairGeneratorInitMethod and typeFlag .matches ( "asymmetric%" )
107- ) and
108- (
109- jcaSpec instanceof JavaxCryptoKeyGenerator and typeFlag = "symmetric"
110- or
111- jcaSpec instanceof JavaSecurityKeyPairGenerator and typeFlag .matches ( "asymmetric%" )
112- ) and
113- (
114- getAlgoName ( jcaSpec ) = "AES" and typeFlag = "symmetric"
115- or
116- getAlgoName ( jcaSpec ) .matches ( [ "RSA" , "DSA" , "DH" ] ) and typeFlag = "asymmetric-non-ec"
117- or
118- getAlgoName ( jcaSpec ) .matches ( "EC%" ) and typeFlag = "asymmetric-ec"
119- ) and
120- DataFlow:: localExprFlow ( jcaSpec , ma .getQualifier ( ) ) and
121- node .asExpr ( ) = ma .getArgument ( 0 )
122- )
123- }
124-
125- // TODO: this predicate is just a poc for more code condensing; redo this
126- private string getAlgoName ( JavaxCryptoAlgoSpec jca ) {
127- result = jca .getAlgoSpec ( ) .( StringLiteral ) .getValue ( ) .toUpperCase ( )
114+ // private predicate hasKeySizeInInitMethod(DataFlow::Node node, string typeFlag) {
115+ // exists(MethodAccess ma, JavaxCryptoAlgoSpec jcaSpec |
116+ // (
117+ // ma.getMethod() instanceof KeyGeneratorInitMethod and typeFlag = "symmetric"
118+ // or
119+ // ma.getMethod() instanceof KeyPairGeneratorInitMethod and typeFlag.matches("asymmetric%")
120+ // ) and
121+ // (
122+ // jcaSpec instanceof JavaxCryptoKeyGenerator and typeFlag = "symmetric"
123+ // or
124+ // jcaSpec instanceof JavaSecurityKeyPairGenerator and typeFlag.matches("asymmetric%")
125+ // ) and
126+ // (
127+ // getAlgoName(jcaSpec) = "AES" and typeFlag = "symmetric"
128+ // or
129+ // getAlgoName(jcaSpec).matches(["RSA", "DSA", "DH"]) and typeFlag = "asymmetric-non-ec"
130+ // or
131+ // getAlgoName(jcaSpec).matches("EC%") and typeFlag = "asymmetric-ec"
132+ // ) and
133+ // DataFlow::localExprFlow(jcaSpec, ma.getQualifier()) and
134+ // node.asExpr() = ma.getArgument(0)
135+ // )
136+ // }
137+ // // TODO: this predicate is just a poc for more code condensing; redo this
138+ // private string getAlgoName(JavaxCryptoAlgoSpec jca) {
139+ // result = jca.getAlgoSpec().(StringLiteral).getValue().toUpperCase()
140+ // }
141+ abstract class InitMethodAccess extends MethodAccess {
142+ Argument getKeySizeArg ( ) { result = this .getArgument ( 0 ) }
143+ }
144+
145+ class AsymmInitMethodAccess extends InitMethodAccess {
146+ AsymmInitMethodAccess ( ) { this .getMethod ( ) instanceof KeyPairGeneratorInitMethod }
147+ }
148+
149+ class SymmInitMethodAccess extends InitMethodAccess {
150+ SymmInitMethodAccess ( ) { this .getMethod ( ) instanceof KeyGeneratorInitMethod }
151+ }
152+
153+ abstract class KeyGen extends JavaxCryptoAlgoSpec {
154+ string getAlgoName ( ) { result = this .getAlgoSpec ( ) .( StringLiteral ) .getValue ( ) .toUpperCase ( ) }
155+ }
156+
157+ class AsymmKeyGen extends KeyGen {
158+ AsymmKeyGen ( ) { this instanceof JavaSecurityKeyPairGenerator }
159+
160+ // ! this override is repetitive...
161+ override Expr getAlgoSpec ( ) { result = this .( MethodAccess ) .getArgument ( 0 ) }
162+ }
163+
164+ class SymmKeyGen extends KeyGen {
165+ SymmKeyGen ( ) { this instanceof JavaxCryptoKeyGenerator }
166+
167+ // ! this override is repetitive...
168+ override Expr getAlgoSpec ( ) { result = this .( MethodAccess ) .getArgument ( 0 ) }
128169}
129170
130171// TODO: rethink the predicate name; also think about whether this could/should be a class instead; or a predicate within the sink class so can do sink.predicate()...
131172// TODO: can prbly re-work way using the typeFlag to be better and less repetitive...
132- private predicate hasKeySizeInSpec ( DataFlow:: Node node ) {
133- exists ( ClassInstanceExpr paramSpec |
134- (
135- paramSpec .getConstructedType ( ) instanceof AsymmetricNonECSpec //and
136- or
137- //typeFlag = "asymmetric-non-ec"
138- paramSpec .getConstructedType ( ) instanceof EcGenParameterSpec //and
139- //typeFlag = "asymmetric-ec"
140- ) and
141- node .asExpr ( ) = paramSpec .getArgument ( 0 )
142- )
143- }
144-
145- // ! use below instead of/in above??
146- class Spec extends ClassInstanceExpr {
147- Spec ( ) {
148- this .getConstructedType ( ) instanceof AsymmetricNonECSpec or
149- this .getConstructedType ( ) instanceof EcGenParameterSpec
173+ // private predicate hasKeySizeInSpec(DataFlow::Node node, string typeFlag) {
174+ // exists(ClassInstanceExpr paramSpec |
175+ // (
176+ // paramSpec.getConstructedType() instanceof AsymmetricNonEcSpec and
177+ // typeFlag = "asymmetric-non-ec"
178+ // or
179+ // paramSpec.getConstructedType() instanceof EcGenParameterSpec and
180+ // typeFlag = "asymmetric-ec"
181+ // ) and
182+ // node.asExpr() = paramSpec.getArgument(0)
183+ // )
184+ // }
185+ // ! use below instead of/in above?? (actually I don't think I need any of this, can just use AsymmetricNonEcSpec and EcGenParameterSpec directly???)
186+ // Algo spec
187+ abstract class AsymmetricAlgoSpec extends ClassInstanceExpr {
188+ Argument getKeySizeArg ( ) { result = this .getArgument ( 0 ) }
189+ }
190+
191+ class AsymmetricNonEcSpec extends AsymmetricAlgoSpec {
192+ AsymmetricNonEcSpec ( ) {
193+ this .getConstructedType ( ) instanceof RsaKeyGenParameterSpec or
194+ this .getConstructedType ( ) instanceof DsaGenParameterSpec or
195+ this .getConstructedType ( ) instanceof DhGenParameterSpec
150196 }
197+ }
151198
152- Argument getKeySizeArg ( ) { result = this .getArgument ( 0 ) }
199+ class AsymmetricEcSpec extends AsymmetricAlgoSpec {
200+ AsymmetricEcSpec ( ) { this .getConstructedType ( ) instanceof EcGenParameterSpec }
153201}
154202// TODO:
155203// todo #0: look into use of specs without keygen objects; should spec not be a sink in these cases?
0 commit comments