-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Quantum: Add base classes for OpenSSL EVP methods #19607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6d1b1d1
af8702d
f103e8b
328cf79
f04fa58
eff6eb3
60d9b6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,118 +8,78 @@ private import OpenSSLOperationBase | |
private import EVPHashInitializer | ||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers | ||
|
||
// import EVPHashConsumers | ||
abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance { | ||
Expr getContextArg() { result = this.(Call).getArgument(0) } | ||
class EVP_Digest_Update_Call extends EVPUpdate { | ||
EVP_Digest_Update_Call() { this.(Call).getTarget().getName() = "EVP_DigestUpdate" } | ||
|
||
Expr getAlgorithmArg() { result = this.getInitCall().getAlgorithmArg() } | ||
|
||
EVP_Hash_Initializer getInitCall() { | ||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) | ||
} | ||
|
||
/** | ||
* By default, the algorithm value comes from the init call. | ||
* There are variants where this isn't true, in which case the | ||
* subclass should override this method. | ||
*/ | ||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { | ||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(), | ||
DataFlow::exprNode(this.getAlgorithmArg())) | ||
} | ||
} | ||
|
||
private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig { | ||
predicate isSource(DataFlow::Node source) { | ||
exists(OpenSSLAlgorithmValueConsumer c | c.getResultNode() = source) | ||
} | ||
|
||
predicate isSink(DataFlow::Node sink) { | ||
exists(EVP_Hash_Operation c | c.getAlgorithmArg() = sink.asExpr()) | ||
} | ||
override Expr getInputArg() { result = this.(Call).getArgument(1) } | ||
} | ||
|
||
private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>; | ||
|
||
//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis | ||
class EVP_Q_Digest_Operation extends EVP_Hash_Operation { | ||
class EVP_Q_Digest_Operation extends EVPOperation, Crypto::HashOperationInstance { | ||
EVP_Q_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Q_digest" } | ||
|
||
//override Crypto::AlgorithmConsumer getAlgorithmConsumer() { } | ||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } | ||
|
||
override EVP_Hash_Initializer getInitCall() { | ||
// This variant of digest does not use an init | ||
// and even if it were used, the init would be ignored/undefined | ||
none() | ||
} | ||
|
||
override Expr getOutputArg() { result = this.(Call).getArgument(5) } | ||
|
||
override Expr getInputArg() { result = this.(Call).getArgument(3) } | ||
|
||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } | ||
|
||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } | ||
override Expr getOutputArg() { result = this.(Call).getArgument(5) } | ||
|
||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { | ||
// The operation is a direct algorithm consumer | ||
// NOTE: the operation itself is already modeld as a value consumer, so we can | ||
// simply return 'this', see modeled hash algorithm consuers for EVP_Q_Digest | ||
this = result | ||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] There’s repeated boilerplate in many EVP* classes for overriding Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
result = EVPOperation.super.getOutputArtifact() | ||
} | ||
|
||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) } | ||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { | ||
result = EVPOperation.super.getInputConsumer() | ||
} | ||
} | ||
|
||
class EVP_Digest_Operation extends EVP_Hash_Operation { | ||
class EVP_Digest_Operation extends EVPOperation, Crypto::HashOperationInstance { | ||
EVP_Digest_Operation() { this.(Call).getTarget().getName() = "EVP_Digest" } | ||
|
||
// There is no context argument for this function | ||
override Expr getContextArg() { none() } | ||
|
||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(4) } | ||
|
||
override EVP_Hash_Initializer getInitCall() { | ||
// This variant of digest does not use an init | ||
// and even if it were used, the init would be ignored/undefined | ||
none() | ||
} | ||
|
||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(4) } | ||
|
||
override Expr getOutputArg() { result = this.(Call).getArgument(2) } | ||
|
||
override Expr getInputArg() { result = this.(Call).getArgument(0) } | ||
|
||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } | ||
|
||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } | ||
} | ||
|
||
// NOTE: not modeled as hash operations, these are intermediate calls | ||
class EVP_Digest_Update_Call extends Call { | ||
EVP_Digest_Update_Call() { this.(Call).getTarget().getName() in ["EVP_DigestUpdate"] } | ||
|
||
Expr getInputArg() { result = this.(Call).getArgument(1) } | ||
override Expr getOutputArg() { result = this.(Call).getArgument(2) } | ||
|
||
DataFlow::Node getInputNode() { result.asExpr() = this.getInputArg() } | ||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { | ||
result = EVPOperation.super.getOutputArtifact() | ||
} | ||
|
||
Expr getContextArg() { result = this.(Call).getArgument(0) } | ||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { | ||
result = EVPOperation.super.getInputConsumer() | ||
} | ||
} | ||
|
||
class EVP_Digest_Final_Call extends EVP_Hash_Operation { | ||
class EVP_Digest_Final_Call extends EVPFinal, Crypto::HashOperationInstance { | ||
EVP_Digest_Final_Call() { | ||
this.(Call).getTarget().getName() in [ | ||
"EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF" | ||
] | ||
} | ||
|
||
EVP_Digest_Update_Call getUpdateCalls() { | ||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) | ||
} | ||
|
||
override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() } | ||
|
||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } | ||
|
||
override Expr getOutputArg() { result = this.(Call).getArgument(1) } | ||
|
||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { result = this.getOutputNode() } | ||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { | ||
result = EVPFinal.super.getOutputArtifact() | ||
} | ||
|
||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { | ||
result = EVPFinal.super.getInputConsumer() | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.