diff --git a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll index b544079579af..f22bcae69275 100644 --- a/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll +++ b/cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPCipherOperation.qll @@ -67,37 +67,42 @@ abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperati } } -// abstract class EVP_Update_Call extends EVP_Cipher_Operation { } -abstract class EVP_Final_Call extends EVP_Cipher_Operation { - override Expr getInputArg() { none() } -} - -// TODO: only model Final (model final as operation and model update but not as an operation) -// Updates are multiple input consumers (most important) -// TODO: assuming update doesn't ouput, otherwise it outputs artifacts, but is not an operation class EVP_Cipher_Call extends EVP_Cipher_Operation { EVP_Cipher_Call() { this.(Call).getTarget().getName() = "EVP_Cipher" } override Expr getInputArg() { result = this.(Call).getArgument(2) } } -// ******* TODO: model UPDATE but not as the core operation, rather a step towards final -// see the JCA -// class EVP_Encrypt_Decrypt_or_Cipher_Update_Call extends EVP_Update_Call { -// EVP_Encrypt_Decrypt_or_Cipher_Update_Call() { -// this.(Call).getTarget().getName() in [ -// "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" -// ] -// } -// override Expr getInputArg() { result = this.(Call).getArgument(3) } -// } -class EVP_Encrypt_Decrypt_or_Cipher_Final_Call extends EVP_Final_Call { - EVP_Encrypt_Decrypt_or_Cipher_Final_Call() { +// NOTE: not modeled as cipher operations, these are intermediate calls +class EVP_Update_Call extends Call { + EVP_Update_Call() { + this.(Call).getTarget().getName() in [ + "EVP_EncryptUpdate", "EVP_DecryptUpdate", "EVP_CipherUpdate" + ] + } + + Expr getInputArg() { result = this.(Call).getArgument(3) } + + DataFlow::Node getInputNode() { result.asExpr() = this.getInputArg() } + + Expr getContextArg() { result = this.(Call).getArgument(0) } +} + +class EVP_Final_Call extends EVP_Cipher_Operation { + EVP_Final_Call() { this.(Call).getTarget().getName() in [ "EVP_EncryptFinal_ex", "EVP_DecryptFinal_ex", "EVP_CipherFinal_ex", "EVP_EncryptFinal", "EVP_DecryptFinal", "EVP_CipherFinal" ] } + + EVP_Update_Call getUpdateCalls() { + CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg()) + } + + override Expr getInputArg() { result = this.getUpdateCalls().getInputArg() } + + override Crypto::ConsumerInputDataFlowNode getInputConsumer() { result = this.getInputNode() } } class EVP_PKEY_Operation extends EVP_Cipher_Operation { diff --git a/java/ql/lib/experimental/quantum/JCA.qll b/java/ql/lib/experimental/quantum/JCA.qll index ceca0e45464b..867d6f2c9b8f 100644 --- a/java/ql/lib/experimental/quantum/JCA.qll +++ b/java/ql/lib/experimental/quantum/JCA.qll @@ -611,6 +611,8 @@ module JCAModel { } class CipherOperationInstance extends Crypto::KeyOperationInstance instanceof CipherOperationCall { + CipherOperationInstance() { not this.isIntermediate() } + override Crypto::KeyOperationSubtype getKeyOperationSubtype() { if CipherFlowAnalysisImpl::hasInit(this) then result = CipherFlowAnalysisImpl::getInitFromUse(this, _, _).getCipherOperationModeType()