Skip to content

Commit 7847e92

Browse files
committed
Crypto: Update KDF iteration and count to be path problems
1 parent 76128ed commit 7847e92

File tree

3 files changed

+102
-12
lines changed

3 files changed

+102
-12
lines changed

java/ql/src/experimental/quantum/Examples/WeakKDFIterationCount.ql

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @name Weak known key derivation function iteration count
33
* @description Detects key derivation operations with a known weak iteration count.
44
* @id java/quantum/weak-kdf-iteration-count
5-
* @kind problem
5+
* @kind path-problem
66
* @problem.severity error
77
* @precision high
88
* @tags quantum
@@ -12,9 +12,49 @@
1212
import java
1313
import experimental.quantum.Language
1414

15-
from Crypto::KeyDerivationOperationNode op, Literal l
15+
module IterationCountConfig implements DataFlow::ConfigSig {
16+
predicate isSource(DataFlow::Node source) {
17+
source = any(Crypto::GenericSourceInstance i).getOutputNode() or
18+
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
19+
}
20+
21+
predicate isSink(DataFlow::Node sink) {
22+
exists(Crypto::KeyDerivationOperationInstance kdev |
23+
sink = kdev.getIterationCountConsumer().getConsumer().getInputNode()
24+
)
25+
}
26+
27+
predicate isBarrierOut(DataFlow::Node node) {
28+
node = any(Crypto::FlowAwareElement element).getInputNode()
29+
}
30+
31+
predicate isBarrierIn(DataFlow::Node node) {
32+
node = any(Crypto::FlowAwareElement element).getOutputNode()
33+
}
34+
35+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
36+
node1.(AdditionalFlowInputStep).getOutput() = node2
37+
or
38+
exists(MethodCall m |
39+
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
40+
node1.asExpr() = m.getQualifier() and
41+
node2.asExpr() = m
42+
)
43+
}
44+
}
45+
46+
module IterationCountFlow = TaintTracking::Global<IterationCountConfig>;
47+
48+
import IterationCountFlow::PathGraph
49+
50+
from
51+
Crypto::KeyDerivationOperationNode op, Literal l, IterationCountFlow::PathNode srcNode,
52+
IterationCountFlow::PathNode sinkNode
1653
where
1754
op.getIterationCount().asElement() = l and
18-
l.getValue().toInt() < 100000
19-
select op, "Key derivation operation configures iteration count below 100k: $@", l,
20-
l.getValue().toString()
55+
l.getValue().toInt() < 100000 and
56+
srcNode.getNode().asExpr() = l and
57+
sinkNode.getNode() = op.getIterationCountConsumer().getConsumer().getInputNode() and
58+
IterationCountFlow::flowPath(srcNode, sinkNode)
59+
select sinkNode, srcNode, sinkNode,
60+
"Key derivation operation configures iteration count below 100k: $@", l, l.getValue().toString()

java/ql/src/experimental/quantum/Examples/WeakKDFKeySize.ql

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @name Weak known key derivation function output length
33
* @description Detects key derivation operations with a known weak output length
44
* @id java/quantum/weak-kdf-key-size
5-
* @kind problem
5+
* @kind path-problem
66
* @problem.severity error
77
* @precision high
88
* @tags quantum
@@ -12,9 +12,49 @@
1212
import java
1313
import experimental.quantum.Language
1414

15-
from Crypto::KeyDerivationOperationNode op, Literal l
15+
module KeySizeConfig implements DataFlow::ConfigSig {
16+
predicate isSource(DataFlow::Node source) {
17+
source = any(Crypto::GenericSourceInstance i).getOutputNode() or
18+
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
19+
}
20+
21+
predicate isSink(DataFlow::Node sink) {
22+
exists(Crypto::KeyDerivationOperationInstance kdev |
23+
sink = kdev.getKeySizeConsumer().getConsumer().getInputNode()
24+
)
25+
}
26+
27+
predicate isBarrierOut(DataFlow::Node node) {
28+
node = any(Crypto::FlowAwareElement element).getInputNode()
29+
}
30+
31+
predicate isBarrierIn(DataFlow::Node node) {
32+
node = any(Crypto::FlowAwareElement element).getOutputNode()
33+
}
34+
35+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
36+
node1.(AdditionalFlowInputStep).getOutput() = node2
37+
or
38+
exists(MethodCall m |
39+
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
40+
node1.asExpr() = m.getQualifier() and
41+
node2.asExpr() = m
42+
)
43+
}
44+
}
45+
46+
module KeySizeFlow = TaintTracking::Global<KeySizeConfig>;
47+
48+
import KeySizeFlow::PathGraph
49+
50+
from
51+
Crypto::KeyDerivationOperationNode op, Literal l, KeySizeFlow::PathNode srcNode,
52+
KeySizeFlow::PathNode sinkNode
1653
where
1754
op.getOutputKeySize().asElement() = l and
18-
l.getValue().toInt() < 256
19-
select op, "Key derivation operation configures output key length below 256: $@", l,
20-
l.getValue().toString()
55+
l.getValue().toInt() < 256 and
56+
srcNode.getNode().asExpr() = l and
57+
sinkNode.getNode() = op.getKeySizeConsumer().getConsumer().getInputNode() and
58+
KeySizeFlow::flowPath(srcNode, sinkNode)
59+
select sinkNode, srcNode, sinkNode,
60+
"Key derivation operation configures output key length below 256: $@", l, l.getValue().toString()

shared/quantum/codeql/quantum/experimental/Model.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
15801580
result = instance.getKeySizeConsumer().getConsumer().getAKnownSourceNode()
15811581
}
15821582

1583+
ConsumerInputDataFlowNode getKeySizeConsumer() { result = instance.getKeySizeConsumer() }
1584+
15831585
/**
15841586
* Gets the key artifact produced by this operation.
15851587
*/
@@ -1753,11 +1755,19 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
17531755
}
17541756

17551757
GenericSourceNode getIterationCount() {
1756-
result.asElement() = kdfInstance.getIterationCountConsumer().getConsumer().getAGenericSource()
1758+
result.asElement() = this.getIterationCountConsumer().getConsumer().getAGenericSource()
17571759
}
17581760

17591761
GenericSourceNode getOutputKeySize() {
1760-
result.asElement() = kdfInstance.getOutputKeySizeConsumer().getConsumer().getAGenericSource()
1762+
result.asElement() = this.getOutputKeySizeConsumer().getConsumer().getAGenericSource()
1763+
}
1764+
1765+
ConsumerInputDataFlowNode getIterationCountConsumer() {
1766+
result = kdfInstance.getIterationCountConsumer()
1767+
}
1768+
1769+
ConsumerInputDataFlowNode getOutputKeySizeConsumer() {
1770+
result = kdfInstance.getOutputKeySizeConsumer()
17611771
}
17621772

17631773
override predicate isCandidateAlgorithmNode(AlgorithmNode node) {

0 commit comments

Comments
 (0)