Crypto: Separate out CTX parameter initialization, and add additional initializer subclasses.

This commit is contained in:
REDMOND\brodes
2025-06-09 16:49:54 -04:00
parent 4f2045bbdd
commit 729467ccd6
5 changed files with 128 additions and 27 deletions

View File

@@ -27,9 +27,37 @@ class EVP_Q_Digest_Algorithm_Consumer extends HashAlgorithmValueConsumer {
}
}
/**
* Instances from https://docs.openssl.org/3.0/man3/EVP_PKEY_CTX_ctrl/
* where the digest is directly consumed by name.
* In these cases, the operation is not yet performed, but there is
* these functions are treated as 'initializers' and track the algorithm through
* `EvpInitializer` mechanics, i.e., the resultNode is considered 'none'
*/
class EvpPkeySetCtxALgorithmConsumer extends HashAlgorithmValueConsumer {
DataFlow::Node valueArgNode;
EvpPkeySetCtxALgorithmConsumer() {
this.(Call).getTarget().getName() in [
"EVP_PKEY_CTX_set_rsa_mgf1_md_name", "EVP_PKEY_CTX_set_rsa_oaep_md_name",
"EVP_PKEY_CTX_set_dsa_paramgen_md_props"
] and
valueArgNode.asExpr() = this.(Call).getArgument(1)
}
override DataFlow::Node getResultNode() { none() }
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
}
}
/**
* The EVP digest algorithm getters
* https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
* https://docs.openssl.org/3.0/man3/EVP_DigestSignInit/#name
*/
class EVPDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
DataFlow::Node valueArgNode;
@@ -43,8 +71,11 @@ class EVPDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
] and
valueArgNode.asExpr() = this.(Call).getArgument(0)
or
this.(Call).getTarget().getName() = "EVP_MD_fetch" and
this.(Call).getTarget().getName() in ["EVP_MD_fetch"] and
valueArgNode.asExpr() = this.(Call).getArgument(1)
or
this.(Call).getTarget().getName() = "EVP_DigestSignInit_ex" and
valueArgNode.asExpr() = this.(Call).getArgument(2)
)
}

View File

@@ -50,32 +50,6 @@ class EVPNewKeyCtx extends EvpKeyInitializer {
//TODO: do we specify the algorithm from the key as well?
}
/**
* A call to `EVP_PKEY_CTX_set_rsa_keygen_bits`.
* This sets the key size for RSA key generation.
*/
class EVPSetRSAKeyKeyBits extends EvpKeySizeInitializer {
EVPSetRSAKeyKeyBits() { this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_keygen_bits" }
override Expr getKeySizeArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
/**
* A call to `EVP_PKEY_CTX_set_dsa_paramgen_bits`.
* This sets the key size for DSA key generation.
*/
class EVPSetDSAKeyParamGenBits extends EvpKeySizeInitializer {
EVPSetDSAKeyParamGenBits() {
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_dsa_paramgen_bits"
}
override Expr getKeySizeArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
class EVPKeyGenOperation extends EVPFinal, Crypto::KeyGenerationOperationInstance {
DataFlow::Node keyResultNode;

View File

@@ -0,0 +1,69 @@
/**
* Initializers from https://docs.openssl.org/3.0/man3/EVP_PKEY_CTX_ctrl/
*/
import cpp
private import experimental.quantum.OpenSSL.CtxFlow
private import OpenSSLOperationBase
class EvpCtxSetAlgorithmInitializer extends EvpAlgorithmInitializer {
EvpCtxSetAlgorithmInitializer() {
this.(Call).getTarget().getName() in [
"EVP_PKEY_CTX_set_signature_md", "EVP_PKEY_CTX_set_rsa_mgf1_md_name",
"EVP_PKEY_CTX_set_rsa_mgf1_md", "EVP_PKEY_CTX_set_rsa_oaep_md_name",
"EVP_PKEY_CTX_set_rsa_oaep_md", "EVP_PKEY_CTX_set_dsa_paramgen_md",
"EVP_PKEY_CTX_set_dsa_paramgen_md_props", "EVP_PKEY_CTX_set_dh_kdf_md",
"EVP_PKEY_CTX_set_ec_paramgen_curve_nid", "EVP_PKEY_CTX_set_ecdh_kdf_md"
]
}
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
class EvpCtxSetKeySizeInitializer extends EvpKeySizeInitializer {
Expr arg;
EvpCtxSetKeySizeInitializer() {
this.(Call).getTarget().getName() in [
"EVP_PKEY_CTX_set_rsa_keygen_bits", "EVP_PKEY_CTX_set_dsa_paramgen_bits"
] and
arg = this.(Call).getArgument(1)
or
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_mac_key" and
arg = this.(Call).getArgument(2)
}
override Expr getKeySizeArg() { result = arg }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
class EvpCtxSetKeyInitializer extends EvpKeyInitializer {
EvpCtxSetKeyInitializer() { this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_mac_key" }
override Expr getKeyArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
class EvpCtxSetPaddingInitializer extends EvpPaddingInitializer {
EvpCtxSetPaddingInitializer() {
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_padding"
}
override Expr getPaddingArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}
class EvpCtxSetSaltLengthInitializer extends EvpSaltLengthInitializer {
EvpCtxSetSaltLengthInitializer() {
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_pss_saltlen"
}
override Expr getSaltLengthArg() { result = this.(Call).getArgument(1) }
override CtxPointerSource getContextArg() { result = this.(Call).getArgument(0) }
}

View File

@@ -1,6 +1,10 @@
private import experimental.quantum.Language
private import experimental.quantum.OpenSSL.CtxFlow
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
// Importing these intializers here to ensure the are part of any model that is
// using OpenSSLOperationBase. This futher ensures that initializers are tied to opeartions
// even if only importing the operation by itself.
import EVPPKeyCtxInitializer
/**
* A class for all OpenSSL operations.
@@ -44,6 +48,12 @@ abstract class EvpKeySizeInitializer extends EvpInitializer {
abstract Expr getKeySizeArg();
}
/**
* Unlike many initializers, this returns the key operation subtype immediately, not the arg.
* This is a design choice in the overall model, in that the model will not do any tracking
* for the subtype argument in any automated fashion. Users are currently expected to find the
* subtype argument manually and associate a type directly.
*/
abstract class EvpKeyOperationSubtypeInitializer extends EvpInitializer {
abstract Crypto::KeyOperationSubtype getKeyOperationSubtype();
}
@@ -66,6 +76,22 @@ abstract class EvpIVInitializer extends EvpInitializer {
abstract Expr getIVArg();
}
abstract class EvpPaddingInitializer extends EvpInitializer {
/**
* Gets the padding mode argument.
* e.g., `EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING)` argument 1 (0-based)
*/
abstract Expr getPaddingArg();
}
abstract class EvpSaltLengthInitializer extends EvpInitializer {
/**
* Gets the salt length argument.
* e.g., `EVP_PKEY_CTX_set_scrypt_salt_len(ctx, 16)` argument 1 (0-based)
*/
abstract Expr getSaltLengthArg();
}
/**
* A Call to an "update" function.
* These are not operations in the sense of Crypto::OperationInstance,

View File

@@ -4,3 +4,4 @@ import EVPHashOperation
import ECKeyGenOperation
import EVPSignatureOperation
import EVPKeyGenOperation
import EVPPKeyCtxInitializer