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+ string toString ( ) { result = super .toString ( ) }
14+ }
15+
16+ /**
17+ * A class of algorithms for which a key size smaller than the recommended key
18+ * size might be embedded in the algorithm name.
19+ */
20+ abstract class AlgorithmKind extends string {
21+ bindingset [ this ]
22+ AlgorithmKind ( ) { any ( ) }
23+
24+ string toString ( ) { result = super .toString ( ) }
25+ }
26+
27+ /**
28+ * A key size that is greater than the tracked value and equal to the minimum
29+ * recommended key size for some algorithm, or a kind of algorithm for which the
30+ * tracked string indicates a too small key size.
31+ */
32+ final class KeySizeState = Either< MinimumKeySize , AlgorithmKind > :: Either ;
633
734/** A source for an insufficient key size. */
835abstract class InsufficientKeySizeSource extends DataFlow:: Node {
936 /** Holds if this source has the specified `state`. */
10- predicate hasState ( DataFlow :: FlowState state ) { state instanceof DataFlow :: FlowStateEmpty }
37+ abstract predicate hasState ( KeySizeState state ) ;
1138}
1239
1340/** A sink for an insufficient key size. */
1441abstract class InsufficientKeySizeSink extends DataFlow:: Node {
15- /** Holds if this sink has the specified `state`. */
16- predicate hasState ( DataFlow:: FlowState state ) { state instanceof DataFlow:: FlowStateEmpty }
42+ /** Holds if this sink accepts the specified `state`. */
43+ final predicate hasState ( KeySizeState state ) {
44+ state .asLeft ( ) <= this .minimumKeySize ( ) or this .algorithmKind ( state .asRight ( ) )
45+ }
46+
47+ /** Gets the minimum recommended key size. */
48+ abstract int minimumKeySize ( ) ;
49+
50+ /**
51+ * Holds if this sink recommends a keysize that is greater than the value in a
52+ * source with the given algorithm kind.
53+ */
54+ predicate algorithmKind ( AlgorithmKind kind ) { none ( ) }
55+ }
56+
57+ /** A source for an insufficient key size used in some algorithm. */
58+ private class IntegerLiteralSource extends InsufficientKeySizeSource {
59+ private int value ;
60+
61+ IntegerLiteralSource ( ) { this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) = value }
62+
63+ override predicate hasState ( KeySizeState state ) {
64+ state .asLeft ( ) = min ( MinimumKeySize m | value < m )
65+ }
1766}
1867
1968/** Provides models for asymmetric cryptography. */
2069private module Asymmetric {
2170 /** Provides models for non-elliptic-curve asymmetric cryptography. */
2271 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- }
72+ private class NonEllipticCurveKeySize extends MinimumKeySize {
73+ NonEllipticCurveKeySize ( ) { this = getMinKeySize ( _) }
3274 }
3375
3476 /** A sink for an insufficient key size used in RSA, DSA, and DH algorithms. */
@@ -46,9 +88,7 @@ private module Asymmetric {
4688 exists ( Spec spec | this .asExpr ( ) = spec .getKeySizeArg ( ) and algoName = spec .getAlgoName ( ) )
4789 }
4890
49- override predicate hasState ( DataFlow:: FlowState state ) {
50- state = getMinKeySize ( algoName ) .toString ( )
51- }
91+ override int minimumKeySize ( ) { result = getMinKeySize ( algoName ) }
5292 }
5393
5494 /** Returns the minimum recommended key size for RSA, DSA, and DH algorithms. */
@@ -88,16 +128,24 @@ private module Asymmetric {
88128
89129 /** Provides models for elliptic-curve asymmetric cryptography. */
90130 private module EllipticCurve {
131+ private class EllipticCurveKeySize extends MinimumKeySize {
132+ EllipticCurveKeySize ( ) { this = getMinKeySize ( ) }
133+ }
134+
135+ private class EllipticCurveKind extends AlgorithmKind {
136+ EllipticCurveKind ( ) { this = "EC" }
137+ }
138+
91139 /** A source for an insufficient key size used in elliptic curve (EC) algorithms. */
92140 private class Source extends InsufficientKeySizeSource {
93141 Source ( ) {
94- this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < getMinKeySize ( )
95- or
96142 // the below is needed for cases when the key size is embedded in the curve name
97143 getKeySize ( this .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < getMinKeySize ( )
98144 }
99145
100- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
146+ override predicate hasState ( KeySizeState state ) {
147+ state .asRight ( ) instanceof EllipticCurveKind
148+ }
101149 }
102150
103151 /** A sink for an insufficient key size used in elliptic curve (EC) algorithms. */
@@ -112,7 +160,9 @@ private module Asymmetric {
112160 exists ( Spec s | this .asExpr ( ) = s .getKeySizeArg ( ) )
113161 }
114162
115- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
163+ override int minimumKeySize ( ) { result = getMinKeySize ( ) }
164+
165+ override predicate algorithmKind ( AlgorithmKind kind ) { kind instanceof EllipticCurveKind }
116166 }
117167
118168 /** Returns the minimum recommended key size for elliptic curve (EC) algorithms. */
@@ -176,11 +226,8 @@ private module Asymmetric {
176226
177227/** Provides models for symmetric cryptography. */
178228private 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 ( ) }
229+ private class SymmetricKeySize extends MinimumKeySize {
230+ SymmetricKeySize ( ) { this = getMinKeySize ( ) }
184231 }
185232
186233 /** A sink for an insufficient key size used in AES algorithms. */
@@ -193,7 +240,7 @@ private module Symmetric {
193240 )
194241 }
195242
196- override predicate hasState ( DataFlow :: FlowState state ) { state = getMinKeySize ( ) . toString ( ) }
243+ override int minimumKeySize ( ) { result = getMinKeySize ( ) }
197244 }
198245
199246 /** Returns the minimum recommended key size for AES algorithms. */
0 commit comments