Skip to content

Commit 28a8e80

Browse files
committed
Added support for EllipticCurveConsumingAlgorithm
1 parent 805019f commit 28a8e80

File tree

3 files changed

+85
-80
lines changed

3 files changed

+85
-80
lines changed

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

Lines changed: 73 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
import java
22
import experimental.quantum.Language
33
import AlgorithmValueConsumers
4+
import OperationInstances
45
import FlowAnalysis
56

6-
/**
7-
* Elliptic curve algorithms.
8-
*/
9-
abstract private class EllipticCurveConsumingAlgorithmInstance extends Crypto::EllipticCurveConsumingAlgorithmInstance
10-
{
11-
string getFixedEllipticCurveName() { none() }
12-
13-
override Crypto::AlgorithmValueConsumer getEllipticCurveConsumer() {
14-
result.(ImplicitEllipticCurveInstance).getAlgorithm() = this
15-
}
16-
}
17-
187
/**
198
* A string literal that represents an elliptic curve name.
209
*/
@@ -42,28 +31,12 @@ class EllipticCurveStringLiteralInstance extends Crypto::EllipticCurveInstance i
4231
}
4332

4433
/**
45-
* Represents an elliptic curve that is implicitly defined by the underlying
46-
* algorithm. In this case, we view the algorithm and elliptic curve as being
47-
* implicitly defined by the constructor call.
34+
* Represents an elliptic curve algorithm where the elliptic curve is implicitly
35+
* defined by the underlying type.
4836
*/
49-
class ImplicitEllipticCurveInstance extends Crypto::EllipticCurveInstance,
50-
EllipticCurveAlgorithmValueConsumer instanceof ClassInstanceExpr
37+
abstract class KnownEllipticCurveInstance extends Crypto::EllipticCurveInstance,
38+
Crypto::EllipticCurveConsumingAlgorithmInstance, Crypto::AlgorithmValueConsumer instanceof ClassInstanceExpr
5139
{
52-
EllipticCurveConsumingAlgorithmInstance algorithm;
53-
54-
ImplicitEllipticCurveInstance() {
55-
this = algorithm and
56-
exists(algorithm.getFixedEllipticCurveName())
57-
}
58-
59-
EllipticCurveConsumingAlgorithmInstance getAlgorithm() { result = this }
60-
61-
override string getRawEllipticCurveName() { result = algorithm.getFixedEllipticCurveName() }
62-
63-
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
64-
65-
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
66-
6740
override Crypto::TEllipticCurveType getEllipticCurveType() {
6841
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName().toUpperCase(),
6942
_, result)
@@ -73,6 +46,8 @@ class ImplicitEllipticCurveInstance extends Crypto::EllipticCurveInstance,
7346
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName().toUpperCase(),
7447
result, _)
7548
}
49+
50+
override Crypto::AlgorithmValueConsumer getEllipticCurveConsumer() { result = this }
7651
}
7752

7853
/**
@@ -112,6 +87,18 @@ abstract class SignatureAlgorithmInstance extends Crypto::KeyOperationAlgorithmI
11287
DataFlow::Node getEllipticCurveInput() { none() }
11388
}
11489

90+
/**
91+
* Represents an elliptic curve signature algorithm where both the signature
92+
* algorithm and elliptic curve are implicitly defined by the underlying type.
93+
*/
94+
abstract class KnownEllipticCurveSignatureAlgorithmInstance extends KnownEllipticCurveInstance,
95+
SignatureAlgorithmInstance
96+
{
97+
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
98+
99+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
100+
}
101+
115102
/**
116103
* DSA and DSADigest signers.
117104
*/
@@ -129,22 +116,24 @@ class DSASignatureAlgorithmInstance extends SignatureAlgorithmInstance instanceo
129116
/**
130117
* Ed25519, Ed25519ph, and Ed25519ctx signers.
131118
*/
132-
class Ed25519SignatureAlgorithmInstance extends SignatureAlgorithmInstance,
133-
EllipticCurveConsumingAlgorithmInstance instanceof ClassInstanceExpr
119+
class Ed25519SignatureAlgorithmInstance extends KnownEllipticCurveSignatureAlgorithmInstance instanceof ClassInstanceExpr
134120
{
135121
Ed25519SignatureAlgorithmInstance() {
136122
super.getConstructedType() instanceof Signers::Signer and
137123
super.getConstructedType().getName().matches("Ed25519%")
138124
}
139125

140-
override string getFixedEllipticCurveName() { result = "Curve25519" }
126+
override string getRawAlgorithmName() {
127+
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
128+
}
129+
130+
override string getRawEllipticCurveName() { result = "Curve25519" }
141131
}
142132

