Skip to content

Commit 80a29f9

Browse files
committed
Fixed QL for QL findings
1 parent 7969bdf commit 80a29f9

File tree

5 files changed

+66
-93
lines changed

5 files changed

+66
-93
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
import java
21
import BouncyCastle.OperationInstances
2+
import BouncyCastle.AlgorithmInstances
3+
import BouncyCastle.AlgorithmValueConsumers

java/ql/lib/experimental/quantum/BouncyCastle/AlgorithmInstances.qll

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import java
2-
import OperationInstances
3-
import FlowAnalysis
1+
private import java
2+
private import experimental.quantum.Language
3+
private import AlgorithmValueConsumers
4+
private import OperationInstances
5+
private import FlowAnalysis
46

57
/**
68
* A string literal that represents an elliptic curve name.
@@ -194,34 +196,24 @@ class StatefulSignatureAlgorithmInstance extends SignatureAlgorithmInstance inst
194196
* A key generation algorithm where the algorithm is implicitly defined by the
195197
* type.
196198
*/
197-
abstract class KeyGenerationAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance,
199+
abstract class KeyGenerationAlgorithmInstance extends Crypto::AlgorithmInstance,
198200
KeyGenerationAlgorithmValueConsumer instanceof ClassInstanceExpr
199201
{
200-
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
201-
202-
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
203-
204-
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() }
205-
206-
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
207-
generatorNameToKeySizeAndAlgorithmMapping(this.getRawAlgorithmName(), _, result)
208-
}
209-
210-
override int getKeySizeFixed() {
211-
generatorNameToKeySizeAndAlgorithmMapping(this.getRawAlgorithmName(), result, _)
212-
}
213-
214-
override string getRawAlgorithmName() {
215-
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
216-
}
217-
218202
// Used for data flow from elliptic curve string literals to the algorithm
219203
// instance.
220204
DataFlow::Node getParametersInput() { none() }
221205

222206
// Used for data flow from elliptic curve string literals to the algorithm
223207
// instance.
224208
DataFlow::Node getEllipticCurveInput() { none() }
209+
210+
string getRawAlgorithmName() {
211+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
212+
}
213+
214+
int getKeySizeFixed() {
215+
generatorNameToKeySizeAndAlgorithmMapping(this.getRawAlgorithmName(), result, _)
216+
}
225217
}
226218

