3
3
private import semmle.code.java.security.Encryption
4
4
private import semmle.code.java.dataflow.DataFlow
5
5
private 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 ;
6
35
7
36
/** A source for an insufficient key size. */
8
37
abstract class InsufficientKeySizeSource extends DataFlow:: Node {
9
38
/** Holds if this source has the specified `state`. */
10
- predicate hasState ( DataFlow :: FlowState state ) { state instanceof DataFlow :: FlowStateEmpty }
39
+ abstract predicate hasState ( KeySizeState state ) ;
11
40
}
12
41
13
42
/** A sink for an insufficient key size. */
14
43
abstract 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
+ }
17
68
}
18
69
19
70
/** Provides models for asymmetric cryptography. */
20
71
private module Asymmetric {
21
72
/** Provides models for non-elliptic-curve asymmetric cryptography. */
22
73
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 ( _) }
32
76
}
33
77
34
78
/** A sink for an insufficient key size used in RSA, DSA, and DH algorithms. */
@@ -46,9 +90,7 @@ private module Asymmetric {
46
90
exists ( Spec spec | this .asExpr ( ) = spec .getKeySizeArg ( ) and algoName = spec .getAlgoName ( ) )
47
91
}
48
92
49
- override predicate hasState ( DataFlow:: FlowState state ) {
50
- state = getMinKeySize ( algoName ) .toString ( )
51
- }
93
+ override int minimumKeySize ( ) { result = getMinKeySize ( algoName ) }
52
94
}
53
95
54
96
/** Returns the minimum recommended key size for RSA, DSA, and DH algorithms. */
@@ -88,16 +130,24 @@ private module Asymmetric {
88
130
89
131
/** Provides models for elliptic-curve asymmetric cryptography. */
90
132
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
+
91
141
/** A source for an insufficient key size used in elliptic curve (EC) algorithms. */
92
142
private class Source extends InsufficientKeySizeSource {
93
143
Source ( ) {
94
- this .asExpr ( ) .( IntegerLiteral ) .getIntValue ( ) < getMinKeySize ( )
95
- or
96
144
// the below is needed for cases when the key size is embedded in the curve name
97
145
getKeySize ( this .asExpr ( ) .( StringLiteral ) .getValue ( ) ) < getMinKeySize ( )
98
146
}
99
147
100
- override predicate hasState ( DataFlow:: FlowState state ) { state = getMinKeySize ( ) .toString ( ) }
148
+ override predicate hasState ( KeySizeState state ) {
149
+ state .asRight ( ) instanceof EllipticCurveKind
150
+ }
101
151
}
102
152
103
153
/** A sink for an insufficient key size used in elliptic curve (EC) algorithms. */
@@ -112,7 +162,9 @@ private module Asymmetric {
112
162
exists ( Spec s | this .asExpr ( ) = s .getKeySizeArg ( ) )
113
163
}
114
164
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 }
116
168
}
117
169
118
170
/** Returns the minimum recommended key size for elliptic curve (EC) algorithms. */
@@ -176,11 +228,8 @@ private module Asymmetric {
176
228
177
229
/** Provides models for symmetric cryptography. */
178
230
private 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 ( ) }
184
233
}
185
234
186
235
/** A sink for an insufficient key size used in AES algorithms. */
@@ -193,7 +242,7 @@ private module Symmetric {
193
242
)
194
243
}
195
244
196
- override predicate hasState ( DataFlow :: FlowState state ) { state = getMinKeySize ( ) . toString ( ) }
245
+ override int minimumKeySize ( ) { result = getMinKeySize ( ) }
197
246
}
198
247
199
248
/** Returns the minimum recommended key size for AES algorithms. */
0 commit comments