143133
/**
144134
* Ed448 and Ed448ph signers.
145135
*/
146-
class Ed448SignatureAlgorithmInstance extends SignatureAlgorithmInstance,
147-
EllipticCurveConsumingAlgorithmInstance instanceof ClassInstanceExpr
136+
class Ed448SignatureAlgorithmInstance extends KnownEllipticCurveSignatureAlgorithmInstance instanceof ClassInstanceExpr
148137
{
149138
Ed448SignatureAlgorithmInstance() {
150139
super.getConstructedType() instanceof Signers::Signer and
@@ -155,7 +144,7 @@ class Ed448SignatureAlgorithmInstance extends SignatureAlgorithmInstance,
155144
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
156145
}
157146

158-
override string getFixedEllipticCurveName() { result = "Curve448" }
147+
override string getRawEllipticCurveName() { result = "Curve448" }
159148
}
160149

161150
/**
@@ -171,7 +160,7 @@ class Ed448SignatureAlgorithmInstance extends SignatureAlgorithmInstance,
171160
class ECDSASignatureAlgorithmInstance extends SignatureAlgorithmInstance instanceof ClassInstanceExpr
172161
{
173162
ECDSASignatureAlgorithmInstance() {
174-
super.getConstructedType() instanceof Signers::Signer and
163+
super.getConstructedType() instanceof Signers::OneShotSigner and
175164
super.getConstructedType().getName().matches("ECDSA%")
176165
}
177166

@@ -186,6 +175,9 @@ class ECDSASignatureAlgorithmInstance extends SignatureAlgorithmInstance instanc
186175
override int getKeySizeFixed() { none() }
187176
}
188177

178+
/**
179+
* LMS signers.
180+
*/
189181
class LMSSignatureAlgorithmInstance extends SignatureAlgorithmInstance instanceof ClassInstanceExpr {
190182
LMSSignatureAlgorithmInstance() {
191183
super.getConstructedType() instanceof Signers::Signer and
@@ -239,50 +231,79 @@ abstract class KeyGenerationAlgorithmInstance extends Crypto::KeyOperationAlgori
239231
DataFlow::Node getEllipticCurveInput() { none() }
240232
}
241233

242-
class Ed25519KeyGenerationAlgorithmInstance extends KeyGenerationAlgorithmInstance,
243-
EllipticCurveConsumingAlgorithmInstance instanceof ClassInstanceExpr
234+
/**
235+
* Represents an elliptic curve key generation algorithm where both the key
236+
* generation algorithm and elliptic curve are implicitly defined by the
237+
* underlying type.
238+
*/
239+
abstract class KnownEllipticCurveKeyGenerationAlgorithmInstance extends KnownEllipticCurveInstance,
240+
KeyGenerationAlgorithmInstance
241+
{
242+
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
243+
244+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
245+
}
246+
247+
class Ed25519KeyGenerationAlgorithmInstance extends KnownEllipticCurveKeyGenerationAlgorithmInstance instanceof ClassInstanceExpr
244248
{
245249
Ed25519KeyGenerationAlgorithmInstance() {
246250
super.getConstructedType() instanceof Generators::KeyGenerator and
247251
super.getConstructedType().getName().matches("Ed25519%")
248252
}
249253

250-
override string getFixedEllipticCurveName() { result = "Curve25519" }
254+
override string getRawEllipticCurveName() { result = "Curve25519" }
251255
}
252256

253-
class Ed448KeyGenerationAlgorithmInstance extends KeyGenerationAlgorithmInstance,
254-
EllipticCurveConsumingAlgorithmInstance instanceof ClassInstanceExpr
257+
class Ed448KeyGenerationAlgorithmInstance extends KnownEllipticCurveKeyGenerationAlgorithmInstance instanceof ClassInstanceExpr
255258
{
256259
Ed448KeyGenerationAlgorithmInstance() {
257260
super.getConstructedType() instanceof Generators::KeyGenerator and
258261
super.getConstructedType().getName().matches("Ed448%")
259262
}
260263

261-
override string getFixedEllipticCurveName() { result = "Curve448" }
264+
override string getRawEllipticCurveName() { result = "Curve448" }
262265
}
263266

264267
/**
265268
* Represents a generic `ECKeyPairGenerator` instance.
266269
*/
267-
class GenericEllipticCurveKeyGenerationAlgorithmInstance extends KeyGenerationAlgorithmInstance instanceof ClassInstanceExpr
270+
class GenericEllipticCurveKeyGenerationAlgorithmInstance extends KeyGenerationAlgorithmInstance,
271+
Crypto::EllipticCurveConsumingAlgorithmInstance instanceof ClassInstanceExpr
268272
{
269273
GenericEllipticCurveKeyGenerationAlgorithmInstance() {
270274
super.getConstructedType() instanceof Generators::KeyGenerator and
271275
super.getConstructedType().getName().matches("EC%")
272276
}
273277

274278
override string getRawAlgorithmName() {
275-
// TODO: The generator constructs an elliptic curve key pair, but the
276-
// algorithm is not determined at key generation. As an example, the key
277-
// could be used for either ECDSA or ECDH. For this reason, we just return
278-
// "EllipticCurve".
279-
result = "EllipticCurve"
279+
// TODO: The generator constructs an elliptic curve key pair. The curve used
280+
// is determined using data flow. If this fails we would like to report
281+
// something useful, so we use "UnknownCurve". However, this should probably
282+
// be handled at the node layer.
283+
if exists(this.getConsumedEllipticCurve())
284+
then result = this.getConsumedEllipticCurve().getRawEllipticCurveName()
285+
else result = "UnknownCurve"
280286
}
281287

282288
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
283-
// The algorithm type is not known. See above.
289+
// TODO: There is currently to algorithm type for elliptic curve key
290+
// generation.
284291
result = Crypto::KeyOpAlg::TUnknownKeyOperationAlgorithmType()
285292
}
293+
294+
override Crypto::AlgorithmValueConsumer getEllipticCurveConsumer() {
295+
// The elliptic curve is resolved recursively from the parameters passed to
296+
// the `init()` call.
297+
exists(MethodCall init |
298+
init = Generators::KeyGeneratorFlow::getInitFromNew(this, _, _) and
299+
result =
300+
Generators::ParametersFlow::getParametersFromInit(init, _, _).getAnAlgorithmValueConsumer()
301+
)
302+
}
303+
304+
Crypto::EllipticCurveInstance getConsumedEllipticCurve() {
305+
result = this.getEllipticCurveConsumer().getAKnownAlgorithmSource()
306+
}
286307
}
287308