227219
/**
@@ -267,22 +259,6 @@ class GenericEllipticCurveKeyGenerationAlgorithmInstance extends KeyGenerationAl
267259
super.getConstructedType().getName().matches("EC%")
268260
}
269261

270-
override string getRawAlgorithmName() {
271-
// TODO: The generator constructs an elliptic curve key pair. The curve used
272-
// is determined using data flow. If this fails we would like to report
273-
// something useful, so we use "UnknownCurve". However, this should probably
274-
// be handled at the node layer.
275-
if exists(this.getConsumedEllipticCurve())
276-
then result = this.getConsumedEllipticCurve().getRawEllipticCurveName()
277-
else result = "UnknownCurve"
278-
}
279-
280-
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
281-
// TODO: There is currently to algorithm type for elliptic curve key
282-
// generation.
283-
result = Crypto::KeyOpAlg::TUnknownKeyOperationAlgorithmType()
284-
}
285-
286262
override Crypto::AlgorithmValueConsumer getEllipticCurveConsumer() {
287263
// The elliptic curve is resolved recursively from the parameters passed to
288264
// the `init()` call.
@@ -308,18 +284,6 @@ class StatefulSignatureKeyGenerationAlgorithmInstance extends KeyGenerationAlgor
308284
super.getConstructedType() instanceof Generators::KeyGenerator and
309285
super.getConstructedType().getName().matches(["LMS%", "HSS%"])
310286
}
311-
312-
override string getRawAlgorithmName() {
313-
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
314-
}
315-
316-
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
317-
super.getConstructedType().getName().matches("LMS%") and
318-
result = Crypto::KeyOpAlg::TSignature(Crypto::KeyOpAlg::LMS())
319-
or
320-
super.getConstructedType().getName().matches("HSS%") and
321-
result = Crypto::KeyOpAlg::TSignature(Crypto::KeyOpAlg::HSS())
322-
}
323287
}
324288

325289
/**

java/ql/lib/experimental/quantum/BouncyCastle/AlgorithmValueConsumers.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import java
2-
import AlgorithmInstances
1+
private import java
2+
private import experimental.quantum.Language
3+
private import AlgorithmValueConsumers
4+
private import AlgorithmInstances
35

46
abstract class EllipticCurveAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
57

java/ql/lib/experimental/quantum/BouncyCastle/FlowAnalysis.qll

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import java
2-
import semmle.code.java.dataflow.DataFlow
3-
import experimental.quantum.Language
4-
import AlgorithmValueConsumers
1+
private import java
2+
private import semmle.code.java.dataflow.DataFlow
3+
private import experimental.quantum.Language
4+
private import AlgorithmValueConsumers
55

66
/**
77
* A signature for the `getInstance()` method calls used in JCA, or direct
@@ -46,24 +46,25 @@ signature class UseCallSig instanceof MethodCall {
4646
* ```
4747
*/
4848
module NewToInitToUseFlow<NewCallSig New, InitCallSig Init, UseCallSig Use> {
49-
newtype TFlowState =
49+
private newtype TFlowState =
5050
TUninitialized() or
5151
TInitialized(Init call) or
5252
TIntermediateUse(Use call)
5353

54-
abstract class InitFlowState extends TFlowState {
54+
abstract private class InitFlowState extends TFlowState {
5555
string toString() {
5656
this = TUninitialized() and result = "Uninitialized"
5757
or
5858
this = TInitialized(_) and result = "Initialized"
59-
// TODO: add intermediate use
59+
or
60+
this = TIntermediateUse(_) and result = "Intermediate"
6061
}
6162
}
6263

6364
// The flow state is uninitialized if the `init` call is not yet made.
64-
class UninitializedFlowState extends InitFlowState, TUninitialized { }
65+
private class UninitializedFlowState extends InitFlowState, TUninitialized { }
6566

66-
class InitializedFlowState extends InitFlowState, TInitialized {
67+
private class InitializedFlowState extends InitFlowState, TInitialized {
6768
Init call;
6869
DataFlow::Node node1;
6970
DataFlow::Node node2; // The receiver of the `init` call
@@ -82,7 +83,7 @@ module NewToInitToUseFlow<NewCallSig New, InitCallSig Init, UseCallSig Use> {
8283
DataFlow::Node getSndNode() { result = node2 }
8384
}
8485

85-
class IntermediateUseState extends InitFlowState, TIntermediateUse {
86+
private class IntermediateUseState extends InitFlowState, TIntermediateUse {
8687
Use call;
8788
DataFlow::Node node1; // The receiver of the method call
8889
DataFlow::Node node2;
@@ -101,19 +102,21 @@ module NewToInitToUseFlow<NewCallSig New, InitCallSig Init, UseCallSig Use> {
101102
DataFlow::Node getSndNode() { result = node2 }
102103
}
103104

104-
module NewToInitToUseConfig implements DataFlow::StateConfigSig {
105+
private module NewToInitToUseConfig implements DataFlow::StateConfigSig {
105106
class FlowState = InitFlowState;
106107

107108
predicate isSource(DataFlow::Node src, FlowState state) {
108109
state instanceof UninitializedFlowState and
109110
src.asExpr() instanceof New
110111
or
112+
// Needed to determine the init call from a (final) use.
111113
src = state.(InitializedFlowState).getSndNode()
112114
or
115+
// Needed to determine all intermediate uses from a (final) use.
113116
src = state.(IntermediateUseState).getSndNode()
114117
}
115118

116-
// TODO: document this, but this is intentional (avoid cross products?)
119+
// TODO: Document this, but this is intentional (to avoid cross products).
117120
predicate isSink(DataFlow::Node sink, FlowState state) { none() }
118121

119122
predicate isSink(DataFlow::Node sink) {
@@ -138,15 +141,15 @@ module NewToInitToUseFlow<NewCallSig New, InitCallSig Init, UseCallSig Use> {
138141
predicate isBarrier(DataFlow::Node node, FlowState state) {
139142
exists(Init call | node.asExpr() = call.(MethodCall).getQualifier() |
140143
// Ensures that the receiver of a call to `init` is tracked as initialized.
141-
state instanceof UninitializedFlowState
144+
not state instanceof InitializedFlowState
142145
or
143146
// Ensures that call tracked by the state is the last call to `init`.
144147
state.(InitializedFlowState).getInitCall() != call
145148
)
146149
}
147150
}
148151

149-
module NewToInitToUseFlow = DataFlow::GlobalWithState<NewToInitToUseConfig>;
152+
private module NewToInitToUseFlow = DataFlow::GlobalWithState<NewToInitToUseConfig>;
150153

151154
New getNewFromUse(Use use, NewToInitToUseFlow::PathNode src, NewToInitToUseFlow::PathNode sink) {
152155
src.getNode().asExpr() = result and
@@ -222,7 +225,7 @@ module ParametersToInitFlow<NewCallSig New, InitCallSig Init> {
222225
predicate isSink(DataFlow::Node sink) { exists(Init init | sink = init.getParametersInput()) }
223226

224227
/**
225-
* A flow step for parameters created from other parameters.
228+
* Holds for parameters created from other parameters.
226229
*
227230
* As an example, below we want to track the flow from the `X9ECParameters`
228231
* constructor call to the `keyPairGenerator.init()` call to be able to

java/ql/lib/experimental/quantum/BouncyCastle/OperationInstances.qll

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import java
1+
private import java
2+
private import experimental.quantum.Language
3+
private import FlowAnalysis
4+
private import AlgorithmInstances
25

36
module Params {
4-
import FlowAnalysis
5-
import AlgorithmInstances
6-
77
/**
88
* A model of the `Parameters` class in Bouncy Castle.
99
*/
@@ -17,15 +17,15 @@ module Params {
1717

1818
class Curve extends Class {
1919
Curve() {
20-
this.getPackage().getName() = "org.bouncycastle.math.ec" and
21-
this.getName().matches("ECCurve")
20+
this.getPackage().hasName("org.bouncycastle.math.ec") and
21+
this.hasName("ECCurve")
2222
}
2323
}
2424

2525
class KeyParameters extends Parameters {
2626
KeyParameters() {
27-
this.getPackage().getName() =
28-
["org.bouncycastle.crypto.params", "org.bouncycastle.pqc.crypto.lms"] and
27+
this.getPackage()
28+
.hasName(["org.bouncycastle.crypto.params", "org.bouncycastle.pqc.crypto.lms"]) and
2929
this.getName().matches(["%KeyParameter", "%KeyParameters"])
3030
}
3131
}
@@ -95,7 +95,7 @@ module Params {
9595
}
9696

9797
/**
98-
* The named elliptic curve passed to `X9ECParameters.getCurve()`.
98+
* A named elliptic curve passed to `X9ECParameters.getCurve()`.
9999
*/
100100
class X9ECParametersInstantiation extends ParametersInstantiation {
101101
X9ECParametersInstantiation() { this.(Expr).getType().getName() = "X9ECParameters" }
@@ -108,7 +108,7 @@ module Params {
108108
}
109109

110110
/**
111-
* The named elliptic curve passed to `ECNamedCurveTable.getParameterSpec()`.
111+
* A named elliptic curve passed to `ECNamedCurveTable.getParameterSpec()`.
112112
*/
113113
class ECNamedCurveParameterSpecInstantiation extends ParametersInstantiation {
114114
ECNamedCurveParameterSpecInstantiation() {
@@ -135,6 +135,11 @@ module Params {
135135
override Expr getNonceArg() { result = this.(ConstructorCall).getArgument(2) }
136136
}
137137

138+
/**
139+
* A `ParametersWithIV` instantiation.
140+
*
141+
* This type is used to model data flow from a nonce to a cipher operation.
142+
*/
138143
class ParametersWithIvInstantiation extends ParametersInstantiation {
139144
ParametersWithIvInstantiation() {
140145
this.(ConstructorCall).getConstructedType().getName() = "ParametersWithIV"
@@ -161,9 +166,6 @@ module Params {
161166
* Models for the signature algorithms defined by the `org.bouncycastle.crypto.signers` package.
162167
*/
163168
module Signers {
164-
import FlowAnalysis
165-
import AlgorithmInstances
166-
167169
/**
168170
* A model of the `Signer` class in Bouncy Castle.
169171
*
@@ -207,8 +209,8 @@ module Signers {
207209
}
208210

209211
/**
210-
* This class represents signers with a one shot API (where the entire message
211-
* is passed to either `generateSignature()` or `verifySignature`.).
212+
* A signer with a one shot API (where the entire message is passed to either
213+
* `generateSignature()` or `verifySignature`.).
212214
*/
213215
class OneShotSigner extends Signer {
214216
OneShotSigner() { this.getName().matches(["DSASigner", "ECDSA%", "LMS%", "HSS%"]) }
@@ -335,9 +337,6 @@ module Signers {
335337
* Models for the key generation algorithms defined by the `org.bouncycastle.crypto.generators` package.
336338
*/
337339
module Generators {
338-
import FlowAnalysis
339-
import AlgorithmInstances
340-
341340
/**
342341
* A model of the `KeyGenerator` and `KeyPairGenerator` classes in Bouncy Castle.
343342
*/
@@ -366,6 +365,8 @@ module Generators {
366365
}
367366

368367
/**
368+
* An asymmetric key pair.
369+
*
369370
* This type is used to model data flow from a key pair to the private and
370371
* public components of the key pair.
371372
*/
@@ -391,13 +392,13 @@ module Generators {
391392
private class KeyGeneratorNewCall = KeyGenerationAlgorithmInstance;
392393

393394
/**
395+
* A call to a key generator `init()` method.
396+
*
394397
* The type is instantiated by a constructor call and initialized by a call to
395398
* `init()` which takes a single `KeyGenerationParameters` argument.
396399
*/
397400
private class KeyGeneratorInitCall extends MethodCall {
398-
KeyGenerator gen;
399-
400-
KeyGeneratorInitCall() { this = gen.getAnInitCall() }
401+
KeyGeneratorInitCall() { this = any(KeyGenerator gen).getAnInitCall() }
401402

402403
Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() }
403404

@@ -435,7 +436,8 @@ module Generators {
435436
class KeyGenerationOperationInstance extends Crypto::KeyGenerationOperationInstance instanceof KeyGeneratorUseCall
436437
{
437438
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
438-
// The algorithm is implicitly defined by the key generator type
439+
// The algorithm is implicitly defined by the key generator type, which is
440+
// determined by the constructor call.
439441
result = KeyGeneratorFlow::getNewFromUse(this, _, _)
440442
}
441443

@@ -529,6 +531,9 @@ module Modes {
529531
}
530532
}
531533

534+
/**
535+
* A block cipher engine, like `AESEngine`.
536+
*/
532537
class BlockCipher extends Class {
533538
BlockCipher() {
534539
this.getPackage().getName() = "org.bouncycastle.crypto.engines" and
@@ -605,9 +610,7 @@ module Modes {
605610
* decrypt data.
606611
*/
607612
private class BlockCipherModeUseCall extends MethodCall {
608-
BlockCipherMode mode;
609-
610-
BlockCipherModeUseCall() { this = mode.getAUseCall() }
613+
BlockCipherModeUseCall() { this = any(BlockCipherMode mode).getAUseCall() }
611614

612615
predicate isIntermediate() { not this.getCallee().getName() = "doFinal" }
613616

0 commit comments

Comments
 (0)