33private import semmle.code.java.security.Encryption
44private import semmle.code.java.dataflow.DataFlow
55private import semmle.code.java.security.internal.EncryptionKeySizes
6+ import codeql.util.Either
7+
8+ /** A minimum recommended key size for some algorithm. */
9+ abstract class MinimumKeySize extends int {
10+ bindingset [ this ]
11+ MinimumKeySize ( ) { any ( ) }
12+
13+ /** Gets a textual representation of this element. */
14+ string toString ( ) { result = super .toString ( ) }
15+ }
16+
17+ /**
18+ * A class of algorithms for which a key size smaller than the recommended key
19+ * size might be embedded in the algorithm name.
20+ */
21+ abstract class AlgorithmKind extends string {
22+ bindingset [ this ]
23+ AlgorithmKind ( ) { any ( ) }
24+
25+ /** Gets a textual representation of this element. */
26+ string toString ( ) { result = super .toString ( ) }
27+ }
28+
29+ /**
30+ * A key size that is greater than the tracked value and equal to the minimum
31+ * recommended key size for some algorithm, or a kind of algorithm for which the
32+ * tracked string indicates a too small key size.
33+ */
34+ final class KeySizeState = Either< MinimumKeySize , AlgorithmKind > :: Either ;
635
736/** A source for an insufficient key size. */
837abstract class InsufficientKeySizeSource extends DataFlow:: Node {
938 /** Holds if this source has the specified `state`. */
10- predicate hasState ( DataFlow :: FlowState state ) { state instanceof DataFlow :: FlowStateEmpty }
39+ abstract predicate hasState ( KeySizeState state ) ;
1140}
1241
1342/** A sink for an insufficient key size. */
1443abstract class InsufficientKeySizeSink extends DataFlow:: Node {
15- /** Holds if this sink has the specified `state`. */
16- predicate hasState ( DataFlow:: FlowState state ) { state instanceof DataFlow:: FlowStateEmpty }
44+ /** Holds if this sink accepts the specified `state`. */
45+ final predicate hasState ( KeySizeState state ) {
46+ state .asLeft ( ) <= this .minimumKeySize ( ) or this .algorithmKind ( state .asRight ( ) )
47+ }
48+
49+ /** Gets the minimum recommended key size. */
50+ abstract int minimumKeySize ( ) ;
51+
52+ /**
53+ * Holds if this sink recommends a keysize that is greater than the value in a
54+ * source with the given algorithm kind.
55+ */
56+ predicate algorithmKind ( AlgorithmKind kind ) { none ( ) }
57+ }
58+
59+ /** A source for an insufficient key size used in some algorithm. */
60+ private class IntegerLiteralSource extends InsufficientKeySizeSource {
61+ private int value ;
62+
63+ IntegerLiteralSource ( ) { this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) = value }
64+
65+ override predicate hasState ( KeySizeState state ) {
66+ state .asLeft ( ) = min ( MinimumKeySize m | value < m )
67+ }
1768}
1869
1970/** Provides models for asymmetric cryptography. */
2071private module Asymmetric {
2172 /** Provides models for non-elliptic-curve asymmetric cryptography. */
2273 private module NonEllipticCurve {
23- /** A source for an insufficient key size used in RSA, DSA, and DH algorithms. */
24- private class Source extends InsufficientKeySizeSource {
25- string algoName ;
26-
27- Source ( ) { this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < getMinKeySize ( algoName ) }
28-
29- override predicate hasState ( DataFlow:: FlowState state ) {
30- state = getMinKeySize ( algoName ) .toString ( )
31- }
74+ private class NonEllipticCurveKeySize extends MinimumKeySize {
75+ NonEllipticCurveKeySize ( ) { this = getMinKeySize ( _) }
3276 }
3377
3478 /** A sink for an insufficient key size used in RSA, DSA, and DH algorithms. */
@@ -46,9 +90,7 @@ private module Asymmetric {
4690 exists ( Spec spec | this .asExpr ( ) = spec .getKeySizeArg ( ) and algoName = spec .getAlgoName ( ) )
4791 }
4892
49- override predicate hasState ( DataFlow:: FlowState state ) {
50- state = getMinKeySize ( algoName ) .toString ( )
51- }
93+ override int minimumKeySize ( ) { result = getMinKeySize ( algoName ) }
5294 }
5395
5496 /** Returns the minimum recommended key size for RSA, DSA, and DH algorithms. */
@@ -88,16 +130,24 @@ private module Asymmetric {
88130
89131 /** Provides models for elliptic-curve asymmetric cryptography. */
90132 private module EllipticCurve {
133+ private class EllipticCurveKeySize extends MinimumKeySize {
134+ EllipticCurveKeySize ( ) { this = getMinKeySize ( ) }
135+ }
136+
137+ private class EllipticCurveKind extends AlgorithmKind {
138+ EllipticCurveKind ( ) { this = "EC" }
139+ }
140+
91141 /** A source for an insufficient key size used in elliptic curve (EC) algorithms. */
92142 private class Source extends InsufficientKeySizeSource {
93143 Source ( ) {
94- this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < getMinKeySize ( )
95- or
96144 // the below is needed for cases when the key size is embedded in the curve name
97145 getKeySize ( this .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < getMinKeySize ( )
98146 }
99147
100- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
148+ override predicate hasState ( KeySizeState state ) {
149+ state .asRight ( ) instanceof EllipticCurveKind
150+ }
101151 }
102152
103153 /** A sink for an insufficient key size used in elliptic curve (EC) algorithms. */
@@ -112,7 +162,9 @@ private module Asymmetric {
112162 exists ( Spec s | this .asExpr ( ) = s .getKeySizeArg ( ) )
113163 }
114164
115- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
165+ override int minimumKeySize ( ) { result = getMinKeySize ( ) }
166+
167+ override predicate algorithmKind ( AlgorithmKind kind ) { kind instanceof EllipticCurveKind }
116168 }
117169
118170 /** Returns the minimum recommended key size for elliptic curve (EC) algorithms. */
@@ -176,11 +228,8 @@ private module Asymmetric {
176228
177229/** Provides models for symmetric cryptography. */
178230private module Symmetric {
179- /** A source for an insufficient key size used in AES algorithms. */
180- private class Source extends InsufficientKeySizeSource {
181- Source ( ) { this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < getMinKeySize ( ) }
182-
183- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
231+ private class SymmetricKeySize extends MinimumKeySize {
232+ SymmetricKeySize ( ) { this = getMinKeySize ( ) }
184233 }
185234
186235 /** A sink for an insufficient key size used in AES algorithms. */
@@ -193,7 +242,7 @@ private module Symmetric {
193242 )
194243 }
195244
196- override predicate hasState ( DataFlow :: FlowState state ) { state = getMinKeySize ( ) . toString ( ) }
245+ override int minimumKeySize ( ) { result = getMinKeySize ( ) }
197246 }
198247
199248 /** Returns the minimum recommended key size for AES algorithms. */
0 commit comments