288309
/**

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ module NewToInitToUseFlowAnalysis<NewCallSig New, InitCallSig Init, UseCallSig U
161161
NewToInitToUseFlow::flowPath(src, sink)
162162
}
163163

164+
Init getInitFromNew(New new, NewToInitToUseFlow::PathNode src, NewToInitToUseFlow::PathNode sink) {
165+
src.getNode().asExpr() = new and
166+
sink.getNode().asExpr() = result.(MethodCall).getQualifier() and
167+
NewToInitToUseFlow::flowPath(src, sink)
168+
}
169+
164170
Init getInitFromUse(Use use, NewToInitToUseFlow::PathNode src, NewToInitToUseFlow::PathNode sink) {
165171
src.getNode().asExpr() = result.(MethodCall).getQualifier() and
166172
sink.getNode().asExpr() = use.(MethodCall).getQualifier() and
@@ -211,7 +217,7 @@ private class CurveInstantiation extends MethodCall {
211217
* represents a parameter object or a curve.
212218
*/
213219
module ParametersToInitFlowAnalysis<NewCallSig New, InitCallSig Init> {
214-
module ParametersToInitConfig implements DataFlow::ConfigSig {
220+
private module ParametersToInitConfig implements DataFlow::ConfigSig {
215221
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof New }
216222

217223
predicate isSink(DataFlow::Node sink) { exists(Init init | sink = init.getParametersInput()) }
@@ -261,7 +267,7 @@ module ParametersToInitFlowAnalysis<NewCallSig New, InitCallSig Init> {
261267
}
262268
}
263269

264-
module ParametersToInitFlow = DataFlow::Global<ParametersToInitConfig>;
270+
private module ParametersToInitFlow = DataFlow::Global<ParametersToInitConfig>;
265271

266272
New getParametersFromInit(
267273
Init init, ParametersToInitFlow::PathNode src, ParametersToInitFlow::PathNode sink

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

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ module Signers {
173173

174174
override Expr getSignatureArg(MethodCall call) {
175175
// For ECDSA, r and s are passed to `verifySignature()` as separate arguments.
176+
// For LMS, the signature is passed as a single argument in position 1.
176177
call.getCallee().getName() = "verifySignature" and
177178
result = call.getArgument([1, 2])
178179
}
@@ -204,20 +205,6 @@ module Signers {
204205
Expr getParametersArg() { result = this.getArgument(1) }
205206

206207
DataFlow::Node getParametersInput() { result.asExpr() = this.getParametersArg() }
207-
208-
// TODO: Support dataflow for the operation sub-type.
209-
Crypto::KeyOperationSubtype getKeyOperationSubtype() {
210-
if this.isOperationSubTypeKnown()
211-
then
212-
this.getForSigningArg().(BooleanLiteral).getBooleanValue() = true and
213-
result = Crypto::TSignMode()
214-
or
215-
this.getForSigningArg().(BooleanLiteral).getBooleanValue() = false and
216-
result = Crypto::TVerifyMode()
217-
else result = Crypto::TUnknownKeyOperationMode()
218-
}
219-
220-
predicate isOperationSubTypeKnown() { this.getForSigningArg() instanceof BooleanLiteral }
221208
}
222209

223210
/**
@@ -390,21 +377,12 @@ module Generators {
390377
Expr getOutput() { result = this }
391378
}
392379

393-
private module KeyGeneratorFlow =
380+
module KeyGeneratorFlow =
394381
NewToInitToUseFlowAnalysis<KeyGeneratorNewCall, KeyGeneratorInitCall, KeyGeneratorUseCall>;
395382

396-
private module ParametersFlow =
383+
module ParametersFlow =
397384
ParametersToInitFlowAnalysis<Params::ParametersInstantiation, KeyGeneratorInitCall>;
398385

399-
Params::ParametersInstantiation getParametersFromInit(KeyGeneratorInitCall init) {
400-
result = ParametersFlow::getParametersFromInit(init, _, _)
401-
}
402-
403-
// TODO: Remove this.
404-
Params::ParametersInstantiation getParametersFromUse(KeyGeneratorInitCall init) {
405-
result = ParametersFlow::getParametersFromInit(init, _, _)
406-
}
407-
408386
/**
409387
* A key generation operation instance is a call to `generateKey()` or
410388
* `generateKeyPair()` on a key generator defined under
@@ -413,7 +391,7 @@ module Generators {
413391
class KeyGenerationOperationInstance extends Crypto::KeyGenerationOperationInstance instanceof KeyGeneratorUseCall
414392
{
415393
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
416-
// The algorithm is implicit in the key generator type
394+
// The algorithm is implicitly defined by the key generator type
417395
result = KeyGeneratorFlow::getNewFromUse(this, _, _)
418396
}
419397

0 commit comments

Comments
 (0)