Files
codeql/cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll
REDMOND\brodes 63aaebbea6 .
2025-03-19 18:30:06 -04:00

496 lines
21 KiB
Plaintext

// import cpp
// import semmle.code.cpp.dataflow.new.DataFlow
// import LibraryDetector
// import OpenSSLKnownAlgorithmConstants
// import experimental.Quantum.Language
// class OpenSSLAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep {
// OpenSSLAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) }
// override DataFlow::Node getOutput() {
// exists(AlgorithmPassthroughCall c | c.getInNode() = this and c.getOutNode() = result)
// }
// }
// module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
// predicate isSource(DataFlow::Node source) {
// exists(OpenSSLAlgorithmGetterCall c | c.getResultNode() = source)
// }
// predicate isSink(DataFlow::Node sink) {
// exists(Crypto::AlgorithmConsumer c | c.getInputNode() = sink)
// }
// }
// module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsumerConfig>;
// abstract class AlgorithmPassthroughCall extends Call {
// abstract DataFlow::Node getInNode();
// abstract DataFlow::Node getOutNode();
// }
// class CopyAndDupAlgorithmPassthroughCall extends AlgorithmPassthroughCall {
// DataFlow::Node inNode;
// DataFlow::Node outNode;
// CopyAndDupAlgorithmPassthroughCall() {
// // Flow out through any return or other argument of the same type
// // Assume flow in and out is asIndirectExpr or asDefinitingArgument since a pointer is assumed
// // to be involved
// // NOTE: not attempting to detect openssl specific copy/dup functions, but anything suspected to be copy/dup
// this.getTarget().getName().toLowerCase().matches(["%_dup%", "%_copy%"]) and
// exists(Expr inArg, Type t |
// inArg = this.getAnArgument() and t = inArg.getUnspecifiedType().stripType()
// |
// inNode.asIndirectExpr() = inArg and
// (
// // Case 1: flow through another argument as an out arg of the same type
// exists(Expr outArg |
// outArg = this.getAnArgument() and
// outArg != inArg and
// outArg.getUnspecifiedType().stripType() = t
// |
// outNode.asDefiningArgument() = outArg
// )
// or
// // Case 2: flow through the return value if the result is the same as the intput type
// exists(Expr outArg | outArg = this and outArg.getUnspecifiedType().stripType() = t |
// outNode.asIndirectExpr() = outArg
// )
// )
// )
// }
// override DataFlow::Node getInNode() { result = inNode }
// override DataFlow::Node getOutNode() { result = outNode }
// }
// class NIDToPointerPassthroughCall extends AlgorithmPassthroughCall {
// DataFlow::Node inNode;
// DataFlow::Node outNode;
// NIDToPointerPassthroughCall() {
// this.getTarget().getName() in ["OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn"] and
// inNode.asExpr() = this.getArgument(0) and
// outNode.asExpr() = this
// //outNode.asIndirectExpr() = this
// }
// override DataFlow::Node getInNode() { result = inNode }
// override DataFlow::Node getOutNode() { result = outNode }
// }
// class PointerToPointerPassthroughCall extends AlgorithmPassthroughCall {
// DataFlow::Node inNode;
// DataFlow::Node outNode;
// PointerToPointerPassthroughCall() {
// this.getTarget().getName() = "OBJ_txt2obj" and
// inNode.asIndirectExpr() = this.getArgument(0) and
// outNode.asIndirectExpr() = this
// or
// //outNode.asExpr() = this
// this.getTarget().getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and
// inNode.asIndirectExpr() = this.getArgument(2) and
// outNode.asDefiningArgument() = this.getArgument(0)
// }
// override DataFlow::Node getInNode() { result = inNode }
// override DataFlow::Node getOutNode() { result = outNode }
// }
// class PointerToNIDPassthroughCall extends AlgorithmPassthroughCall {
// DataFlow::Node inNode;
// DataFlow::Node outNode;
// PointerToNIDPassthroughCall() {
// this.getTarget().getName() in ["OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid", "OBJ_txt2nid"] and
// (
// inNode.asIndirectExpr() = this.getArgument(0)
// or
// inNode.asExpr() = this.getArgument(0)
// ) and
// outNode.asExpr() = this
// }
// override DataFlow::Node getInNode() { result = inNode }
// override DataFlow::Node getOutNode() { result = outNode }
// }
// predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) {
// exists(AlgorithmPassthroughCall c | c.getInNode() = node1 and c.getOutNode() = node2)
// }
// abstract class OpenSSLAlgorithmGetterCall extends Call {
// abstract DataFlow::Node getValueArgNode();
// abstract DataFlow::Node getResultNode();
// abstract Expr getValueArgExpr();
// abstract Expr getResultExpr();
// }
// module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig {
// predicate isSource(DataFlow::Node source) {
// source.asExpr() instanceof KnownOpenSSLAlgorithmConstant
// }
// predicate isSink(DataFlow::Node sink) {
// exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink)
// }
// predicate isBarrier(DataFlow::Node node) {
// // False positive reducer, don't flow out through argv
// exists(VariableAccess va, Variable v |
// v.getAnAccess() = va and va = node.asExpr()
// or
// va = node.asIndirectExpr()
// |
// v.getName().matches("%argv")
// )
// }
// predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// knownPassThroughStep(node1, node2)
// }
// }
// module KnownOpenSSLAlgorithmToAlgorithmGetterFlow =
// DataFlow::Global<KnownOpenSSLAlgorithmToAlgorithmGetterConfig>;
// /**
// * Cases like EVP_MD5(),
// * there is no input, rather it directly gets an algorithm
// * and returns it.
// */
// class DirectGetterCall extends OpenSSLAlgorithmGetterCall {
// DataFlow::Node resultNode;
// Expr resultExpr;
// DirectGetterCall() {
// this instanceof KnownOpenSSLAlgorithmConstant and
// this instanceof Call and
// resultExpr = this and
// resultNode.asExpr() = resultExpr
// }
// override DataFlow::Node getValueArgNode() { none() }
// override DataFlow::Node getResultNode() { result = resultNode }
// override Expr getValueArgExpr() { none() }
// override Expr getResultExpr() { result = resultExpr }
// }
// // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
// class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall {
// DataFlow::Node valueArgNode;
// DataFlow::Node resultNode;
// Expr valueArgExpr;
// Expr resultExpr;
// EVPCipherGetterCall() {
// resultExpr = this and
// resultNode.asExpr() = this and
// isPossibleOpenSSLFunction(this.getTarget()) and
// (
// this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and
// valueArgExpr = this.getArgument(0) and
// valueArgNode.asExpr() = valueArgExpr
// or
// this.getTarget().getName() = "EVP_CIPHER_fetch" and
// valueArgExpr = this.getArgument(1) and
// valueArgNode.asExpr() = valueArgExpr
// or
// this.getTarget().getName() = "EVP_get_cipherbynid" and
// valueArgExpr = this.getArgument(0) and
// valueArgNode.asExpr() = valueArgExpr
// )
// }
// override DataFlow::Node getValueArgNode() { result = valueArgNode }
// override DataFlow::Node getResultNode() { result = resultNode }
// override Expr getValueArgExpr() { result = valueArgExpr }
// override Expr getResultExpr() { result = resultExpr }
// }
// class EVPAsymCipherGetterCall extends OpenSSLAlgorithmGetterCall {
// DataFlow::Node valueArgNode;
// DataFlow::Node resultNode;
// Expr valueArgExpr;
// Expr resultExpr;
// EVPAsymCipherGetterCall() {
// isPossibleOpenSSLFunction(this.getTarget()) and
// resultExpr = this and
// resultNode.asExpr() = this and
// this.getTarget().getName() = "EVP_ASYM_CIPHER_fetch" and
// valueArgExpr = this.getArgument(1) and
// valueArgNode.asExpr() = valueArgExpr
// }
// override DataFlow::Node getValueArgNode() { result = valueArgNode }
// override DataFlow::Node getResultNode() { result = resultNode }
// override Expr getValueArgExpr() { result = valueArgExpr }
// override Expr getResultExpr() { result = resultExpr }
// }
// class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall {
// DataFlow::Node valueArgNode;
// DataFlow::Node resultNode;
// Expr valueArgExpr;
// Expr resultExpr;
// EVPDigestGetterCall() {
// resultExpr = this and
// resultNode.asExpr() = this and
// isPossibleOpenSSLFunction(this.getTarget()) and
// (
// this.getTarget().getName() in [
// "EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid"
// ] and
// valueArgExpr = this.getArgument(0) and
// valueArgNode.asExpr() = valueArgExpr
// or
// this.getTarget().getName() = "EVP_MD_fetch" and
// valueArgExpr = this.getArgument(1) and
// valueArgNode.asExpr() = valueArgExpr
// )
// }
// override DataFlow::Node getValueArgNode() { result = valueArgNode }
// override DataFlow::Node getResultNode() { result = resultNode }
// override Expr getValueArgExpr() { result = valueArgExpr }
// override Expr getResultExpr() { result = resultExpr }
// }
// class EVPKDFFetch extends OpenSSLAlgorithmGetterCall {
// DataFlow::Node valueArgNode;
// DataFlow::Node resultNode;
// Expr valueArgExpr;
// Expr resultExpr;
// EVPKDFFetch() {
// resultExpr = this and
// resultNode.asExpr() = this and
// isPossibleOpenSSLFunction(this.getTarget()) and
// this.getTarget().getName() in ["EVP_KDF_fetch"] and
// valueArgExpr = this.getArgument(1) and
// valueArgNode.asExpr() = valueArgExpr
// }
// override DataFlow::Node getValueArgNode() { result = valueArgNode }
// override DataFlow::Node getResultNode() { result = resultNode }
// override Expr getValueArgExpr() { result = valueArgExpr }
// override Expr getResultExpr() { result = resultExpr }
// }
// // /**
// // * Predicates/classes for identifying algorithm sinks.
// // * An Algorithm Sink is a function that takes an algorithm as an argument.
// // * In particular, any function that takes in an algorithm that until the call
// // * the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm)
// // */
// // //TODO: enforce a hierarchy of AlgorithmSinkArgument, e.g., so I can get all Asymmetric SinkArguments that includes all the strictly RSA etc.
// // import cpp
// // // import experimental.cryptography.utils.OpenSSL.LibraryFunction
// // // import experimental.cryptography.CryptoAlgorithmNames
// // predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType }
// // abstract class AlgorithmSinkArgument extends Expr {
// // AlgorithmSinkArgument() {
// // exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget()))
// // }
// // /**
// // * Gets the function call in which the argument exists
// // */
// // Call getSinkCall() { result.getAnArgument() = this }
// // abstract string algType();
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
// // predicate cipherAlgorithmSink(string funcName, int argInd) {
// // funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0
// // or
// // funcName = "EVP_CIPHER_fetch" and argInd = 1
// // }
// // class CipherAlgorithmSink extends AlgorithmSinkArgument {
// // CipherAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // cipherAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getSymmetricEncryptionType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch
// // predicate macAlgorithmSink(string funcName, int argInd) {
// // (funcName = "EVP_MAC_fetch" and argInd = 1)
// // }
// // class MACAlgorithmSink extends AlgorithmSinkArgument {
// // MACAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // macAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = "TBD" }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch
// // predicate messageDigestAlgorithmSink(string funcName, int argInd) {
// // funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0
// // or
// // funcName = "EVP_MD_fetch" and argInd = 1
// // }
// // class MessageDigestAlgorithmSink extends AlgorithmSinkArgument {
// // MessageDigestAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // messageDigestAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getHashType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch
// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch
// // predicate keyExchangeAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_KEYEXCH_fetch" and argInd = 1
// // or
// // funcName = "EVP_KEM_fetch" and argInd = 1
// // }
// // class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument {
// // KeyExchangeAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // keyExchangeAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getKeyExchangeType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch
// // predicate keyManagementAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_KEYMGMT_fetch" and argInd = 1
// // }
// // class KeyManagementAlgorithmSink extends AlgorithmSinkArgument {
// // KeyManagementAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // keyManagementAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = "TBD" }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_KDF
// // predicate keyDerivationAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_KDF_fetch" and argInd = 1
// // }
// // class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument {
// // KeyDerivationAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // keyDerivationAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getKeyDerivationType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html
// // predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1
// // or
// // funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3
// // // NOTE: other cases are handled by AsymmetricAlgorithmSink
// // }
// // class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument {
// // AsymmetricCipherAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // asymmetricCipherAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" }
// // }
// // class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
// // AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() {
// // exists(Call c, string funcName |
// // funcName = c.getTarget().getName() and
// // this = c.getArgument(3)
// // |
// // funcName = "EVP_PKEY_Q_keygen" and
// // c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType
// // )
// // }
// // override string algType() { result = "ASYMMETRIC_ENCRYPTION" }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch
// // predicate randomAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_RAND_fetch" and argInd = 1
// // }
// // class RandomAlgorithmSink extends AlgorithmSinkArgument {
// // RandomAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // randomAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = "TBD" }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch
// // predicate signatureAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_SIGNATURE_fetch" and argInd = 1
// // }
// // class SignatureAlgorithmSink extends AlgorithmSinkArgument {
// // SignatureAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // signatureAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getSignatureType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html
// // predicate ellipticCurveAlgorithmSink(string funcName, int argInd) {
// // funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0
// // or
// // funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2
// // or
// // funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1
// // }
// // class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument {
// // EllipticCurveAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // ellipticCurveAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getEllipticCurveType() }
// // }
// // /**
// // * Special cased to address the fact that arg index 3 (zero offset based) is the curve name.
// // * ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve
// // */
// // class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
// // EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() {
// // exists(Call c, string funcName |
// // funcName = c.getTarget().getName() and
// // this = c.getArgument(3)
// // |
// // funcName = "EVP_PKEY_Q_keygen" and
// // c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and
// // c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType
// // )
// // }
// // override string algType() { result = getEllipticCurveType() }
// // }
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html
// // // https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html
// // // https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html
// // predicate asymmetricAlgorithmSink(string funcName, int argInd) {
// // funcName = "EVP_PKEY_CTX_new_id" and argInd = 0
// // or
// // funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1
// // or
// // funcName in [
// // "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key"
// // ] and
// // argInd = 0
// // or
// // funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1
// // or
// // // special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs
// // // funcName = "EVP_PKEY_Q_keygen" and argInd = 2
// // funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1
// // // TODO consider void cases EVP_PKEY_new
// // }
// // class AsymmetricAlgorithmSink extends AlgorithmSinkArgument {
// // AsymmetricAlgorithmSink() {
// // exists(Call c, string funcName, int argInd |
// // funcName = c.getTarget().getName() and this = c.getArgument(argInd)
// // |
// // asymmetricAlgorithmSink(funcName, argInd)
// // )
// // }
// // override string algType() { result = getAsymmetricType() }
// // }
// // class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
// // AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() {
// // exists(Call c, string funcName |
// // funcName = c.getTarget().getName() and
// // this = c.getArgument(2)
// // |
// // funcName = "EVP_PKEY_Q_keygen" and
// // not exists(c.getArgument(3))
// // )
// // }
// // override string algType() { result = getAsymmetricType() }
// // }