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