Crypto: OperationStep overhaul to account for errors and missing interproc flow.

This commit is contained in:
REDMOND\brodes
2025-08-25 16:59:09 -04:00
parent b7ceeb399f
commit 5d29240f27
18 changed files with 205 additions and 185 deletions

View File

@@ -14,8 +14,8 @@ module CryptoInput implements InputSig<Language::Location> {
result = node.asExpr() or
result = node.asParameter() or
result = node.asVariable() or
result = node.asDefiningArgument()
// TODO: do we need asIndirectExpr()?
result = node.asDefiningArgument() or
result = node.asIndirectExpr()
}
string locationToFileBaseNameAndLineNumberString(Location location) {
@@ -93,7 +93,10 @@ module GenericDataSourceFlow = TaintTracking::Global<GenericDataSourceFlowConfig
private class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof OpenSslGenericSourceCandidateLiteral
{
override DataFlow::Node getOutputNode() { result.asExpr() = this }
override DataFlow::Node getOutputNode() {
// A literal can be a string or an int, so handling both indirect and direct cases
[result.asIndirectExpr(), result.asExpr()] = this
}
override predicate flowsTo(Crypto::FlowAwareElement other) {
// TODO: separate config to avoid blowing up data-flow analysis

View File

@@ -12,7 +12,7 @@ class EvpCipherAlgorithmValueConsumer extends CipherAlgorithmValueConsumer {
DataFlow::Node resultNode;
EvpCipherAlgorithmValueConsumer() {
resultNode.asExpr() = this and
resultNode.asIndirectExpr() = this and
(
this.(Call).getTarget().getName() in [
"EVP_get_cipherbyname", "EVP_get_cipherbyobj", "EVP_get_cipherbynid"

View File

@@ -23,7 +23,7 @@ class DirectAlgorithmValueConsumer extends OpenSslAlgorithmValueConsumer instanc
*/
override DataFlow::Node getResultNode() {
this instanceof OpenSslDirectAlgorithmFetchCall and
result.asExpr() = this
result.asIndirectExpr() = this
// NOTE: if instanceof OpenSslDirectAlgorithmOperationCall then there is no algorithm generated
// the algorithm is directly used
}

View File

@@ -12,7 +12,7 @@ class EvpEllipticCurveAlgorithmConsumer extends EllipticCurveValueConsumer {
DataFlow::Node resultNode;
EvpEllipticCurveAlgorithmConsumer() {
resultNode.asExpr() = this.(Call) and // in all cases the result is the return
resultNode.asIndirectExpr() = this.(Call) and // in all cases the result is the return
(
this.(Call).getTarget().getName() in ["EVP_EC_gen", "EC_KEY_new_by_curve_name"] and
valueArgNode.asExpr() = this.(Call).getArgument(0)

View File

@@ -64,7 +64,7 @@ class EvpDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
DataFlow::Node resultNode;
EvpDigestAlgorithmValueConsumer() {
resultNode.asExpr() = this and
resultNode.asIndirectExpr() = this and
(
this.(Call).getTarget().getName() in [
"EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"

View File

@@ -11,7 +11,7 @@ class EvpKemAlgorithmValueConsumer extends KemAlgorithmValueConsumer {
DataFlow::Node resultNode;
EvpKemAlgorithmValueConsumer() {
resultNode.asExpr() = this and
resultNode.asIndirectExpr() = this and
(
this.(Call).getTarget().getName() = "EVP_KEM_fetch" and
valueArgNode.asExpr() = this.(Call).getArgument(1)

View File

@@ -11,7 +11,7 @@ class EvpKeyExchangeAlgorithmValueConsumer extends KeyExchangeAlgorithmValueCons
DataFlow::Node resultNode;
EvpKeyExchangeAlgorithmValueConsumer() {
resultNode.asExpr() = this and
resultNode.asIndirectExpr() = this and
(
this.(Call).getTarget().getName() = "EVP_KEYEXCH_fetch" and
valueArgNode.asExpr() = this.(Call).getArgument(1)

View File

@@ -11,7 +11,7 @@ class EvpPKeyAlgorithmConsumer extends PKeyValueConsumer {
DataFlow::Node resultNode;
EvpPKeyAlgorithmConsumer() {
resultNode.asExpr() = this.(Call) and // in all cases the result is the return
resultNode.asIndirectExpr() = this.(Call) and // in all cases the result is the return
(
// NOTE: some of these consumers are themselves key gen operations,
// in these cases, the operation will be created separately for the same function.

View File

@@ -14,7 +14,7 @@ class Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer extends PaddingAlgorit
DataFlow::Node resultNode;
Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer() {
resultNode.asExpr() = this.(Call).getArgument(0) and
resultNode.asDefiningArgument() = this.(Call).getArgument(0) and
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_padding" and
valueArgNode.asExpr() = this.(Call).getArgument(1)
}

View File

@@ -12,7 +12,7 @@ class EvpSignatureAlgorithmValueConsumer extends SignatureAlgorithmValueConsumer
DataFlow::Node resultNode;
EvpSignatureAlgorithmValueConsumer() {
resultNode.asExpr() = this and
resultNode.asIndirectExpr() = this and
(
// EVP_SIGNATURE
this.(Call).getTarget().getName() = "EVP_SIGNATURE_fetch" and

View File

@@ -13,7 +13,9 @@ module AvcToCallArgConfig implements DataFlow::ConfigSig {
* Trace to any call accepting the algorithm.
* NOTE: users must restrict this set to the operations they are interested in.
*/
predicate isSink(DataFlow::Node sink) { exists(Call c | c.getAnArgument() = sink.asExpr()) }
predicate isSink(DataFlow::Node sink) {
exists(Call c | c.getAnArgument() = [sink.asIndirectExpr(), sink.asExpr()])
}
}
module AvcToCallArgFlow = DataFlow::Global<AvcToCallArgConfig>;

View File

@@ -15,11 +15,11 @@ abstract class FinalCipherOperationStep extends OperationStep {
*/
abstract class EvpCipherOperationFinalStep extends FinalCipherOperationStep {
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -28,9 +28,9 @@ abstract class EvpCipherOperationFinalStep extends FinalCipherOperationStep {
*/
abstract class EvpCipherInitializer extends OperationStep {
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and
result.asIndirectExpr() = this.getArgument(1) and
type = PrimaryAlgorithmIO() and
// Constants that are not equal to zero or
// non-constants (e.g., variable accesses, which require data-flow to determine the value)
@@ -40,7 +40,7 @@ abstract class EvpCipherInitializer extends OperationStep {
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -127,13 +127,13 @@ class EvpPkeyEncryptDecryptInit extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = OsslParamIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -161,7 +161,7 @@ class EvpCipherUpdateCall extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
}
@@ -169,7 +169,7 @@ class EvpCipherUpdateCall extends OperationStep {
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(1) and type = CiphertextIO()
or
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = UpdateStep() }

View File

@@ -38,7 +38,9 @@ class EvpNewKeyCtx extends OperationStep instanceof Call {
type = OsslLibContextIO()
}
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = ContextIO() }
override DataFlow::Node getOutput(IOType type) {
result.asIndirectExpr() = this and type = ContextIO()
}
override OperationStepType getStepType() { result = ContextCreationStep() }
}
@@ -52,13 +54,13 @@ class EvpCtxSetEcParamgenCurveNidInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -102,7 +104,7 @@ class EvpCtxSetHashInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and
type = HashAlgorithmIO() and
@@ -115,7 +117,7 @@ class EvpCtxSetHashInitializer extends OperationStep {
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -134,13 +136,13 @@ class EvpCtxSetKeySizeInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = KeySizeIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -150,7 +152,7 @@ class EvpCtxSetMacKeyInitializer extends OperationStep {
EvpCtxSetMacKeyInitializer() { this.getTarget().getName() = "EVP_PKEY_CTX_set_mac_key" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(2) and type = KeySizeIO()
or
@@ -159,7 +161,7 @@ class EvpCtxSetMacKeyInitializer extends OperationStep {
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -171,13 +173,13 @@ class EvpCtxSetPaddingInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PaddingAlgorithmIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -189,13 +191,13 @@ class EvpCtxSetSaltLengthInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SaltLengthIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }

View File

@@ -25,13 +25,13 @@ class EvpDigestInitVariantCalls extends OperationStep instanceof Call {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and
result.asDefiningArgument() = this.getArgument(0) and
type = ContextIO()
}
@@ -45,13 +45,13 @@ class EvpDigestUpdateCall extends OperationStep instanceof Call {
EvpDigestUpdateCall() { this.getTarget().getName() = "EVP_DigestUpdate" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and
result.asDefiningArgument() = this.getArgument(0) and
type = ContextIO()
}
@@ -66,15 +66,15 @@ class EvpQDigestOperation extends FinalDigestOperation instanceof Call {
EvpQDigestOperation() { this.getTarget().getName() = "EVP_Q_digest" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
or
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and
result.asDefiningArgument() = this.getArgument(0) and
type = ContextIO()
or
result.asDefiningArgument() = this.getArgument(5) and type = DigestIO()
@@ -85,7 +85,7 @@ class EvpDigestOperation extends FinalDigestOperation instanceof Call {
EvpDigestOperation() { this.getTarget().getName() = "EVP_Digest" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(4) and type = PrimaryAlgorithmIO()
result.asIndirectExpr() = this.getArgument(4) and type = PrimaryAlgorithmIO()
or
result.asExpr() = this.getArgument(0) and type = PlaintextIO()
}
@@ -104,14 +104,15 @@ class EvpDigestFinalCall extends FinalDigestOperation instanceof Call {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and
result.asDefiningArgument() = this.getArgument(0) and
type = ContextIO()
or
result.asDefiningArgument() = this.getArgument(1) and type = DigestIO()
//result.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = this.getArgument(1)
}
}

View File

@@ -13,7 +13,7 @@ class ECKeyGen extends OperationStep instanceof Call {
ECKeyGen() { this.(Call).getTarget().getName() = "EC_KEY_generate_key" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.(Call).getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.(Call).getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
@@ -33,11 +33,11 @@ class EvpKeyGenInitialize extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -57,13 +57,13 @@ class EvpPKeyQKeyGen extends KeyGenFinalOperationStep instanceof Call {
EvpPKeyQKeyGen() { this.getTarget().getName() = "EVP_PKEY_Q_keygen" }
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this and type = KeyIO()
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
// When arg 3 is a derived type, it is a curve name, otherwise it is a key size for RSA if provided
// and arg 2 is the algorithm type
@@ -120,7 +120,7 @@ class RsaGenerateKeyEx extends KeyGenFinalOperationStep instanceof Call {
override DataFlow::Node getInput(IOType type) {
// arg 0 comes in as a blank RSA key, which we consider a context,
// on output it is considered a key
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
}
@@ -131,13 +131,13 @@ class EvpPkeyGen extends KeyGenFinalOperationStep instanceof Call {
EvpPkeyGen() { this.getTarget().getName() in ["EVP_PKEY_generate", "EVP_PKEY_keygen"] }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asDefiningArgument() = this.getArgument(1) and type = KeyIO()
or
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -158,7 +158,6 @@ class EvpNewMacKey extends KeyGenFinalOperationStep {
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
}
/// TODO: https://docs.openssl.org/3.0/man3/EVP_PKEY_new/#synopsis
/**
* An `KeyGenerationOperationInstance` for the for all key gen final operation steps.

View File

@@ -198,8 +198,7 @@ abstract class OperationStep extends Call {
* If `sink` is `this`, then this holds true.
*/
predicate flowsToOperationStep(OperationStep sink) {
sink = this or
OperationStepFlow::flow(this.getAnOutput(), sink.getAnInput())
OperationStepFlow::flow(this.getAnOutput(), [sink.getAnInput(), sink.getAnOutput()])
}
/**
@@ -207,8 +206,7 @@ abstract class OperationStep extends Call {
* If `source` is `this`, then this holds true.
*/
predicate flowsFromOperationStep(OperationStep source) {
source = this or
OperationStepFlow::flow(source.getAnOutput(), this.getAnInput())
OperationStepFlow::flow(source.getAnOutput(), [this.getAnInput(), this.getAnOutput()])
}
/**
@@ -226,11 +224,22 @@ abstract class OperationStep extends Call {
* the operation allows for multiple inputs (like plaintext for cipher update calls before final).
*/
OperationStep getDominatingInitializersToStep(IOType type) {
result.flowsToOperationStep(this) and
//exists(IOType sinkInType |
//sinkInType = ContextIO() or sinkInType = type |
result.flowsToOperationStep(this) and //, sinkInType)
//)
result.setsValue(type) and
(
// Do not consider a 'reset' to occur on updates
result.getStepType() = UpdateStep()
// but only for resets that are part of the same update/finalize
// progression (e.g., an update for an unrelated finalize is ignored)
result.getStepType() = UpdateStep() and
not exists(OperationStep op |
result.flowsToOperationStep(op) and
op.flowsToOperationStep(this) and
op != this and
op.getStepType() = FinalStep()
)
or
not exists(OperationStep reset |
result != reset and
@@ -269,20 +278,22 @@ abstract class OperationStep extends Call {
Crypto::AlgorithmValueConsumer getPrimaryAlgorithmValueConsumer() {
this instanceof Crypto::AlgorithmValueConsumer and result = this
or
exists(DataFlow::Node src, DataFlow::Node sink, IOType t, OperationStep avcConsumingPred |
(t = PrimaryAlgorithmIO() or t = ContextIO() or t = KeyIO()) and
exists(
DataFlow::Node src, DataFlow::Node sink, IOType srcIntype, OperationStep avcConsumingPred
|
(srcIntype = ContextIO() or srcIntype = PrimaryAlgorithmIO() or srcIntype = KeyIO()) and
avcConsumingPred.flowsToOperationStep(this) and
src.asExpr() = result and
sink = avcConsumingPred.getInput(t) and
src.asIndirectExpr() = result and
sink = avcConsumingPred.getInput(srcIntype) and
AvcToOperationStepFlow::flow(src, sink) and
(
// Case 1: the avcConsumingPred step is a dominating primary algorithm initialization step
// or dominating key initialization step
(t = PrimaryAlgorithmIO() or t = KeyIO()) and
avcConsumingPred = this.getDominatingInitializersToStep(t)
(srcIntype = PrimaryAlgorithmIO() or srcIntype = KeyIO()) and
avcConsumingPred = this.getDominatingInitializersToStep(srcIntype)
or
// Case 2: the pred is a context input
t = ContextIO()
srcIntype = ContextIO()
)
)
}
@@ -297,7 +308,7 @@ abstract class OperationStep extends Call {
or
exists(DataFlow::Node src, DataFlow::Node sink |
AvcToOperationStepFlow::flow(src, sink) and
src.asExpr() = result and
src.asIndirectExpr() = result and
sink = this.getInput(type)
)
}
@@ -375,7 +386,7 @@ private class CtxCopyOutArgCall extends CtxPassThroughCall {
CtxCopyOutArgCall() {
this.getTarget().getName().toLowerCase().matches("%copy%") and
n1.asExpr() = this.getAnArgument() and
n1.asIndirectExpr() = this.getAnArgument() and
n1.getType() instanceof CtxType and
n2.asDefiningArgument() = this.getAnArgument() and
n2.getType() instanceof CtxType and
@@ -396,13 +407,13 @@ private class CtxCopyReturnCall extends CtxPassThroughCall, CtxPointerExpr {
CtxCopyReturnCall() {
this.getTarget().getName().toLowerCase().matches("%dup%") and
n1.asExpr() = this.getAnArgument() and
n1.asIndirectExpr() = this.getAnArgument() and
n1.getType() instanceof CtxType
}
override DataFlow::Node getNode1() { result = n1 }
override DataFlow::Node getNode2() { result.asExpr() = this }
override DataFlow::Node getNode2() { result.asIndirectExpr() = this }
}
// TODO: is this still needed? It appears to be (tests fail without it) but
@@ -422,11 +433,7 @@ private class CtxParamGenCall extends CtxPassThroughCall {
CtxParamGenCall() {
this.getTarget().getName() = "EVP_PKEY_paramgen" and
n1.asExpr() = this.getArgument(0) and
(
n2.asExpr() = this.getArgument(1)
or
n2.asDefiningArgument() = this.getArgument(1)
)
n2.asDefiningArgument() = this.getArgument(1)
}
override DataFlow::Node getNode1() { result = n1 }
@@ -453,15 +460,28 @@ module OperationStepFlowConfig implements DataFlow::ConfigSig {
}
predicate isBarrier(DataFlow::Node node) {
exists(CtxClearCall c | c.getAnArgument() = node.asExpr())
exists(CtxClearCall c | c.getAnArgument() = [node.asExpr(), node.asIndirectExpr()])
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(CtxPassThroughCall c | c.getNode1() = node1 and c.getNode2() = node2)
or
// Flow out through all outputs from an operation step if more than one output
// is defined.
exists(OperationStep s | s.getAnInput() = node1 and s.getAnOutput() = node2)
// Flow only through context and key inputs and outputs
// keys and context generally hold unifying context that link multiple steps
exists(OperationStep s, IOType inType, IOType outType |
(
inType = ContextIO()
or
inType = KeyIO()
) and
(
outType = ContextIO()
or
outType = KeyIO()
) and
s.getInput(inType) = node1 and
s.getOutput(outType) = node2
)
// TODO: consideration for additional alises defined as follows:
// if an output from an operation step itself flows from the output of another operation step
// then the source of that flow's outputs (all of them) are potential aliases
@@ -481,7 +501,7 @@ module AvcToOperationStepFlowConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { exists(OperationStep s | s.getAnInput() = sink) }
predicate isBarrier(DataFlow::Node node) {
exists(CtxClearCall c | c.getAnArgument() = node.asExpr())
exists(CtxClearCall c | c.getAnArgument() = [node.asExpr(), node.asIndirectExpr()])
}
/**

View File

@@ -37,36 +37,32 @@ class EvpSignatureDigestInitializer extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
result.asExpr() = this.getArgument(3) and
result.asIndirectExpr() = this.getArgument(3) and
type = OsslLibContextIO()
or
result.asExpr() = this.getArgument(2) and type = HashAlgorithmIO()
result.asIndirectExpr() = this.getArgument(2) and type = HashAlgorithmIO()
or
this.getTarget().getName() = "EVP_DigestSignInit" and
result.asExpr() = this.getArgument(4) and
result.asIndirectExpr() = this.getArgument(4) and
type = KeyIO()
or
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
result.asExpr() = this.getArgument(5) and
result.asIndirectExpr() = this.getArgument(5) and
type = KeyIO()
or
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
result.asExpr() = this.getArgument(6) and
result.asIndirectExpr() = this.getArgument(6) and
type = OsslParamIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
// EVP_PKEY_CTX
result.asExpr() = this.getArgument(1) and type = ContextIO()
or
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
result.asExpr() = this.getArgument(6) and
type = ContextIO()
result.asDefiningArgument() = this.getArgument(1) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -79,13 +75,13 @@ class EvpSignInit extends OperationStep {
EvpSignInit() { this.getTarget().getName() in ["EVP_SignInit", "EVP_SignInit_ex"] }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = HashAlgorithmIO()
result.asIndirectExpr() = this.getArgument(1) and type = HashAlgorithmIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -107,22 +103,22 @@ class EvpPkeySignInit extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
this.getTarget().getName() in ["EVP_PKEY_sign_init_ex2", "EVP_PKEY_sign_message_init"] and
result.asExpr() = this.getArgument(1) and
result.asIndirectExpr() = this.getArgument(1) and
type = PrimaryAlgorithmIO()
or
this.getTarget().getName() = "EVP_PKEY_sign_init_ex" and
result.asExpr() = this.getArgument(1) and
result.asIndirectExpr() = this.getArgument(1) and
type = OsslParamIO()
or
// Argument 2 (0 based) only exists for EVP_PKEY_sign_init_ex2 and EVP_PKEY_sign_message_init
result.asExpr() = this.getArgument(2) and type = OsslParamIO()
result.asIndirectExpr() = this.getArgument(2) and type = OsslParamIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -139,13 +135,13 @@ class EvpSignatureUpdateCall extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = UpdateStep() }
@@ -158,19 +154,21 @@ class EvpSignFinal extends SignatureFinalOperation {
EvpSignFinal() { this.getTarget().getName() in ["EVP_SignFinal_ex", "EVP_SignFinal"] }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(3) and type = KeyIO()
result.asIndirectExpr() = this.getArgument(3) and type = KeyIO()
or
// params above 3 (0-based) only exist for EVP_SignFinal_ex
result.asExpr() = this.getArgument(4) and
result.asIndirectExpr() = this.getArgument(4) and
type = OsslLibContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
or
result.asDefiningArgument() = this.getArgument(2) and type = SignatureSizeIO()
}
}
@@ -181,15 +179,15 @@ class EvpPkeySign extends SignatureFinalOperation {
EvpPkeySign() { this.getTarget().getName() = "EVP_PKEY_sign" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
}
}
@@ -201,15 +199,15 @@ class EvpDigestSign extends SignatureOrMacFinalOperation {
EvpDigestSign() { this.getTarget().getName() = "EVP_DigestSign" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
}
}
@@ -220,13 +218,15 @@ class EvpPkeySignFinal extends SignatureFinalOperation {
EvpPkeySignFinal() { this.getTarget().getName() = "EVP_PKEY_sign_message_final" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
or
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
}
}
@@ -238,13 +238,13 @@ class EvpDigestSignFinal extends SignatureOrMacFinalOperation {
EvpDigestSignFinal() { this.getTarget().getName() = "EVP_DigestSignFinal" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
}
override OperationStepType getStepType() { result = FinalStep() }
@@ -259,31 +259,31 @@ class EvpDigestVerifyInit extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(2) and type = HashAlgorithmIO()
result.asIndirectExpr() = this.getArgument(2) and type = HashAlgorithmIO()
or
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
result.asExpr() = this.getArgument(3) and
result.asIndirectExpr() = this.getArgument(3) and
type = OsslLibContextIO()
or
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
result.asExpr() = this.getArgument(5) and
result.asIndirectExpr() = this.getArgument(5) and
type = KeyIO()
or
this.getTarget().getName() = "EVP_DigestVerifyInit" and
result.asExpr() = this.getArgument(4) and
result.asIndirectExpr() = this.getArgument(4) and
type = KeyIO()
or
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
result.asExpr() = this.getArgument(6) and
result.asIndirectExpr() = this.getArgument(6) and
type = OsslParamIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(1) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -296,13 +296,13 @@ class EvpDigestVerifyUpdate extends OperationStep {
EvpDigestVerifyUpdate() { this.getTarget().getName() = "EVP_DigestVerifyUpdate" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = UpdateStep() }
@@ -315,13 +315,13 @@ class EvpDigestVerifyFinal extends SignatureFinalOperation {
EvpDigestVerifyFinal() { this.getTarget().getName() = "EVP_DigestVerifyFinal" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -332,15 +332,15 @@ class EvpDigestVerify extends SignatureFinalOperation {
EvpDigestVerify() { this.getTarget().getName() = "EVP_DigestVerify" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -358,23 +358,23 @@ class EvpVerifyInit extends OperationStep {
}
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
this.getTarget().getName() = "EVP_PKEY_verify_init_ex" and
result.asExpr() = this.getArgument(1) and
result.asIndirectExpr() = this.getArgument(1) and
type = OsslParamIO()
or
this.getTarget().getName() in ["EVP_PKEY_verify_init_ex2", "EVP_PKEY_verify_message_init"] and
result.asExpr() = this.getArgument(1) and
result.asIndirectExpr() = this.getArgument(1) and
type = PrimaryAlgorithmIO()
or
this.getTarget().getName() in ["EVP_PKEY_verify_init_ex2", "EVP_PKEY_verify_message_init"] and
result.asExpr() = this.getArgument(2) and
result.asIndirectExpr() = this.getArgument(2) and
type = OsslParamIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -388,15 +388,15 @@ class EvpCtxSetSignatureInitializer extends OperationStep {
EvpCtxSetSignatureInitializer() { this.getTarget().getName() = "EVP_PKEY_CTX_set_signature" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
or
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = InitializerStep() }
@@ -409,15 +409,15 @@ class EvpVerifyMessageUpdate extends OperationStep {
EvpVerifyMessageUpdate() { this.getTarget().getName() = "EVP_PKEY_verify_message_update" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
or
result.asExpr() = this.getArgument(2) and type = PlaintextSizeIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
override OperationStepType getStepType() { result = UpdateStep() }
@@ -430,11 +430,11 @@ class EvpVerifyMessageFinal extends SignatureFinalOperation {
EvpVerifyMessageFinal() { this.getTarget().getName() = "EVP_PKEY_verify_message_final" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -445,19 +445,19 @@ class EvpVerify extends SignatureFinalOperation {
EvpVerify() { this.getTarget().getName() = "EVP_PKEY_verify" }
override DataFlow::Node getInput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
or
result.asExpr() = this.getArgument(1) and type = SignatureIO()
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
or
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
or
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
or
result.asExpr() = this.getArgument(4) and type = PlaintextSizeIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
}
}
@@ -469,25 +469,26 @@ class RsaSign extends SignatureFinalOperation {
RsaSign() { this.getTarget().getName() in ["RSA_sign", "RSA_verify"] }
override DataFlow::Node getInput(IOType type) {
// Arg 0 is an NID (so asExpr not asIndirectExpr)
result.asExpr() = this.getArgument(0) and type = HashAlgorithmIO()
or
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
or
result.asExpr() = this.getArgument(2) and type = PlaintextSizeIO()
or
this.getTarget().getName() = "RSA_verify" and
result.asExpr() = this.getArgument(3) and
result.asIndirectExpr() = this.getArgument(3) and
type = SignatureIO()
or
this.getTarget().getName() = "RSA_verify" and
result.asExpr() = this.getArgument(4) and
result.asIndirectExpr() = this.getArgument(4) and
type = SignatureSizeIO()
or
result.asExpr() = this.getArgument(5) and type = KeyIO()
result.asIndirectExpr() = this.getArgument(5) and type = KeyIO()
}
override DataFlow::Node getOutput(IOType type) {
result.asExpr() = this.getArgument(0) and type = ContextIO()
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
or
this.getTarget().getName() = "RSA_sign" and
result.asDefiningArgument() = this.getArgument(3) and

View File

@@ -363,10 +363,10 @@ cleanup:
return ret;
}
/* =============================================================================
* LOW-LEVEL RSA API - Algorithm-specific functions (deprecated)
* =============================================================================
*/
// /* =============================================================================
// * LOW-LEVEL RSA API - Algorithm-specific functions (deprecated)
// * =============================================================================
// */
/**
* Sign using low-level RSA_sign API (deprecated, RSA-only)
@@ -375,17 +375,13 @@ cleanup:
int sign_using_rsa_sign(const unsigned char *message, size_t message_len,
unsigned char **signature, size_t *signature_len,
RSA *rsa_key, int hash_nid, const EVP_MD *md) {
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len;
int ret = 0;
if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
*signature_len = RSA_size(rsa_key);
*signature = OPENSSL_malloc(*signature_len);
if (!*signature) return 0;
if (RSA_sign(hash_nid, digest, digest_len, *signature,
if (RSA_sign(hash_nid, message, message_len, *signature,
(unsigned int*)signature_len, rsa_key) == 1) {
ret = 1;
} else {
@@ -403,19 +399,15 @@ int sign_using_rsa_sign(const unsigned char *message, size_t message_len,
int verify_using_rsa_verify(const unsigned char *message, size_t message_len,
const unsigned char *signature, size_t signature_len,
RSA *rsa_key, int hash_nid, const EVP_MD *md) {
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len;
if (!create_digest(message, message_len, md, digest, &digest_len)) return 0;
return RSA_verify(hash_nid, digest, digest_len, signature,
return RSA_verify(hash_nid, message, message_len, signature,
(unsigned int)signature_len, rsa_key);
}
/* =============================================================================
* LOW-LEVEL DSA API - Algorithm-specific functions (deprecated)
* =============================================================================
*/
// /* =============================================================================
// * LOW-LEVEL DSA API - Algorithm-specific functions (deprecated)
// * =============================================================================
// */
/**
* Sign using low-level DSA_do_sign API (deprecated, DSA-only)