Make ArtifactConsumers instances of some Artifacts

TODO: refactor the interfaces
This commit is contained in:
Nicolas Will
2025-02-27 15:54:38 +01:00
parent ef0614ad45
commit 0354afc365
3 changed files with 69 additions and 41 deletions

View File

@@ -346,7 +346,7 @@ module JCAModel {
override Crypto::CipherOperationSubtype getCipherOperationSubtype() { result = mode }
override Crypto::ArtifactConsumer getNonceConsumer() {
override Crypto::NonceArtifactConsumer getNonceConsumer() {
result = sink.getState().(InitializedCipherModeFlowState).getInitCall().getNonceArg()
}
@@ -360,9 +360,10 @@ module JCAModel {
/**
* Initialization vectors and other nonce artifacts
*/
abstract class NonceParameterInstantiation extends NonceArtifactInstance instanceof ClassInstanceExpr
{
override DataFlow::Node getOutputNode() { result.asExpr() = this }
abstract class NonceParameterInstantiation extends ClassInstanceExpr {
DataFlow::Node getOutputNode() { result.asExpr() = this }
abstract DataFlow::Node getInputNode();
}
class IvParameterSpecInstance extends NonceParameterInstantiation {
@@ -396,32 +397,25 @@ module JCAModel {
}
}
module NonceArtifactToCipherInitCallConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
exists(NonceParameterInstantiation n |
src = n.getOutputNode() and
not exists(IvParameterSpecGetIvCall m | n.getInputNode().asExpr() = m)
)
}
predicate isSink(DataFlow::Node sink) {
exists(CipherInitCall c | c.getNonceArg() = sink.asExpr())
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(IvParameterSpecGetIvCall m |
node1.asExpr() = m.getQualifier() and
node2.asExpr() = m
)
or
exists(NonceParameterInstantiation n |
node1 = n.getInputNode() and
node2.asExpr() = n
)
}
predicate additionalFlowSteps(DataFlow::Node node1, DataFlow::Node node2) {
exists(IvParameterSpecGetIvCall m |
node1.asExpr() = m.getQualifier() and
node2.asExpr() = m
)
or
exists(NonceParameterInstantiation n |
node1 = n.getInputNode() and
node2 = n.getOutputNode()
)
}
module NonceArtifactToCipherInitCallFlow = DataFlow::Global<NonceArtifactToCipherInitCallConfig>;
class NonceAdditionalFlowInputStep extends AdditionalFlowInputStep {
DataFlow::Node output;
NonceAdditionalFlowInputStep() { additionalFlowSteps(this, output) }
override DataFlow::Node getOutput() { result = output }
}
/**
* A data-flow configuration to track flow from a mode field access to
@@ -487,7 +481,7 @@ module JCAModel {
}
}
class CipherInitCallNonceArgConsumer extends Crypto::ArtifactConsumer instanceof Expr {
class CipherInitCallNonceArgConsumer extends Crypto::NonceArtifactConsumer instanceof Expr {
CipherInitCallNonceArgConsumer() { this = any(CipherInitCall call).getNonceArg() }
override DataFlow::Node getInputNode() { result.asExpr() = this }

View File

@@ -65,6 +65,19 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
override string getAdditionalDescription() { result = this.toString() }
}
class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal {
override DataFlow::Node getOutputNode() { result.asExpr() = this }
override predicate flowsTo(Crypto::FlowAwareElement other) {
other instanceof NonceArtifactInstance and
// limit to only nonces for now
// TODO: separate config to avoid blowing up data-flow analysis
GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
}
override string getAdditionalDescription() { result = this.toString() }
}
/**
* Random number generation, where each instance is modelled as the expression
* tied to an output node (i.e., the result of the source of randomness)
@@ -94,6 +107,12 @@ class InsecureRandomnessInstance extends RandomnessInstance {
/**
* Artifact output to node input configuration
*/
abstract class AdditionalFlowInputStep extends DataFlow::Node {
abstract DataFlow::Node getOutput();
final DataFlow::Node getInput() { result = this }
}
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::ArtifactElement artifact).getOutputNode()
@@ -106,14 +125,28 @@ module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}
module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;
abstract class NonceArtifactInstance extends Crypto::NonceArtifactInstance {
class NonceArtifactInstance extends Crypto::NonceArtifactInstance {
NonceArtifactInstance() { this instanceof Crypto::NonceArtifactConsumer }
override predicate flowsTo(Crypto::FlowAwareElement other) {
ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
}
override DataFlow::Node getOutputNode() {
result = this.(Crypto::NonceArtifactConsumer).getOutputNode()
}
override DataFlow::Node getInputNode() {
result = this.(Crypto::NonceArtifactConsumer).getInputNode()
}
}
/**
@@ -131,6 +164,10 @@ module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}
module GenericDataSourceUniversalFlow = DataFlow::Global<GenericDataSourceUniversalFlowConfig>;