Crypto: Update KDF iteration and count to be path problems

This commit is contained in:
REDMOND\brodes
2025-10-13 15:30:53 -04:00
parent 76128ed8dc
commit 7847e92670
3 changed files with 102 additions and 12 deletions

View File

@@ -2,7 +2,7 @@
* @name Weak known key derivation function iteration count
* @description Detects key derivation operations with a known weak iteration count.
* @id java/quantum/weak-kdf-iteration-count
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @tags quantum
@@ -12,9 +12,49 @@
import java
import experimental.quantum.Language
from Crypto::KeyDerivationOperationNode op, Literal l
module IterationCountConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::GenericSourceInstance i).getOutputNode() or
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
exists(Crypto::KeyDerivationOperationInstance kdev |
sink = kdev.getIterationCountConsumer().getConsumer().getInputNode()
)
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
or
exists(MethodCall m |
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
node1.asExpr() = m.getQualifier() and
node2.asExpr() = m
)
}
}
module IterationCountFlow = TaintTracking::Global<IterationCountConfig>;
import IterationCountFlow::PathGraph
from
Crypto::KeyDerivationOperationNode op, Literal l, IterationCountFlow::PathNode srcNode,
IterationCountFlow::PathNode sinkNode
where
op.getIterationCount().asElement() = l and
l.getValue().toInt() < 100000
select op, "Key derivation operation configures iteration count below 100k: $@", l,
l.getValue().toString()
l.getValue().toInt() < 100000 and
srcNode.getNode().asExpr() = l and
sinkNode.getNode() = op.getIterationCountConsumer().getConsumer().getInputNode() and
IterationCountFlow::flowPath(srcNode, sinkNode)
select sinkNode, srcNode, sinkNode,
"Key derivation operation configures iteration count below 100k: $@", l, l.getValue().toString()

View File

@@ -2,7 +2,7 @@
* @name Weak known key derivation function output length
* @description Detects key derivation operations with a known weak output length
* @id java/quantum/weak-kdf-key-size
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @tags quantum
@@ -12,9 +12,49 @@
import java
import experimental.quantum.Language
from Crypto::KeyDerivationOperationNode op, Literal l
module KeySizeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::GenericSourceInstance i).getOutputNode() or
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}
predicate isSink(DataFlow::Node sink) {
exists(Crypto::KeyDerivationOperationInstance kdev |
sink = kdev.getKeySizeConsumer().getConsumer().getInputNode()
)
}
predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
or
exists(MethodCall m |
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
node1.asExpr() = m.getQualifier() and
node2.asExpr() = m
)
}
}
module KeySizeFlow = TaintTracking::Global<KeySizeConfig>;
import KeySizeFlow::PathGraph
from
Crypto::KeyDerivationOperationNode op, Literal l, KeySizeFlow::PathNode srcNode,
KeySizeFlow::PathNode sinkNode
where
op.getOutputKeySize().asElement() = l and
l.getValue().toInt() < 256
select op, "Key derivation operation configures output key length below 256: $@", l,
l.getValue().toString()
l.getValue().toInt() < 256 and
srcNode.getNode().asExpr() = l and
sinkNode.getNode() = op.getKeySizeConsumer().getConsumer().getInputNode() and
KeySizeFlow::flowPath(srcNode, sinkNode)
select sinkNode, srcNode, sinkNode,
"Key derivation operation configures output key length below 256: $@", l, l.getValue().toString()

View File

@@ -1580,6 +1580,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
result = instance.getKeySizeConsumer().getConsumer().getAKnownSourceNode()
}
ConsumerInputDataFlowNode getKeySizeConsumer() { result = instance.getKeySizeConsumer() }
/**
* Gets the key artifact produced by this operation.
*/
@@ -1753,11 +1755,19 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
}
GenericSourceNode getIterationCount() {
result.asElement() = kdfInstance.getIterationCountConsumer().getConsumer().getAGenericSource()
result.asElement() = this.getIterationCountConsumer().getConsumer().getAGenericSource()
}
GenericSourceNode getOutputKeySize() {
result.asElement() = kdfInstance.getOutputKeySizeConsumer().getConsumer().getAGenericSource()
result.asElement() = this.getOutputKeySizeConsumer().getConsumer().getAGenericSource()
}
ConsumerInputDataFlowNode getIterationCountConsumer() {
result = kdfInstance.getIterationCountConsumer()
}
ConsumerInputDataFlowNode getOutputKeySizeConsumer() {
result = kdfInstance.getOutputKeySizeConsumer()
}
override predicate isCandidateAlgorithmNode(AlgorithmNode node) {