mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into redsun82/rust-extract-libs
This commit is contained in:
6
.github/workflows/build-ripunzip.yml
vendored
6
.github/workflows/build-ripunzip.yml
vendored
@@ -6,18 +6,18 @@ on:
|
||||
ripunzip-version:
|
||||
description: "what reference to checktout from google/runzip"
|
||||
required: false
|
||||
default: v1.2.1
|
||||
default: v2.0.2
|
||||
openssl-version:
|
||||
description: "what reference to checkout from openssl/openssl for Linux"
|
||||
required: false
|
||||
default: openssl-3.3.0
|
||||
default: openssl-3.5.0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-13, windows-2019]
|
||||
os: [ubuntu-22.04, macos-13, windows-2022]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
2
.github/workflows/csharp-qltest.yml
vendored
2
.github/workflows/csharp-qltest.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
unit-tests:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-2019]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/java/ql/test-kotlin2/ @github/codeql-kotlin
|
||||
|
||||
# Experimental CodeQL cryptography
|
||||
**/experimental/quantum/ @github/ps-codeql
|
||||
**/experimental/**/quantum/ @github/ps-codeql
|
||||
/shared/quantum/ @github/ps-codeql
|
||||
|
||||
# CodeQL tools and associated docs
|
||||
|
||||
@@ -71,7 +71,11 @@ class KnownOpenSSLBlockModeConstantAlgorithmInstance extends OpenSSLAlgorithmIns
|
||||
|
||||
// NOTE: I'm not going to attempt to parse out the mode specific part, so returning
|
||||
// the same as the raw name for now.
|
||||
override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
override string getRawModeAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
|
||||
}
|
||||
|
||||
@@ -102,7 +102,11 @@ class KnownOpenSSLCipherConstantAlgorithmInstance extends OpenSSLAlgorithmInstan
|
||||
// TODO or trace through getter ctx to set padding
|
||||
}
|
||||
|
||||
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
override string getRawAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override int getKeySizeFixed() {
|
||||
this.(KnownOpenSSLCipherAlgorithmConstant).getExplicitKeySize() = result
|
||||
|
||||
@@ -32,7 +32,11 @@ class KnownOpenSSLEllipticCurveConstantAlgorithmInstance extends OpenSSLAlgorith
|
||||
|
||||
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
|
||||
|
||||
override string getRawEllipticCurveName() { result = this.(Literal).getValue().toString() }
|
||||
override string getRawEllipticCurveName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override Crypto::TEllipticCurveType getEllipticCurveType() {
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getParsedEllipticCurveName(), _, result)
|
||||
|
||||
@@ -76,7 +76,11 @@ class KnownOpenSSLHashConstantAlgorithmInstance extends OpenSSLAlgorithmInstance
|
||||
not knownOpenSSLConstantToHashFamilyType(this, _) and result = Crypto::OtherHashType()
|
||||
}
|
||||
|
||||
override string getRawHashAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
override string getRawHashAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override int getFixedDigestLength() {
|
||||
this.(KnownOpenSSLHashAlgorithmConstant).getExplicitDigestLength() = result
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import KnownAlgorithmConstants
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
|
||||
private import AlgToAVCFlow
|
||||
|
||||
predicate knownOpenSSLConstantToKeyAgreementFamilyType(
|
||||
KnownOpenSSLKeyAgreementAlgorithmConstant e, Crypto::TKeyAgreementType type
|
||||
) {
|
||||
exists(string name |
|
||||
name = e.getNormalizedName() and
|
||||
(
|
||||
name = "ECDH" and type = Crypto::ECDH()
|
||||
or
|
||||
name = "DH" and type = Crypto::DH()
|
||||
or
|
||||
name = "EDH" and type = Crypto::EDH()
|
||||
or
|
||||
name = "ESDH" and type = Crypto::EDH()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class KnownOpenSSLHashConstantAlgorithmInstance extends OpenSSLAlgorithmInstance,
|
||||
Crypto::KeyAgreementAlgorithmInstance instanceof KnownOpenSSLKeyAgreementAlgorithmConstant
|
||||
{
|
||||
OpenSSLAlgorithmValueConsumer getterCall;
|
||||
|
||||
KnownOpenSSLHashConstantAlgorithmInstance() {
|
||||
// Two possibilities:
|
||||
// 1) The source is a literal and flows to a getter, then we know we have an instance
|
||||
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
|
||||
// Possibility 1:
|
||||
this instanceof Literal and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink |
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// This traces to a getter
|
||||
KnownOpenSSLAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
or
|
||||
// Possibility 2:
|
||||
this instanceof DirectAlgorithmValueConsumer and getterCall = this
|
||||
}
|
||||
|
||||
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
|
||||
|
||||
override Crypto::TKeyAgreementType getKeyAgreementType() {
|
||||
knownOpenSSLConstantToKeyAgreementFamilyType(this, result)
|
||||
or
|
||||
not knownOpenSSLConstantToKeyAgreementFamilyType(this, _) and
|
||||
result = Crypto::OtherKeyAgreementType()
|
||||
}
|
||||
|
||||
override string getRawKeyAgreementAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,10 @@ class KnownOpenSSLSignatureAlgorithmConstant extends KnownOpenSSLAlgorithmConsta
|
||||
KnownOpenSSLSignatureAlgorithmConstant() { resolveAlgorithmFromExpr(this, _, "SIGNATURE") }
|
||||
}
|
||||
|
||||
class KnownOpenSSLKeyAgreementAlgorithmConstant extends KnownOpenSSLAlgorithmConstant {
|
||||
KnownOpenSSLKeyAgreementAlgorithmConstant() { resolveAlgorithmFromExpr(this, _, "KEY_AGREEMENT") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a call to a 'direct algorithm getter', e.g., EVP_MD5()
|
||||
* This approach to fetching algorithms was used in OpenSSL 1.0.2.
|
||||
@@ -141,6 +145,14 @@ predicate customAliases(string target, string alias) {
|
||||
* The `target` and `alias` are converted to lowercase to be of a standard form.
|
||||
*/
|
||||
predicate defaultAliases(string target, string alias) {
|
||||
// "DH" and "DHX" are not aliases in the traditional sense,
|
||||
// i.e., they are not registered as aliases explicitly,
|
||||
// rather they appear in common usage, and experiments reveal their
|
||||
// NID matches those of the `dhKeyAgreement` and `x9.42 dh` algorithms respectively.
|
||||
alias = "dh" and target = "dhKeyAgreement"
|
||||
or
|
||||
alias = "dhx" and target = "x9.42 dh"
|
||||
or
|
||||
alias = "aes128" and target = "aes-128-cbc"
|
||||
or
|
||||
alias = "aes192" and target = "aes-192-cbc"
|
||||
@@ -236,6 +248,10 @@ predicate defaultAliases(string target, string alias) {
|
||||
* `algType` is the type of algorithm (e.g., "SYMMETRIC_ENCRYPTION")
|
||||
*/
|
||||
predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized, string algType) {
|
||||
name = "dhKeyAgreement" and nid = 28 and normalized = "DH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "x9.42 dh" and nid = 29 and normalized = "DH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "rsa" and nid = 19 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "prime192v1" and nid = 409 and normalized = "PRIME192V1" and algType = "ELLIPTIC_CURVE"
|
||||
@@ -868,6 +884,8 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
or
|
||||
name = "id-alg-dh-sig-hmac-sha1" and nid = 325 and normalized = "SHA1" and algType = "HASH"
|
||||
or
|
||||
name = "id-alg-dh-sig-hmac-sha1" and nid = 325 and normalized = "DH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "aes-128-ofb" and nid = 420 and normalized = "AES-128" and algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "aes-128-ofb" and nid = 420 and normalized = "OFB" and algType = "BLOCK_MODE"
|
||||
@@ -1369,9 +1387,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
or
|
||||
name = "kx-rsa" and nid = 1037 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "kx-ecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_EXCHANGE"
|
||||
name = "kx-ecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "kx-ecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_EXCHANGE"
|
||||
name = "kx-ecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "kx-rsa-psk" and nid = 1042 and normalized = "RSA" and algType = "ASYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
@@ -1679,11 +1697,11 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
or
|
||||
name = "x448" and nid = 1035 and normalized = "X448" and algType = "ELLIPTIC_CURVE"
|
||||
or
|
||||
name = "x448" and nid = 1035 and normalized = "X448" and algType = "KEY_EXCHANGE"
|
||||
name = "x448" and nid = 1035 and normalized = "X448" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "x25519" and nid = 1034 and normalized = "X25519" and algType = "ELLIPTIC_CURVE"
|
||||
or
|
||||
name = "x25519" and nid = 1034 and normalized = "X25519" and algType = "KEY_EXCHANGE"
|
||||
name = "x25519" and nid = 1034 and normalized = "X25519" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "authecdsa" and nid = 1047 and normalized = "ECDSA" and algType = "SIGNATURE"
|
||||
or
|
||||
@@ -1783,51 +1801,101 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "SHA1" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha1kdf-scheme" and
|
||||
nid = 941 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha224kdf-scheme" and
|
||||
nid = 942 and
|
||||
normalized = "SHA-224" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha224kdf-scheme" and
|
||||
nid = 942 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha256kdf-scheme" and
|
||||
nid = 943 and
|
||||
normalized = "SHA-256" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha256kdf-scheme" and
|
||||
nid = 943 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha384kdf-scheme" and
|
||||
nid = 944 and
|
||||
normalized = "SHA-384" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha384kdf-scheme" and
|
||||
nid = 944 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha512kdf-scheme" and
|
||||
nid = 945 and
|
||||
normalized = "SHA-512" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-cofactordh-sha512kdf-scheme" and
|
||||
nid = 945 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha1kdf-scheme" and
|
||||
nid = 936 and
|
||||
normalized = "SHA1" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha1kdf-scheme" and
|
||||
nid = 936 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha224kdf-scheme" and
|
||||
nid = 937 and
|
||||
normalized = "SHA-224" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha224kdf-scheme" and
|
||||
nid = 937 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha256kdf-scheme" and
|
||||
nid = 938 and
|
||||
normalized = "SHA-256" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha256kdf-scheme" and
|
||||
nid = 938 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha384kdf-scheme" and
|
||||
nid = 939 and
|
||||
normalized = "SHA-384" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha384kdf-scheme" and
|
||||
nid = 939 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha512kdf-scheme" and
|
||||
nid = 940 and
|
||||
normalized = "SHA-512" and
|
||||
algType = "HASH"
|
||||
or
|
||||
name = "dhsinglepass-stddh-sha512kdf-scheme" and
|
||||
nid = 940 and
|
||||
normalized = "DH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "dsa-old" and nid = 67 and normalized = "DSA" and algType = "SIGNATURE"
|
||||
or
|
||||
name = "dsa-sha" and nid = 66 and normalized = "DSA" and algType = "SIGNATURE"
|
||||
@@ -1987,7 +2055,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "GOST" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "gost r 34.10-2001 dh" and
|
||||
name = "gost r 34.10-2001 dh" and // TODO: review this algorithm
|
||||
nid = 817 and
|
||||
normalized = "GOST" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
@@ -2057,7 +2125,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "GOST" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "gost r 34.10-94 dh" and
|
||||
name = "gost r 34.10-94 dh" and // TODO: review this algorithm
|
||||
nid = 818 and
|
||||
normalized = "GOST" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
@@ -2272,7 +2340,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "GOSTR34102001" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "id-gostr3410-2001dh" and
|
||||
name = "id-gostr3410-2001dh" and // TODO: review this algorithm
|
||||
nid = 817 and
|
||||
normalized = "GOSTR34102001" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
@@ -2337,7 +2405,7 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "GOSTR341094" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "id-gostr3410-94dh" and
|
||||
name = "id-gostr3410-94dh" and // TODO: review this algorithm
|
||||
nid = 818 and
|
||||
normalized = "GOSTR341094" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
@@ -2421,16 +2489,31 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "3DES" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "id-smime-alg-esdhwith3des" and
|
||||
nid = 241 and
|
||||
normalized = "ESDH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "id-smime-alg-esdhwithrc2" and
|
||||
nid = 242 and
|
||||
normalized = "RC2" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "id-smime-alg-esdhwithrc2" and
|
||||
nid = 242 and
|
||||
normalized = "ESDH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "id-smime-alg-rc2wrap" and
|
||||
nid = 244 and
|
||||
normalized = "RC2" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "id_smime_alg_esdh" and
|
||||
nid = 245 and
|
||||
normalized = "ESDH" and
|
||||
algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "id-tc26-gost-28147-param-z" and
|
||||
nid = 1003 and
|
||||
normalized = "GOST28147" and
|
||||
@@ -2476,9 +2559,9 @@ predicate knownOpenSSLAlgorithmLiteral(string name, int nid, string normalized,
|
||||
normalized = "GOST34102012" and
|
||||
algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
name = "kxecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_EXCHANGE"
|
||||
name = "kxecdhe" and nid = 1038 and normalized = "ECDH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "kxecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_EXCHANGE"
|
||||
name = "kxecdhe-psk" and nid = 1040 and normalized = "ECDH" and algType = "KEY_AGREEMENT"
|
||||
or
|
||||
name = "kxgost" and nid = 1045 and normalized = "GOST" and algType = "SYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
|
||||
@@ -90,7 +90,11 @@ class KnownOpenSSLPaddingConstantAlgorithmInstance extends OpenSSLAlgorithmInsta
|
||||
isPaddingSpecificConsumer = true
|
||||
}
|
||||
|
||||
override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
override string getRawPaddingAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override OpenSSLAlgorithmValueConsumer getAVC() { result = getterCall }
|
||||
|
||||
|
||||
@@ -3,18 +3,14 @@ private import experimental.quantum.Language
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
|
||||
private import experimental.quantum.OpenSSL.LibraryDetector
|
||||
|
||||
abstract class HashAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
|
||||
|
||||
/**
|
||||
* EVP_Q_Digest directly consumes algorithm constant values
|
||||
*/
|
||||
class EVP_Q_Digest_Algorithm_Consumer extends OpenSSLAlgorithmValueConsumer {
|
||||
EVP_Q_Digest_Algorithm_Consumer() {
|
||||
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
|
||||
this.(Call).getTarget().getName() = "EVP_Q_digest"
|
||||
}
|
||||
class EVP_Q_Digest_Algorithm_Consumer extends HashAlgorithmValueConsumer {
|
||||
EVP_Q_Digest_Algorithm_Consumer() { this.(Call).getTarget().getName() = "EVP_Q_digest" }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputNode() {
|
||||
result.asExpr() = this.(Call).getArgument(1)
|
||||
@@ -35,13 +31,12 @@ class EVP_Q_Digest_Algorithm_Consumer extends OpenSSLAlgorithmValueConsumer {
|
||||
* The EVP digest algorithm getters
|
||||
* https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
|
||||
*/
|
||||
class EVPDigestAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer {
|
||||
class EVPDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
|
||||
DataFlow::Node valueArgNode;
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EVPDigestAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
isPossibleOpenSSLFunction(this.(Call).getTarget()) and
|
||||
(
|
||||
this.(Call).getTarget().getName() in [
|
||||
"EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
|
||||
|
||||
abstract class KEMAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
|
||||
|
||||
class EVPKEMAlgorithmValueConsumer extends KEMAlgorithmValueConsumer {
|
||||
DataFlow::Node valueArgNode;
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EVPKEMAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() = "EVP_KEM_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getResultNode() { result = resultNode }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
|
||||
|
||||
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
|
||||
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
|
||||
|
||||
abstract class KeyExchangeAlgorithmValueConsumer extends OpenSSLAlgorithmValueConsumer { }
|
||||
|
||||
class EVPKeyExchangeAlgorithmValueConsumer extends KeyExchangeAlgorithmValueConsumer {
|
||||
DataFlow::Node valueArgNode;
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EVPKeyExchangeAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() = "EVP_KEYEXCH_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getResultNode() { result = resultNode }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
|
||||
|
||||
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
|
||||
exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i)
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,19 @@ import semmle.code.cpp.dataflow.new.DataFlow
|
||||
* - EVP_PKEY_CTX
|
||||
*/
|
||||
private class CtxType extends Type {
|
||||
CtxType() { this.getUnspecifiedType().stripType().getName().matches("evp_%ctx_%st") }
|
||||
CtxType() {
|
||||
// It is possible for users to use the underlying type of the CTX variables
|
||||
// these have a name matching 'evp_%ctx_%st
|
||||
this.getUnspecifiedType().stripType().getName().matches("evp_%ctx_%st")
|
||||
or
|
||||
// In principal the above check should be sufficient, but in case of build mode none issues
|
||||
// i.e., if a typedef cannot be resolved,
|
||||
// or issues with properly stubbing test cases, we also explicitly check for the wrapping type defs
|
||||
// i.e., patterns matching 'EVP_%_CTX'
|
||||
exists(Type base | base = this or base = this.(DerivedType).getBaseType() |
|
||||
base.getName().matches("EVP_%_CTX")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@ private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(EVP_Cipher_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr())
|
||||
exists(EVP_Cipher_Operation c | c.getAlgorithmArg() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ private module AlgGetterToAlgConsumerFlow = DataFlow::Global<AlgGetterToAlgConsu
|
||||
abstract class EVP_Cipher_Operation extends OpenSSLOperation, Crypto::KeyOperationInstance {
|
||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
||||
|
||||
Expr getAlgorithmArg() { this.getInitCall().getAlgorithmArg() = result }
|
||||
|
||||
override Expr getOutputArg() { result = this.(Call).getArgument(1) }
|
||||
|
||||
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||
|
||||
@@ -12,6 +12,8 @@ private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgor
|
||||
abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperationInstance {
|
||||
Expr getContextArg() { result = this.(Call).getArgument(0) }
|
||||
|
||||
Expr getAlgorithmArg() { result = this.getInitCall().getAlgorithmArg() }
|
||||
|
||||
EVP_Hash_Initializer getInitCall() {
|
||||
CTXFlow::ctxArgFlowsToCtxArg(result.getContextArg(), this.getContextArg())
|
||||
}
|
||||
@@ -23,7 +25,7 @@ abstract class EVP_Hash_Operation extends OpenSSLOperation, Crypto::HashOperatio
|
||||
*/
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
||||
DataFlow::exprNode(this.getInitCall().getAlgorithmArg()))
|
||||
DataFlow::exprNode(this.getAlgorithmArg()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ private module AlgGetterToAlgConsumerConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(EVP_Hash_Operation c | c.getInitCall().getAlgorithmArg() = sink.asExpr())
|
||||
exists(EVP_Hash_Operation c | c.getAlgorithmArg() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +66,8 @@ class EVP_Q_Digest_Operation extends EVP_Hash_Operation {
|
||||
// simply return 'this', see modeled hash algorithm consuers for EVP_Q_Digest
|
||||
this = result
|
||||
}
|
||||
|
||||
override Expr getAlgorithmArg() { result = this.(Call).getArgument(1) }
|
||||
}
|
||||
|
||||
class EVP_Digest_Operation extends EVP_Hash_Operation {
|
||||
@@ -72,17 +76,14 @@ class EVP_Digest_Operation extends EVP_Hash_Operation {
|
||||
// There is no context argument for this function
|
||||
override Expr getContextArg() { none() }
|
||||
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
AlgGetterToAlgConsumerFlow::flow(result.(OpenSSLAlgorithmValueConsumer).getResultNode(),
|
||||
DataFlow::exprNode(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) }
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:179:43:179:76 | Constant |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:179:43:179:76 | Constant |
|
||||
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::CipherOperationNode op, Crypto::KeyArtifactNode k
|
||||
where op.getAKey() = k
|
||||
select op, k, k.getSourceNode()
|
||||
@@ -0,0 +1,2 @@
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:180:42:180:59 | Constant |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:180:42:180:59 | Constant |
|
||||
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::CipherOperationNode op, Crypto::NonceArtifactNode n
|
||||
where op.getANonce() = n
|
||||
select op, n, n.getSourceNode()
|
||||
@@ -0,0 +1,8 @@
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:23:62:23:65 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:23:68:23:71 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:40:13:40:31 | KeyOperationOutput | openssl_basic.c:31:49:31:51 | Key | openssl_basic.c:31:54:31:55 | Nonce | openssl_basic.c:23:37:23:51 | KeyOperationAlgorithm | Encrypt |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:69:58:69:61 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:69:64:69:67 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||
| openssl_basic.c:90:11:90:29 | DecryptOperation | openssl_basic.c:81:49:81:58 | Message | openssl_basic.c:90:11:90:29 | KeyOperationOutput | openssl_basic.c:77:45:77:47 | Key | openssl_basic.c:77:50:77:51 | Nonce | openssl_basic.c:69:33:69:47 | KeyOperationAlgorithm | Decrypt |
|
||||
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::CipherOperationNode n
|
||||
select n, n.getAnInputArtifact(), n.getAnOutputArtifact(), n.getAKey(), n.getANonce(),
|
||||
n.getAnAlgorithmOrGenericSource(), n.getKeyOperationSubtype()
|
||||
@@ -0,0 +1 @@
|
||||
| openssl_basic.c:40:13:40:31 | EncryptOperation | openssl_basic.c:35:54:35:62 | Message | openssl_basic.c:181:49:181:87 | Constant |
|
||||
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::CipherOperationNode n, Crypto::MessageArtifactNode m
|
||||
where n.getAnInputArtifact() = m
|
||||
select n, m, m.getSourceNode()
|
||||
@@ -0,0 +1,2 @@
|
||||
| openssl_basic.c:124:13:124:30 | HashOperation | openssl_basic.c:120:37:120:43 | Message | openssl_basic.c:181:49:181:87 | Constant |
|
||||
| openssl_basic.c:144:13:144:22 | HashOperation | openssl_basic.c:144:24:144:30 | Message | openssl_basic.c:181:49:181:87 | Constant |
|
||||
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::HashOperationNode n, Crypto::MessageArtifactNode m
|
||||
where n.getInputArtifact() = m
|
||||
select n, m, m.getSourceNode()
|
||||
@@ -0,0 +1,2 @@
|
||||
| openssl_basic.c:124:13:124:30 | HashOperation | openssl_basic.c:124:13:124:30 | Digest | openssl_basic.c:116:38:116:47 | HashAlgorithm | openssl_basic.c:120:37:120:43 | Message |
|
||||
| openssl_basic.c:144:13:144:22 | HashOperation | openssl_basic.c:144:13:144:22 | Digest | openssl_basic.c:144:67:144:73 | HashAlgorithm | openssl_basic.c:144:24:144:30 | Message |
|
||||
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
import experimental.quantum.Language
|
||||
|
||||
from Crypto::HashOperationNode n
|
||||
select n, n.getDigest(), n.getAnAlgorithmOrGenericSource(), n.getInputArtifact()
|
||||
@@ -0,0 +1,221 @@
|
||||
#include "openssl/evp_stubs.h"
|
||||
#include "openssl/alg_macro_stubs.h"
|
||||
#include "openssl/rand_stubs.h"
|
||||
|
||||
size_t strlen(const char* str);
|
||||
|
||||
// Sample OpenSSL code that demonstrates various cryptographic operations
|
||||
// that can be detected by the quantum model
|
||||
|
||||
// Function to perform AES-256-GCM encryption
|
||||
int encrypt_aes_gcm(const unsigned char *plaintext, int plaintext_len,
|
||||
const unsigned char *key, const unsigned char *iv, int iv_len,
|
||||
unsigned char *ciphertext, unsigned char *tag) {
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int ciphertext_len;
|
||||
|
||||
// Create and initialize the context
|
||||
if(!(ctx = EVP_CIPHER_CTX_new()))
|
||||
return -1;
|
||||
|
||||
// Initialize the encryption operation
|
||||
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
|
||||
return -1;
|
||||
|
||||
// Set IV length (for GCM mode)
|
||||
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
|
||||
return -1;
|
||||
|
||||
// Initialize key and IV
|
||||
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
|
||||
return -1;
|
||||
|
||||
// Provide the plaintext to be encrypted
|
||||
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
|
||||
return -1;
|
||||
ciphertext_len = len;
|
||||
|
||||
// Finalize the encryption
|
||||
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
|
||||
return -1;
|
||||
ciphertext_len += len;
|
||||
|
||||
// Get the tag
|
||||
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
|
||||
return -1;
|
||||
|
||||
// Clean up
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return ciphertext_len;
|
||||
}
|
||||
|
||||
// Function to perform AES-256-GCM decryption
|
||||
int decrypt_aes_gcm(const unsigned char *ciphertext, int ciphertext_len,
|
||||
const unsigned char *tag, const unsigned char *key,
|
||||
const unsigned char *iv, int iv_len,
|
||||
unsigned char *plaintext) {
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int plaintext_len;
|
||||
int ret;
|
||||
|
||||
// Create and initialize the context
|
||||
if(!(ctx = EVP_CIPHER_CTX_new()))
|
||||
return -1;
|
||||
|
||||
// Initialize the decryption operation
|
||||
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
|
||||
return -1;
|
||||
|
||||
// Set IV length
|
||||
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
|
||||
return -1;
|
||||
|
||||
// Initialize key and IV
|
||||
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
|
||||
return -1;
|
||||
|
||||
// Provide the ciphertext to be decrypted
|
||||
if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
|
||||
return -1;
|
||||
plaintext_len = len;
|
||||
|
||||
// Set expected tag value
|
||||
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void*)tag))
|
||||
return -1;
|
||||
|
||||
// Finalize the decryption
|
||||
ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
|
||||
|
||||
// Clean up
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
if(ret > 0) {
|
||||
// Success
|
||||
plaintext_len += len;
|
||||
return plaintext_len;
|
||||
} else {
|
||||
// Verification failed
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to calculate SHA-256 hash
|
||||
int calculate_sha256(const unsigned char *message, size_t message_len,
|
||||
unsigned char *digest) {
|
||||
EVP_MD_CTX *mdctx;
|
||||
unsigned int digest_len;
|
||||
|
||||
// Create and initialize the context
|
||||
if(!(mdctx = EVP_MD_CTX_new()))
|
||||
return 0;
|
||||
|
||||
// Initialize the hash operation
|
||||
if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL))
|
||||
return 0;
|
||||
|
||||
// Provide the message to be hashed
|
||||
if(1 != EVP_DigestUpdate(mdctx, message, message_len))
|
||||
return 0;
|
||||
|
||||
// Finalize the hash
|
||||
if(1 != EVP_DigestFinal_ex(mdctx, digest, &digest_len))
|
||||
return 0;
|
||||
|
||||
// Clean up
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Function to generate random bytes
|
||||
int generate_random_bytes(unsigned char *buffer, size_t length) {
|
||||
return RAND_bytes(buffer, length);
|
||||
}
|
||||
|
||||
// Function using direct EVP_Digest function (one-shot hash)
|
||||
int calculate_md5_oneshot(const unsigned char *message, size_t message_len,
|
||||
unsigned char *digest) {
|
||||
unsigned int digest_len;
|
||||
|
||||
// Calculate MD5 in a single call
|
||||
if(1 != EVP_Digest(message, message_len, digest, &digest_len, EVP_md5(), NULL))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Function using HMAC
|
||||
int calculate_hmac_sha256(const unsigned char *key, size_t key_len,
|
||||
const unsigned char *message, size_t message_len,
|
||||
unsigned char *mac) {
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
EVP_PKEY *pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len);
|
||||
|
||||
if (!ctx || !pkey)
|
||||
return 0;
|
||||
|
||||
if (EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, pkey) != 1)
|
||||
return 0;
|
||||
|
||||
if (EVP_DigestSignUpdate(ctx, message, message_len) != 1)
|
||||
return 0;
|
||||
|
||||
size_t mac_len = 32; // SHA-256 output size
|
||||
if (EVP_DigestSignFinal(ctx, mac, &mac_len) != 1)
|
||||
return 0;
|
||||
|
||||
EVP_MD_CTX_free(ctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test function
|
||||
int test_main() {
|
||||
// Test encryption and decryption
|
||||
unsigned char *key = (unsigned char *)"01234567890123456789012345678901"; // 32 bytes
|
||||
unsigned char *iv = (unsigned char *)"0123456789012345"; // 16 bytes
|
||||
unsigned char *plaintext = (unsigned char *)"This is a test message for encryption";
|
||||
unsigned char ciphertext[1024];
|
||||
unsigned char tag[16];
|
||||
unsigned char decrypted[1024];
|
||||
int plaintext_len = strlen((char *)plaintext);
|
||||
int ciphertext_len;
|
||||
int decrypted_len;
|
||||
|
||||
// Test SHA-256 hash
|
||||
unsigned char hash[32];
|
||||
|
||||
// Test random generation
|
||||
unsigned char random_bytes[32];
|
||||
|
||||
// // Initialize OpenSSL
|
||||
// ERR_load_crypto_strings();
|
||||
|
||||
// Encrypt data
|
||||
ciphertext_len = encrypt_aes_gcm(plaintext, plaintext_len, key, iv, 16, ciphertext, tag);
|
||||
|
||||
// Decrypt data
|
||||
decrypted_len = decrypt_aes_gcm(ciphertext, ciphertext_len, tag, key, iv, 16, decrypted);
|
||||
|
||||
//printf("decrypted: %s\n", decrypted);
|
||||
|
||||
// Calculate hash
|
||||
calculate_sha256(plaintext, plaintext_len, hash);
|
||||
|
||||
// Generate random bytes
|
||||
generate_random_bytes(random_bytes, 32);
|
||||
|
||||
// Calculate one-shot MD5
|
||||
unsigned char md5_hash[16];
|
||||
calculate_md5_oneshot(plaintext, plaintext_len, md5_hash);
|
||||
|
||||
// Calculate HMAC
|
||||
unsigned char hmac[32];
|
||||
calculate_hmac_sha256(key, 32, plaintext, plaintext_len, hmac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: -I ../../../stubs
|
||||
4
cpp/ql/test/experimental/stubs/README.md
Normal file
4
cpp/ql/test/experimental/stubs/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
The stubs in this directory are derived from various open-source projects, and
|
||||
used to test that the relevant APIs are correctly modelled. Where a disclaimer
|
||||
or third-party-notice is required, this is included in the top-level directory
|
||||
for each particular library.
|
||||
3741
cpp/ql/test/experimental/stubs/openssl/alg_macro_stubs.h
Normal file
3741
cpp/ql/test/experimental/stubs/openssl/alg_macro_stubs.h
Normal file
File diff suppressed because it is too large
Load Diff
4986
cpp/ql/test/experimental/stubs/openssl/evp_stubs.h
Normal file
4986
cpp/ql/test/experimental/stubs/openssl/evp_stubs.h
Normal file
File diff suppressed because it is too large
Load Diff
177
cpp/ql/test/experimental/stubs/openssl/license.txt
Normal file
177
cpp/ql/test/experimental/stubs/openssl/license.txt
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
3
cpp/ql/test/experimental/stubs/openssl/rand_stubs.h
Normal file
3
cpp/ql/test/experimental/stubs/openssl/rand_stubs.h
Normal file
@@ -0,0 +1,3 @@
|
||||
int RAND_bytes(unsigned char *buf, int num);
|
||||
|
||||
int RAND_pseudo_bytes(unsigned char *buf, int num);
|
||||
@@ -113,7 +113,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
"buildless/mode-active",
|
||||
"C# was extracted with build-mode set to 'none'",
|
||||
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
|
||||
markdownMessage: "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
markdownMessage: "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
severity: DiagnosticMessage.TspSeverity.Note
|
||||
));
|
||||
|
||||
|
||||
@@ -127,13 +127,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
public IList<string> GetNugetFeeds(string nugetConfig)
|
||||
{
|
||||
logger.LogInfo($"Getting Nuget feeds from '{nugetConfig}'...");
|
||||
logger.LogInfo($"Getting NuGet feeds from '{nugetConfig}'...");
|
||||
return GetResultList($"{nugetListSourceCommand} --configfile \"{nugetConfig}\"");
|
||||
}
|
||||
|
||||
public IList<string> GetNugetFeedsFromFolder(string folderPath)
|
||||
{
|
||||
logger.LogInfo($"Getting Nuget feeds in folder '{folderPath}'...");
|
||||
logger.LogInfo($"Getting NuGet feeds in folder '{folderPath}'...");
|
||||
return GetResultList(nugetListSourceCommand, folderPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
internal const string NugetFeedResponsivenessRequestCountForFallback = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_FALLBACK_LIMIT";
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the NuGet feeds to use for fallback Nuget dependency fetching. The value is a space-separated list of feed URLs.
|
||||
/// Specifies the NuGet feeds to use for fallback NuGet dependency fetching. The value is a space-separated list of feed URLs.
|
||||
/// The default value is `https://api.nuget.org/v3/index.json`.
|
||||
/// </summary>
|
||||
public const string FallbackNugetFeeds = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_FALLBACK";
|
||||
|
||||
@@ -135,16 +135,16 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
if (nugetPackageDllPaths.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Restored {nugetPackageDllPaths.Count} Nuget DLLs.");
|
||||
logger.LogInfo($"Restored {nugetPackageDllPaths.Count} NuGet DLLs.");
|
||||
}
|
||||
if (excludedPaths.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Excluding {excludedPaths.Count} Nuget DLLs.");
|
||||
logger.LogInfo($"Excluding {excludedPaths.Count} NuGet DLLs.");
|
||||
}
|
||||
|
||||
foreach (var excludedPath in excludedPaths)
|
||||
{
|
||||
logger.LogInfo($"Excluded Nuget DLL: {excludedPath}");
|
||||
logger.LogInfo($"Excluded NuGet DLL: {excludedPath}");
|
||||
}
|
||||
|
||||
nugetPackageDllPaths.ExceptWith(excludedPaths);
|
||||
@@ -152,7 +152,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
logger.LogError($"Failed to restore Nuget packages with nuget.exe: {exc.Message}");
|
||||
logger.LogError($"Failed to restore NuGet packages with nuget.exe: {exc.Message}");
|
||||
}
|
||||
|
||||
var restoredProjects = RestoreSolutions(out var container);
|
||||
@@ -186,7 +186,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
if (fallbackFeeds.Count == 0)
|
||||
{
|
||||
fallbackFeeds.Add(PublicNugetOrgFeed);
|
||||
logger.LogInfo($"No fallback Nuget feeds specified. Adding default feed: {PublicNugetOrgFeed}");
|
||||
logger.LogInfo($"No fallback NuGet feeds specified. Adding default feed: {PublicNugetOrgFeed}");
|
||||
|
||||
var shouldAddNugetConfigFeeds = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.AddNugetConfigFeedsToFallback);
|
||||
logger.LogInfo($"Adding feeds from nuget.config to fallback restore: {shouldAddNugetConfigFeeds}");
|
||||
@@ -196,23 +196,23 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
// There are some feeds in `feedsFromNugetConfigs` that have already been checked for reachability, we could skip those.
|
||||
// But we might use different responsiveness testing settings when we try them in the fallback logic, so checking them again is safer.
|
||||
fallbackFeeds.UnionWith(feedsFromNugetConfigs);
|
||||
logger.LogInfo($"Using Nuget feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Using NuGet feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
|
||||
}
|
||||
}
|
||||
|
||||
logger.LogInfo($"Checking fallback Nuget feed reachability on feeds: {string.Join(", ", fallbackFeeds.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Checking fallback NuGet feed reachability on feeds: {string.Join(", ", fallbackFeeds.OrderBy(f => f))}");
|
||||
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: true);
|
||||
var reachableFallbackFeeds = fallbackFeeds.Where(feed => IsFeedReachable(feed, initialTimeout, tryCount, allowExceptions: false)).ToList();
|
||||
if (reachableFallbackFeeds.Count == 0)
|
||||
{
|
||||
logger.LogWarning("No fallback Nuget feeds are reachable.");
|
||||
logger.LogWarning("No fallback NuGet feeds are reachable.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInfo($"Reachable fallback Nuget feeds: {string.Join(", ", reachableFallbackFeeds.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Reachable fallback NuGet feeds: {string.Join(", ", reachableFallbackFeeds.OrderBy(f => f))}");
|
||||
}
|
||||
|
||||
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback Nuget feed count", reachableFallbackFeeds.Count.ToString()));
|
||||
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback NuGet feed count", reachableFallbackFeeds.Count.ToString()));
|
||||
|
||||
return reachableFallbackFeeds;
|
||||
}
|
||||
@@ -331,7 +331,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return DownloadMissingPackages(usedPackageNames, fallbackNugetFeeds: reachableFallbackFeeds);
|
||||
}
|
||||
|
||||
logger.LogWarning("Skipping download of missing packages from specific feeds as no fallback Nuget feeds are reachable.");
|
||||
logger.LogWarning("Skipping download of missing packages from specific feeds as no fallback NuGet feeds are reachable.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -624,7 +624,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, bool allowExceptions = true)
|
||||
{
|
||||
logger.LogInfo($"Checking if Nuget feed '{feed}' is reachable...");
|
||||
logger.LogInfo($"Checking if NuGet feed '{feed}' is reachable...");
|
||||
|
||||
// Configure the HttpClient to be aware of the Dependabot Proxy, if used.
|
||||
HttpClientHandler httpClientHandler = new();
|
||||
@@ -662,7 +662,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
try
|
||||
{
|
||||
ExecuteGetRequest(feed, client, cts.Token).GetAwaiter().GetResult();
|
||||
logger.LogInfo($"Querying Nuget feed '{feed}' succeeded.");
|
||||
logger.LogInfo($"Querying NuGet feed '{feed}' succeeded.");
|
||||
return true;
|
||||
}
|
||||
catch (Exception exc)
|
||||
@@ -671,19 +671,19 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
tce.CancellationToken == cts.Token &&
|
||||
cts.Token.IsCancellationRequested)
|
||||
{
|
||||
logger.LogInfo($"Didn't receive answer from Nuget feed '{feed}' in {timeoutMilliSeconds}ms.");
|
||||
logger.LogInfo($"Didn't receive answer from NuGet feed '{feed}' in {timeoutMilliSeconds}ms.");
|
||||
timeoutMilliSeconds *= 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're only interested in timeouts.
|
||||
var start = allowExceptions ? "Considering" : "Not considering";
|
||||
logger.LogInfo($"Querying Nuget feed '{feed}' failed in a timely manner. {start} the feed for use. The reason for the failure: {exc.Message}");
|
||||
logger.LogInfo($"Querying NuGet feed '{feed}' failed in a timely manner. {start} the feed for use. The reason for the failure: {exc.Message}");
|
||||
return allowExceptions;
|
||||
}
|
||||
}
|
||||
|
||||
logger.LogWarning($"Didn't receive answer from Nuget feed '{feed}'. Tried it {tryCount} times.");
|
||||
logger.LogWarning($"Didn't receive answer from NuGet feed '{feed}'. Tried it {tryCount} times.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -694,20 +694,20 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeout), out timeoutMilliSeconds)
|
||||
? timeoutMilliSeconds
|
||||
: 1000;
|
||||
logger.LogDebug($"Initial timeout for Nuget feed reachability check is {timeoutMilliSeconds}ms.");
|
||||
logger.LogDebug($"Initial timeout for NuGet feed reachability check is {timeoutMilliSeconds}ms.");
|
||||
|
||||
int tryCount = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCountForFallback), out tryCount)
|
||||
? tryCount
|
||||
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCount), out tryCount)
|
||||
? tryCount
|
||||
: 4;
|
||||
logger.LogDebug($"Number of tries for Nuget feed reachability check is {tryCount}.");
|
||||
logger.LogDebug($"Number of tries for NuGet feed reachability check is {tryCount}.");
|
||||
|
||||
return (timeoutMilliSeconds, tryCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that we can connect to all Nuget feeds that are explicitly configured in configuration files
|
||||
/// Checks that we can connect to all NuGet feeds that are explicitly configured in configuration files
|
||||
/// as well as any private package registry feeds that are configured.
|
||||
/// </summary>
|
||||
/// <param name="explicitFeeds">Outputs the set of explicit feeds.</param>
|
||||
@@ -727,28 +727,28 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var inheritedFeeds = allFeeds.Except(explicitFeeds).ToHashSet();
|
||||
if (inheritedFeeds.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Inherited Nuget feeds (not checked for reachability): {string.Join(", ", inheritedFeeds.OrderBy(f => f))}");
|
||||
compilationInfoContainer.CompilationInfos.Add(("Inherited Nuget feed count", inheritedFeeds.Count.ToString()));
|
||||
logger.LogInfo($"Inherited NuGet feeds (not checked for reachability): {string.Join(", ", inheritedFeeds.OrderBy(f => f))}");
|
||||
compilationInfoContainer.CompilationInfos.Add(("Inherited NuGet feed count", inheritedFeeds.Count.ToString()));
|
||||
}
|
||||
|
||||
return allFeedsReachable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that we can connect to the specified Nuget feeds.
|
||||
/// Checks that we can connect to the specified NuGet feeds.
|
||||
/// </summary>
|
||||
/// <param name="feeds">The set of package feeds to check.</param>
|
||||
/// <returns>True if all feeds are reachable or false otherwise.</returns>
|
||||
private bool CheckSpecifiedFeeds(HashSet<string> feeds)
|
||||
{
|
||||
logger.LogInfo("Checking that Nuget feeds are reachable...");
|
||||
logger.LogInfo("Checking that NuGet feeds are reachable...");
|
||||
|
||||
var excludedFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.ExcludedNugetFeedsFromResponsivenessCheck)
|
||||
.ToHashSet();
|
||||
|
||||
if (excludedFeeds.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Excluded Nuget feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Excluded NuGet feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
|
||||
}
|
||||
|
||||
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: false);
|
||||
@@ -756,17 +756,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
var allFeedsReachable = feeds.All(feed => excludedFeeds.Contains(feed) || IsFeedReachable(feed, initialTimeout, tryCount));
|
||||
if (!allFeedsReachable)
|
||||
{
|
||||
logger.LogWarning("Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.");
|
||||
logger.LogWarning("Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.");
|
||||
diagnosticsWriter.AddEntry(new DiagnosticMessage(
|
||||
Language.CSharp,
|
||||
"buildless/unreachable-feed",
|
||||
"Found unreachable Nuget feed in C# analysis with build-mode 'none'",
|
||||
"Found unreachable NuGet feed in C# analysis with build-mode 'none'",
|
||||
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
|
||||
markdownMessage: "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
markdownMessage: "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
severity: DiagnosticMessage.TspSeverity.Note
|
||||
));
|
||||
}
|
||||
compilationInfoContainer.CompilationInfos.Add(("All Nuget feeds reachable", allFeedsReachable ? "1" : "0"));
|
||||
compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", allFeedsReachable ? "1" : "0"));
|
||||
|
||||
return allFeedsReachable;
|
||||
}
|
||||
@@ -808,11 +808,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
if (explicitFeeds.Count > 0)
|
||||
{
|
||||
logger.LogInfo($"Found {explicitFeeds.Count} Nuget feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Found {explicitFeeds.Count} NuGet feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug("No Nuget feeds found in nuget.config files.");
|
||||
logger.LogDebug("No NuGet feeds found in nuget.config files.");
|
||||
}
|
||||
|
||||
// todo: this could be improved.
|
||||
@@ -844,7 +844,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
allFeeds = GetFeeds(() => dotnet.GetNugetFeedsFromFolder(this.fileProvider.SourceDir.FullName)).ToHashSet();
|
||||
}
|
||||
|
||||
logger.LogInfo($"Found {allFeeds.Count} Nuget feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
|
||||
logger.LogInfo($"Found {allFeeds.Count} NuGet feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
|
||||
|
||||
return (explicitFeeds, allFeeds);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
| All Nuget feeds reachable | 1.0 |
|
||||
| All NuGet feeds reachable | 1.0 |
|
||||
| Failed project restore with package source error | 0.0 |
|
||||
| Failed solution restore with package source error | 0.0 |
|
||||
| Inherited Nuget feed count | 1.0 |
|
||||
| Inherited NuGet feed count | 1.0 |
|
||||
| NuGet feed responsiveness checked | 1.0 |
|
||||
| Project files on filesystem | 1.0 |
|
||||
| Reachable fallback Nuget feed count | 1.0 |
|
||||
| Reachable fallback NuGet feed count | 1.0 |
|
||||
| Resource extraction enabled | 1.0 |
|
||||
| Restored .NET framework variants | 1.0 |
|
||||
| Restored projects through solution files | 0.0 |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
| All Nuget feeds reachable | 1.0 |
|
||||
| All NuGet feeds reachable | 1.0 |
|
||||
| Failed project restore with package source error | 0.0 |
|
||||
| Failed solution restore with package source error | 0.0 |
|
||||
| Inherited Nuget feed count | 1.0 |
|
||||
| Inherited NuGet feed count | 1.0 |
|
||||
| NuGet feed responsiveness checked | 1.0 |
|
||||
| Project files on filesystem | 1.0 |
|
||||
| Reachable fallback Nuget feed count | 1.0 |
|
||||
| Reachable fallback NuGet feed count | 1.0 |
|
||||
| Resource extraction enabled | 0.0 |
|
||||
| Restored .NET framework variants | 1.0 |
|
||||
| Restored projects through solution files | 0.0 |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
| All Nuget feeds reachable | 1.0 |
|
||||
| All NuGet feeds reachable | 1.0 |
|
||||
| Failed project restore with package source error | 1.0 |
|
||||
| Failed solution restore with package source error | 0.0 |
|
||||
| Fallback nuget restore | 1.0 |
|
||||
| NuGet feed responsiveness checked | 1.0 |
|
||||
| Project files on filesystem | 1.0 |
|
||||
| Reachable fallback Nuget feed count | 1.0 |
|
||||
| Reachable fallback NuGet feed count | 1.0 |
|
||||
| Resolved assembly conflicts | 7.0 |
|
||||
| Resource extraction enabled | 0.0 |
|
||||
| Restored .NET framework variants | 0.0 |
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| All Nuget feeds reachable | 0.0 |
|
||||
| All NuGet feeds reachable | 0.0 |
|
||||
| Fallback nuget restore | 1.0 |
|
||||
| Inherited Nuget feed count | 1.0 |
|
||||
| Inherited NuGet feed count | 1.0 |
|
||||
| NuGet feed responsiveness checked | 1.0 |
|
||||
| Project files on filesystem | 1.0 |
|
||||
| Reachable fallback Nuget feed count | 1.0 |
|
||||
| Reachable fallback NuGet feed count | 1.0 |
|
||||
| Resolved assembly conflicts | 7.0 |
|
||||
| Resource extraction enabled | 0.0 |
|
||||
| Restored .NET framework variants | 0.0 |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
@@ -27,12 +27,12 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
"markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/unreachable-feed",
|
||||
"name": "Found unreachable Nuget feed in C# analysis with build-mode 'none'"
|
||||
"name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
|
||||
@@ -4,7 +4,7 @@ import runs_on
|
||||
|
||||
@runs_on.posix
|
||||
def test(codeql, csharp):
|
||||
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Nuget feed check is enabled by default
|
||||
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # NuGet feed check is enabled by default
|
||||
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_TIMEOUT"] = (
|
||||
"1" # 1ms, the GET request should fail with such short timeout
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
| All Nuget feeds reachable | 0.0 |
|
||||
| All NuGet feeds reachable | 0.0 |
|
||||
| Fallback nuget restore | 1.0 |
|
||||
| NuGet feed responsiveness checked | 1.0 |
|
||||
| Project files on filesystem | 1.0 |
|
||||
| Reachable fallback Nuget feed count | 2.0 |
|
||||
| Reachable fallback NuGet feed count | 2.0 |
|
||||
| Resolved assembly conflicts | 7.0 |
|
||||
| Resource extraction enabled | 0.0 |
|
||||
| Restored .NET framework variants | 0.0 |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
|
||||
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
@@ -27,12 +27,12 @@
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
"markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "csharp",
|
||||
"id": "csharp/autobuilder/buildless/unreachable-feed",
|
||||
"name": "Found unreachable Nuget feed in C# analysis with build-mode 'none'"
|
||||
"name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
|
||||
@@ -5,7 +5,7 @@ import runs_on
|
||||
@runs_on.posix
|
||||
def test(codeql, csharp):
|
||||
|
||||
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Nuget feed check is enabled by default
|
||||
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # NuGet feed check is enabled by default
|
||||
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_TIMEOUT"] = (
|
||||
"1" # 1ms, the GET request should fail with such short timeout
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Generate stubs for a single NuGet package
|
||||
|
||||
Stubs can be generated from Nuget packages with the `make_stubs_nuget.py` script.
|
||||
Stubs can be generated from NuGet packages with the `make_stubs_nuget.py` script.
|
||||
|
||||
The following calls generate stubs for `Newtonsoft.Json`:
|
||||
|
||||
@@ -13,7 +13,7 @@ python3 make_stubs_nuget.py classlib Newtonsoft.Json 13.0.1 /Users/tmp/working-d
|
||||
|
||||
The output stubs are found in the `[DIR]/output/stubs` folder and can be copied over to `csharp/ql/test/resources/stubs`.
|
||||
|
||||
In some more involved cases the output files need to be edited. For example `ServiceStack` has Nuget dependencies, which
|
||||
In some more involved cases the output files need to be edited. For example `ServiceStack` has NuGet dependencies, which
|
||||
are included in the `Microsoft.NETCore.App` framework stub. These dependencies generate empty packages, which can be
|
||||
removed. The `ProjectReference` entries referencing these removed empty packages also need to be deleted from the
|
||||
`.csproj` files.
|
||||
|
||||
@@ -1388,7 +1388,7 @@ module JCAModel {
|
||||
override Crypto::TKeyAgreementType getKeyAgreementType() {
|
||||
if key_agreement_name_to_type_known(_, super.getValue())
|
||||
then key_agreement_name_to_type_known(result, super.getValue())
|
||||
else result = Crypto::UnknownKeyAgreementType()
|
||||
else result = Crypto::OtherKeyAgreementType()
|
||||
}
|
||||
|
||||
KeyAgreementAlgorithmValueConsumer getConsumer() { result = consumer }
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint flow through the `URL` constructor from the `url` package, improving the identification of SSRF vulnerabilities.
|
||||
@@ -82,6 +82,13 @@ module RequestForgery {
|
||||
pred = url.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::NewNode url |
|
||||
url = API::moduleImport("url").getMember("URL").getAnInstantiation()
|
||||
|
|
||||
succ = url and
|
||||
pred = url.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(HtmlSanitizerCall call |
|
||||
pred = call.getInput() and
|
||||
succ = call
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
| serverSide.js:117:20:117:30 | new ws(url) | serverSide.js:115:25:115:35 | request.url | serverSide.js:117:27:117:29 | url | The $@ of this request depends on a $@. | serverSide.js:117:27:117:29 | url | URL | serverSide.js:115:25:115:35 | request.url | user-provided value |
|
||||
| serverSide.js:125:5:128:6 | axios({ ... \\n }) | serverSide.js:123:29:123:35 | req.url | serverSide.js:127:14:127:20 | tainted | The $@ of this request depends on a $@. | serverSide.js:127:14:127:20 | tainted | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
|
||||
| serverSide.js:131:5:131:20 | axios.get(myUrl) | serverSide.js:123:29:123:35 | req.url | serverSide.js:131:15:131:19 | myUrl | The $@ of this request depends on a $@. | serverSide.js:131:15:131:19 | myUrl | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
|
||||
| serverSide.js:141:3:141:30 | axios.g ... ring()) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:141:13:141:29 | target.toString() | The $@ of this request depends on a $@. | serverSide.js:141:13:141:29 | target.toString() | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
|
||||
| serverSide.js:142:3:142:19 | axios.get(target) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:142:13:142:18 | target | The $@ of this request depends on a $@. | serverSide.js:142:13:142:18 | target | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
|
||||
| serverSide.js:143:3:143:24 | axios.g ... t.href) | serverSide.js:139:17:139:29 | req.query.url | serverSide.js:143:13:143:23 | target.href | The $@ of this request depends on a $@. | serverSide.js:143:13:143:23 | target.href | URL | serverSide.js:139:17:139:29 | req.query.url | user-provided value |
|
||||
edges
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | provenance | |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | provenance | |
|
||||
@@ -106,6 +109,15 @@ edges
|
||||
| serverSide.js:123:29:123:35 | req.url | serverSide.js:123:19:123:42 | url.par ... , true) | provenance | |
|
||||
| serverSide.js:130:9:130:45 | myUrl | serverSide.js:131:15:131:19 | myUrl | provenance | |
|
||||
| serverSide.js:130:37:130:43 | tainted | serverSide.js:130:9:130:45 | myUrl | provenance | |
|
||||
| serverSide.js:139:9:139:29 | input | serverSide.js:140:26:140:30 | input | provenance | |
|
||||
| serverSide.js:139:17:139:29 | req.query.url | serverSide.js:139:9:139:29 | input | provenance | |
|
||||
| serverSide.js:140:9:140:31 | target | serverSide.js:141:13:141:18 | target | provenance | |
|
||||
| serverSide.js:140:9:140:31 | target | serverSide.js:142:13:142:18 | target | provenance | |
|
||||
| serverSide.js:140:9:140:31 | target | serverSide.js:143:13:143:18 | target | provenance | |
|
||||
| serverSide.js:140:18:140:31 | new URL(input) | serverSide.js:140:9:140:31 | target | provenance | |
|
||||
| serverSide.js:140:26:140:30 | input | serverSide.js:140:18:140:31 | new URL(input) | provenance | Config |
|
||||
| serverSide.js:141:13:141:18 | target | serverSide.js:141:13:141:29 | target.toString() | provenance | |
|
||||
| serverSide.js:143:13:143:18 | target | serverSide.js:143:13:143:23 | target.href | provenance | |
|
||||
nodes
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | semmle.label | { url } |
|
||||
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | semmle.label | url |
|
||||
@@ -199,4 +211,14 @@ nodes
|
||||
| serverSide.js:130:9:130:45 | myUrl | semmle.label | myUrl |
|
||||
| serverSide.js:130:37:130:43 | tainted | semmle.label | tainted |
|
||||
| serverSide.js:131:15:131:19 | myUrl | semmle.label | myUrl |
|
||||
| serverSide.js:139:9:139:29 | input | semmle.label | input |
|
||||
| serverSide.js:139:17:139:29 | req.query.url | semmle.label | req.query.url |
|
||||
| serverSide.js:140:9:140:31 | target | semmle.label | target |
|
||||
| serverSide.js:140:18:140:31 | new URL(input) | semmle.label | new URL(input) |
|
||||
| serverSide.js:140:26:140:30 | input | semmle.label | input |
|
||||
| serverSide.js:141:13:141:18 | target | semmle.label | target |
|
||||
| serverSide.js:141:13:141:29 | target.toString() | semmle.label | target.toString() |
|
||||
| serverSide.js:142:13:142:18 | target | semmle.label | target |
|
||||
| serverSide.js:143:13:143:18 | target | semmle.label | target |
|
||||
| serverSide.js:143:13:143:23 | target.href | semmle.label | target.href |
|
||||
subpaths
|
||||
|
||||
@@ -133,3 +133,12 @@ var server2 = http.createServer(function(req, res) {
|
||||
var myEncodedUrl = `${something}/bla/${encodeURIComponent(tainted)}`;
|
||||
axios.get(myEncodedUrl);
|
||||
})
|
||||
|
||||
var server2 = http.createServer(function(req, res) {
|
||||
const { URL } = require('url');
|
||||
const input = req.query.url; // $Source[js/request-forgery]
|
||||
const target = new URL(input);
|
||||
axios.get(target.toString()); // $Alert[js/request-forgery]
|
||||
axios.get(target); // $Alert[js/request-forgery]
|
||||
axios.get(target.href); // $Alert[js/request-forgery]
|
||||
});
|
||||
|
||||
@@ -151,4 +151,17 @@ private module Pandas {
|
||||
|
||||
override DataFlow::Node getCode() { result = this.getParameter(0, "expr").asSink() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Call to `pandas.read_sql` or `pandas.read_sql_query`
|
||||
* which allows for executing raw SQL queries against a database.
|
||||
* See https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
|
||||
*/
|
||||
class ReadSqlCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ReadSqlCall() {
|
||||
this = API::moduleImport("pandas").getMember(["read_sql", "read_sql_query"]).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added SQL injection models from the `pandas` PyPI package.
|
||||
@@ -1,5 +1,5 @@
|
||||
import pandas as pd
|
||||
|
||||
import sqlite3
|
||||
|
||||
df = pd.DataFrame({'temp_c': [17.0, 25.0]}, index=['Portland', 'Berkeley'])
|
||||
df.sample().query("query") # $getCode="query"
|
||||
@@ -55,11 +55,12 @@ df = pd.read_sql_table("filepath", 'postgres:///db_name')
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
|
||||
df = pd.read_sql_query("filepath", 'postgres:///db_name')
|
||||
connection = sqlite3.connect("pets.db")
|
||||
df = pd.read_sql_query("sql query", connection) # $getSql="sql query"
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
|
||||
df = pd.read_sql("filepath", 'postgres:///db_name')
|
||||
df = pd.read_sql("sql query", connection) # $getSql="sql query"
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* in the code viewer.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.Variable
|
||||
private import codeql.rust.elements.Locatable
|
||||
private import codeql.rust.elements.FormatArgsExpr
|
||||
@@ -12,9 +13,12 @@ private import codeql.rust.elements.MacroCall
|
||||
private import codeql.rust.elements.NamedFormatArgument
|
||||
private import codeql.rust.elements.PositionalFormatArgument
|
||||
private import codeql.Locations
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
/** An element with an associated definition. */
|
||||
abstract class Use extends Locatable {
|
||||
Use() { not this.(AstNode).isFromMacroExpansion() }
|
||||
|
||||
/** Gets the definition associated with this element. */
|
||||
abstract Definition getDefinition();
|
||||
|
||||
@@ -30,7 +34,8 @@ private module Cached {
|
||||
newtype TDef =
|
||||
TVariable(Variable v) or
|
||||
TFormatArgsArgName(Name name) { name = any(FormatArgsArg a).getName() } or
|
||||
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() }
|
||||
TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or
|
||||
TItemNode(ItemNode i)
|
||||
|
||||
/**
|
||||
* Gets an element, of kind `kind`, that element `use` uses, if any.
|
||||
@@ -51,7 +56,8 @@ class Definition extends Cached::TDef {
|
||||
Location getLocation() {
|
||||
result = this.asVariable().getLocation() or
|
||||
result = this.asName().getLocation() or
|
||||
result = this.asExpr().getLocation()
|
||||
result = this.asExpr().getLocation() or
|
||||
result = this.asItemNode().getLocation()
|
||||
}
|
||||
|
||||
/** Gets this definition as a `Variable` */
|
||||
@@ -63,11 +69,15 @@ class Definition extends Cached::TDef {
|
||||
/** Gets this definition as an `Expr` */
|
||||
Expr asExpr() { this = Cached::TFormatArgsArgIndex(result) }
|
||||
|
||||
/** Gets this definition as an `ItemNode` */
|
||||
ItemNode asItemNode() { this = Cached::TItemNode(result) }
|
||||
|
||||
/** Gets the string representation of this element. */
|
||||
string toString() {
|
||||
result = this.asExpr().toString() or
|
||||
result = this.asVariable().toString() or
|
||||
result = this.asName().getText()
|
||||
result = this.asName().getText() or
|
||||
result = this.asItemNode().toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,3 +134,20 @@ private class PositionalFormatArgumentUse extends Use instanceof PositionalForma
|
||||
|
||||
override string getUseType() { result = "format argument" }
|
||||
}
|
||||
|
||||
private class PathUse extends Use instanceof Path {
|
||||
override Definition getDefinition() { result.asItemNode() = resolvePath(this) }
|
||||
|
||||
override string getUseType() { result = "path" }
|
||||
}
|
||||
|
||||
private class FileUse extends Use instanceof Name {
|
||||
override Definition getDefinition() {
|
||||
exists(Module m |
|
||||
this = m.getName() and
|
||||
fileImport(m, result.asItemNode())
|
||||
)
|
||||
}
|
||||
|
||||
override string getUseType() { result = "file" }
|
||||
}
|
||||
|
||||
@@ -1021,7 +1021,8 @@ private predicate pathAttrImport(Folder f, Module m, string relativePath) {
|
||||
private predicate shouldAppend(Folder f, string relativePath) { pathAttrImport(f, _, relativePath) }
|
||||
|
||||
/** Holds if `m` is a `mod name;` item importing file `f`. */
|
||||
private predicate fileImport(Module m, SourceFile f) {
|
||||
pragma[nomagic]
|
||||
predicate fileImport(Module m, SourceFile f) {
|
||||
exists(string name, Folder parent |
|
||||
modImport0(m, name, _) and
|
||||
fileModule(f, name, parent)
|
||||
@@ -1404,18 +1405,20 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `i` is available inside `f` because it is reexported in [the prelude][1].
|
||||
* Holds if `i` is available inside `f` because it is reexported in
|
||||
* [the `core` prelude][1] or [the `std` prelude][2].
|
||||
*
|
||||
* We don't yet have access to prelude information from the extractor, so for now
|
||||
* we include all the preludes for Rust: 2015, 2018, 2021, and 2024.
|
||||
*
|
||||
* [1]: https://doc.rust-lang.org/core/prelude/index.html
|
||||
* [2]: https://doc.rust-lang.org/std/prelude/index.html
|
||||
*/
|
||||
private predicate preludeEdge(SourceFile f, string name, ItemNode i) {
|
||||
exists(Crate core, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
|
||||
f = any(Crate c0 | core = c0.getDependency(_) or core = c0).getASourceFile() and
|
||||
core.getName() = "core" and
|
||||
mod = core.getSourceFile() and
|
||||
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
|
||||
f = any(Crate c0 | stdOrCore = c0.getDependency(_) or stdOrCore = c0).getASourceFile() and
|
||||
stdOrCore.getName() = ["std", "core"] and
|
||||
mod = stdOrCore.getSourceFile() and
|
||||
prelude = mod.getASuccessorRec("prelude") and
|
||||
rust = prelude.getASuccessorRec(["rust_2015", "rust_2018", "rust_2021", "rust_2024"]) and
|
||||
i = rust.getASuccessorRec(name) and
|
||||
|
||||
@@ -207,81 +207,58 @@ private Type inferAssignmentOperationType(AstNode n, TypePath path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type of `n1` at `path1` is the same as the type of `n2` at
|
||||
* `path2` and type information should propagate in both directions through the
|
||||
* type equality.
|
||||
* Holds if the type tree of `n1` at `prefix1` should be equal to the type tree
|
||||
* of `n2` at `prefix2` and type information should propagate in both directions
|
||||
* through the type equality.
|
||||
*/
|
||||
bindingset[path1]
|
||||
bindingset[path2]
|
||||
private predicate typeEquality(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
|
||||
exists(Variable v |
|
||||
path1 = path2 and
|
||||
n1 = v.getAnAccess()
|
||||
|
|
||||
n2 = v.getPat()
|
||||
private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) {
|
||||
prefix1.isEmpty() and
|
||||
prefix2.isEmpty() and
|
||||
(
|
||||
exists(Variable v | n1 = v.getAnAccess() |
|
||||
n2 = v.getPat()
|
||||
or
|
||||
n2 = v.getParameter().(SelfParam)
|
||||
)
|
||||
or
|
||||
n2 = v.getParameter().(SelfParam)
|
||||
)
|
||||
or
|
||||
exists(LetStmt let |
|
||||
let.getPat() = n1 and
|
||||
let.getInitializer() = n2 and
|
||||
path1 = path2
|
||||
)
|
||||
or
|
||||
n1 = n2.(ParenExpr).getExpr() and
|
||||
path1 = path2
|
||||
or
|
||||
n1 = n2.(BlockExpr).getStmtList().getTailExpr() and
|
||||
path1 = path2
|
||||
or
|
||||
n1 = n2.(IfExpr).getABranch() and
|
||||
path1 = path2
|
||||
or
|
||||
n1 = n2.(MatchExpr).getAnArm().getExpr() and
|
||||
path1 = path2
|
||||
or
|
||||
exists(BreakExpr break |
|
||||
break.getExpr() = n1 and
|
||||
break.getTarget() = n2.(LoopExpr) and
|
||||
path1 = path2
|
||||
)
|
||||
or
|
||||
exists(AssignmentExpr be |
|
||||
n1 = be.getLhs() and
|
||||
n2 = be.getRhs() and
|
||||
path1 = path2
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[path1]
|
||||
private predicate typeEqualityLeft(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
|
||||
typeEquality(n1, path1, n2, path2)
|
||||
or
|
||||
n2 =
|
||||
any(DerefExpr pe |
|
||||
pe.getExpr() = n1 and
|
||||
path1.isCons(TRefTypeParameter(), path2)
|
||||
exists(LetStmt let |
|
||||
let.getPat() = n1 and
|
||||
let.getInitializer() = n2
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[path2]
|
||||
private predicate typeEqualityRight(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
|
||||
typeEquality(n1, path1, n2, path2)
|
||||
or
|
||||
n2 =
|
||||
any(DerefExpr pe |
|
||||
pe.getExpr() = n1 and
|
||||
path1 = TypePath::cons(TRefTypeParameter(), path2)
|
||||
or
|
||||
n1 = n2.(ParenExpr).getExpr()
|
||||
or
|
||||
n1 = n2.(BlockExpr).getStmtList().getTailExpr()
|
||||
or
|
||||
n1 = n2.(IfExpr).getABranch()
|
||||
or
|
||||
n1 = n2.(MatchExpr).getAnArm().getExpr()
|
||||
or
|
||||
exists(BreakExpr break |
|
||||
break.getExpr() = n1 and
|
||||
break.getTarget() = n2.(LoopExpr)
|
||||
)
|
||||
or
|
||||
exists(AssignmentExpr be |
|
||||
n1 = be.getLhs() and
|
||||
n2 = be.getRhs()
|
||||
)
|
||||
)
|
||||
or
|
||||
n1 = n2.(DerefExpr).getExpr() and
|
||||
prefix1 = TypePath::singleton(TRefTypeParameter()) and
|
||||
prefix2.isEmpty()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferTypeEquality(AstNode n, TypePath path) {
|
||||
exists(AstNode n2, TypePath path2 | result = inferType(n2, path2) |
|
||||
typeEqualityRight(n, path, n2, path2)
|
||||
exists(TypePath prefix1, AstNode n2, TypePath prefix2, TypePath suffix |
|
||||
result = inferType(n2, prefix2.appendInverse(suffix)) and
|
||||
path = prefix1.append(suffix)
|
||||
|
|
||||
typeEquality(n, prefix1, n2, prefix2)
|
||||
or
|
||||
typeEqualityLeft(n2, path2, n, path)
|
||||
typeEquality(n2, prefix2, n, prefix1)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
| main.rs:2:9:2:13 | width | main.rs:5:29:5:33 | width | local variable |
|
||||
| main.rs:2:9:2:13 | width | main.rs:6:41:6:45 | width | local variable |
|
||||
| main.rs:2:9:2:13 | width | main.rs:7:36:7:40 | width | local variable |
|
||||
| main.rs:3:9:3:17 | precision | main.rs:5:36:5:44 | precision | local variable |
|
||||
| main.rs:3:9:3:17 | precision | main.rs:6:48:6:56 | precision | local variable |
|
||||
| main.rs:4:9:4:13 | value | main.rs:6:34:6:38 | value | local variable |
|
||||
| main.rs:4:9:4:13 | value | main.rs:7:29:7:33 | value | local variable |
|
||||
| main.rs:5:50:5:54 | value | main.rs:5:22:5:26 | value | format argument |
|
||||
| main.rs:6:34:6:38 | value | main.rs:6:22:6:22 | 0 | format argument |
|
||||
| main.rs:6:41:6:45 | width | main.rs:6:25:6:25 | 1 | format argument |
|
||||
| main.rs:6:48:6:56 | precision | main.rs:6:28:6:28 | 2 | format argument |
|
||||
| main.rs:7:29:7:33 | value | main.rs:7:21:7:22 | {} | format argument |
|
||||
| main.rs:7:36:7:40 | width | main.rs:7:24:7:25 | {} | format argument |
|
||||
| main.rs:8:9:8:14 | people | main.rs:9:22:9:27 | people | local variable |
|
||||
| main.rs:10:31:10:31 | 1 | main.rs:10:19:10:20 | {} | format argument |
|
||||
| main.rs:10:31:10:31 | 1 | main.rs:10:23:10:23 | 0 | format argument |
|
||||
| main.rs:10:34:10:34 | 2 | main.rs:10:16:10:16 | 1 | format argument |
|
||||
| main.rs:10:34:10:34 | 2 | main.rs:10:26:10:27 | {} | format argument |
|
||||
| main.rs:11:40:11:42 | "x" | main.rs:11:31:11:35 | {:<5} | format argument |
|
||||
| main.rs:3:5:3:7 | lib | lib.rs:1:1:1:1 | SourceFile | file |
|
||||
| main.rs:9:22:9:26 | value | main.rs:9:50:9:54 | value | format argument |
|
||||
| main.rs:9:29:9:33 | width | main.rs:6:9:6:13 | width | local variable |
|
||||
| main.rs:9:36:9:44 | precision | main.rs:7:9:7:17 | precision | local variable |
|
||||
| main.rs:10:22:10:22 | 0 | main.rs:10:34:10:38 | value | format argument |
|
||||
| main.rs:10:25:10:25 | 1 | main.rs:10:41:10:45 | width | format argument |
|
||||
| main.rs:10:28:10:28 | 2 | main.rs:10:48:10:56 | precision | format argument |
|
||||
| main.rs:10:34:10:38 | value | main.rs:8:9:8:13 | value | local variable |
|
||||
| main.rs:10:41:10:45 | width | main.rs:6:9:6:13 | width | local variable |
|
||||
| main.rs:10:48:10:56 | precision | main.rs:7:9:7:17 | precision | local variable |
|
||||
| main.rs:11:21:11:22 | {} | main.rs:11:29:11:33 | value | format argument |
|
||||
| main.rs:11:24:11:25 | {} | main.rs:11:36:11:40 | width | format argument |
|
||||
| main.rs:11:29:11:33 | value | main.rs:8:9:8:13 | value | local variable |
|
||||
| main.rs:11:36:11:40 | width | main.rs:6:9:6:13 | width | local variable |
|
||||
| main.rs:13:22:13:27 | people | main.rs:12:9:12:14 | people | local variable |
|
||||
| main.rs:14:16:14:16 | 1 | main.rs:14:34:14:34 | 2 | format argument |
|
||||
| main.rs:14:19:14:20 | {} | main.rs:14:31:14:31 | 1 | format argument |
|
||||
| main.rs:14:23:14:23 | 0 | main.rs:14:31:14:31 | 1 | format argument |
|
||||
| main.rs:14:26:14:27 | {} | main.rs:14:34:14:34 | 2 | format argument |
|
||||
| main.rs:15:31:15:35 | {:<5} | main.rs:15:40:15:42 | "x" | format argument |
|
||||
| main.rs:16:13:16:13 | S | main.rs:1:1:1:9 | struct S | path |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import codeql.rust.internal.Definitions
|
||||
|
||||
from Definition def, Use use, string kind
|
||||
where def = definitionOf(use, kind)
|
||||
select def, use, kind
|
||||
where
|
||||
def = definitionOf(use, kind) and
|
||||
use.fromSource()
|
||||
select use, def, kind
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
struct S;
|
||||
|
||||
mod lib;
|
||||
|
||||
fn main() {
|
||||
let width = 4;
|
||||
let precision = 2;
|
||||
@@ -9,4 +13,5 @@ fn main() {
|
||||
println!("Hello {people}!");
|
||||
println!("{1} {} {0} {}", 1, 2);
|
||||
assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !");
|
||||
let x = S;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
multiplePathResolutions
|
||||
| main.rs:218:14:218:17 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:218:14:218:17 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:219:13:219:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:219:13:219:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:220:13:220:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:220:13:220:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:221:13:221:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:221:13:221:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:222:13:222:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:222:13:222:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:223:13:223:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:223:13:223:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:224:13:224:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| main.rs:224:13:224:16 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
@@ -0,0 +1,11 @@
|
||||
multiplePathResolutions
|
||||
| deallocation.rs:106:16:106:19 | libc | file://:0:0:0:0 | Crate(libc@0.2.171) |
|
||||
| deallocation.rs:106:16:106:19 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| deallocation.rs:106:16:106:27 | ...::malloc | file://:0:0:0:0 | fn malloc |
|
||||
| deallocation.rs:106:16:106:27 | ...::malloc | file://:0:0:0:0 | fn malloc |
|
||||
| deallocation.rs:112:3:112:6 | libc | file://:0:0:0:0 | Crate(libc@0.2.171) |
|
||||
| deallocation.rs:112:3:112:6 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
| deallocation.rs:112:3:112:12 | ...::free | file://:0:0:0:0 | fn free |
|
||||
| deallocation.rs:112:3:112:12 | ...::free | file://:0:0:0:0 | fn free |
|
||||
| deallocation.rs:112:29:112:32 | libc | file://:0:0:0:0 | Crate(libc@0.2.171) |
|
||||
| deallocation.rs:112:29:112:32 | libc | file://:0:0:0:0 | Crate(libc@0.2.172) |
|
||||
@@ -424,6 +424,17 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
final override ConsumerInputDataFlowNode getInputNode() { result = inputNode }
|
||||
}
|
||||
|
||||
final private class SignatureArtifactConsumer extends ArtifactConsumerAndInstance {
|
||||
ConsumerInputDataFlowNode inputNode;
|
||||
|
||||
SignatureArtifactConsumer() {
|
||||
exists(SignatureOperationInstance op | inputNode = op.getSignatureConsumer()) and
|
||||
this = Input::dfn_to_element(inputNode)
|
||||
}
|
||||
|
||||
final override ConsumerInputDataFlowNode getInputNode() { result = inputNode }
|
||||
}
|
||||
|
||||
/**
|
||||
* An artifact that is produced by an operation, representing a concrete artifact instance rather than a synthetic consumer artifact.
|
||||
*/
|
||||
@@ -458,6 +469,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
override DataFlowNode getOutputNode() { result = creator.getOutputArtifact() }
|
||||
|
||||
KeyOperationInstance getCreator() { result = creator }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,6 +795,17 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
abstract ArtifactOutputDataFlowNode getOutputArtifact();
|
||||
}
|
||||
|
||||
/**
|
||||
* A key operation instance representing a signature being generated or verified.
|
||||
*/
|
||||
abstract class SignatureOperationInstance extends KeyOperationInstance {
|
||||
/**
|
||||
* Gets the consumer of the signature that is being verified in case of a
|
||||
* verification operation.
|
||||
*/
|
||||
abstract ConsumerInputDataFlowNode getSignatureConsumer();
|
||||
}
|
||||
|
||||
/**
|
||||
* A key-based algorithm instance used in cryptographic operations such as encryption, decryption,
|
||||
* signing, verification, and key wrapping.
|
||||
@@ -1132,8 +1156,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
DH() or // Diffie-Hellman
|
||||
EDH() or // Ephemeral Diffie-Hellman
|
||||
ECDH() or // Elliptic Curve Diffie-Hellman
|
||||
// NOTE: for now ESDH is considered simply EDH
|
||||
//ESDH() or // Ephemeral-Static Diffie-Hellman
|
||||
// Note: x25519 and x448 are applications of ECDH
|
||||
UnknownKeyAgreementType()
|
||||
OtherKeyAgreementType()
|
||||
|
||||
abstract class KeyAgreementAlgorithmInstance extends AlgorithmInstance {
|
||||
abstract TKeyAgreementType getKeyAgreementType();
|
||||
@@ -1264,6 +1290,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
TNonceInput(NonceArtifactConsumer e) or
|
||||
TMessageInput(MessageArtifactConsumer e) or
|
||||
TSaltInput(SaltArtifactConsumer e) or
|
||||
TSignatureInput(SignatureArtifactConsumer e) or
|
||||
TRandomNumberGeneration(RandomNumberGenerationInstance e) { e.flowsTo(_) } or
|
||||
// Key Creation Operation union type (e.g., key generation, key load)
|
||||
TKeyCreationOperation(KeyCreationOperationInstance e) or
|
||||
@@ -1325,14 +1352,14 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* Returns the child of this node with the given edge name.
|
||||
*
|
||||
* This predicate is overriden by derived classes to construct the graph of cryptographic operations.
|
||||
* This predicate is overridden by derived classes to construct the graph of cryptographic operations.
|
||||
*/
|
||||
NodeBase getChild(string edgeName) { none() }
|
||||
|
||||
/**
|
||||
* Defines properties of this node by name and either a value or location or both.
|
||||
*
|
||||
* This predicate is overriden by derived classes to construct the graph of cryptographic operations.
|
||||
* This predicate is overridden by derived classes to construct the graph of cryptographic operations.
|
||||
*/
|
||||
predicate properties(string key, string value, Location location) { none() }
|
||||
|
||||
@@ -1505,6 +1532,20 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override LocatableElement asElement() { result = instance }
|
||||
}
|
||||
|
||||
/**
|
||||
* A signature input. This may represent a signature, or a signature component
|
||||
* such as the scalar values r and s in ECDSA.
|
||||
*/
|
||||
final class SignatureArtifactNode extends ArtifactNode, TSignatureInput {
|
||||
SignatureArtifactConsumer instance;
|
||||
|
||||
SignatureArtifactNode() { this = TSignatureInput(instance) }
|
||||
|
||||
final override string getInternalType() { result = "SignatureInput" }
|
||||
|
||||
override LocatableElement asElement() { result = instance }
|
||||
}
|
||||
|
||||
/**
|
||||
* A salt input.
|
||||
*/
|
||||
@@ -1528,13 +1569,22 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
KeyOperationOutputNode() { this = TKeyOperationOutput(instance) }
|
||||
|
||||
final override string getInternalType() { result = "KeyOperationOutput" }
|
||||
override string getInternalType() { result = "KeyOperationOutput" }
|
||||
|
||||
override LocatableElement asElement() { result = instance }
|
||||
|
||||
override string getSourceNodeRelationship() { none() }
|
||||
}
|
||||
|
||||
class SignOperationOutputNode extends KeyOperationOutputNode {
|
||||
SignOperationOutputNode() {
|
||||
this.asElement().(KeyOperationOutputArtifactInstance).getCreator().getKeyOperationSubtype() =
|
||||
TSignMode()
|
||||
}
|
||||
|
||||
override string getInternalType() { result = "SignatureOutput" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A source of random number generation.
|
||||
*/
|
||||
@@ -2107,6 +2157,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
class SignatureOperationNode extends KeyOperationNode {
|
||||
override SignatureOperationInstance instance;
|
||||
string nodeName;
|
||||
|
||||
SignatureOperationNode() {
|
||||
@@ -2116,6 +2167,21 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
override string getInternalType() { result = nodeName }
|
||||
|
||||
SignatureArtifactNode getASignatureArtifact() {
|
||||
result.asElement() = instance.getSignatureConsumer().getConsumer()
|
||||
}
|
||||
|
||||
override NodeBase getChild(string key) {
|
||||
result = super.getChild(key)
|
||||
or
|
||||
// [KNOWN_OR_UNKNOWN] - only if we know the type is verify
|
||||
this.getKeyOperationSubtype() = TVerifyMode() and
|
||||
key = "Signature" and
|
||||
if exists(this.getASignatureArtifact())
|
||||
then result = this.getASignatureArtifact()
|
||||
else result = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2563,6 +2629,8 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
or
|
||||
curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
or
|
||||
curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448()
|
||||
or
|
||||
// TODO: separate these into key agreement logic or sign/verify (ECDSA / ECDH)
|
||||
// or
|
||||
// curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
@@ -2570,8 +2638,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
// curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
// or
|
||||
// curveName = "ED448" and keySize = 448 and curveFamily = CURVE448()
|
||||
// curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448()
|
||||
// or
|
||||
// or
|
||||
// curveName = "X448" and keySize = 448 and curveFamily = CURVE448()
|
||||
curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2()
|
||||
|
||||
Reference in New Issue
Block a user