mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
Changed casing on TCipherType, Added some initial fixes for hash support, started developing openssl hashing modeling.
This commit is contained in:
@@ -3,7 +3,7 @@ import experimental.Quantum.Language
|
||||
import EVPCipherConsumers
|
||||
import OpenSSLAlgorithmGetter
|
||||
|
||||
predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
|
||||
predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
|
||||
exists(string name, string algType | algType.toLowerCase().matches("%encryption") |
|
||||
resolveAlgorithmFromLiteral(e, name, algType) and
|
||||
(
|
||||
@@ -21,9 +21,9 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
|
||||
or
|
||||
name.matches("CAST5") and type instanceof Crypto::CAST5
|
||||
or
|
||||
name.matches("2DES") and type instanceof Crypto::DOUBLEDES
|
||||
name.matches("2DES") and type instanceof Crypto::DoubleDES
|
||||
or
|
||||
name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TRIPLEDES
|
||||
name.matches(["3DES", "TRIPLEDES"]) and type instanceof Crypto::TripleDES
|
||||
or
|
||||
name.matches("DES") and type instanceof Crypto::DES
|
||||
or
|
||||
@@ -52,7 +52,6 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal
|
||||
{
|
||||
OpenSSLAlgorithmGetterCall cipherGetterCall;
|
||||
@@ -81,7 +80,9 @@ class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorit
|
||||
|
||||
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
|
||||
override Crypto::TCipherType getCipherFamily() { literalToCipherFamilyType(this, result) }
|
||||
override Crypto::TCipherType getCipherFamily() {
|
||||
literalToCipherFamilyType(this, result)
|
||||
}
|
||||
}
|
||||
// override Crypto::TCipherType getCipherFamily() {
|
||||
// if this.cipherNameMappingKnown(_, super.getAlgorithmName())
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import cpp
|
||||
import experimental.Quantum.Language
|
||||
import EVPCipherConsumers
|
||||
import OpenSSLAlgorithmGetter
|
||||
|
||||
predicate literalToHashFamilyType(Literal e, Crypto::THashType type) {
|
||||
exists(string name, string algType | algType.toLowerCase().matches("%hash") |
|
||||
resolveAlgorithmFromLiteral(e, name, algType) and
|
||||
(
|
||||
name.matches("BLAKE2B") and type instanceof Crypto::BLAKE2B
|
||||
or
|
||||
name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S
|
||||
or
|
||||
name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160
|
||||
or
|
||||
name.matches("MD2") and type instanceof Crypto::MD2
|
||||
or
|
||||
name.matches("MD4") and type instanceof Crypto::MD4
|
||||
or
|
||||
name.matches("MD5") and type instanceof Crypto::MD5
|
||||
or
|
||||
name.matches("POLY1305") and type instanceof Crypto::POLY1305
|
||||
or
|
||||
name.matches(["SHA1", "SHA"]) and type instanceof Crypto::SHA1
|
||||
or
|
||||
name.matches("SHA2") and type instanceof Crypto::SHA2
|
||||
or
|
||||
name.matches("SHA3") and type instanceof Crypto::SHA3
|
||||
or
|
||||
name.matches("SHAKE") and type instanceof Crypto::SHAKE
|
||||
or
|
||||
name.matches("SM3") and type instanceof Crypto::SM3
|
||||
or
|
||||
name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL
|
||||
// TODO: what about MD_GOST?
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal
|
||||
{
|
||||
OpenSSLAlgorithmGetterCall cipherGetterCall;
|
||||
|
||||
HashKnownAlgorithmLiteralAlgorithmInstance() {
|
||||
exists(DataFlow::Node src, DataFlow::Node sink |
|
||||
sink = cipherGetterCall.getValueArgNode() and
|
||||
src.asExpr() = this and
|
||||
KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and
|
||||
// Not just any known value, but specifically a known cipher operation
|
||||
exists(string algType |
|
||||
resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and
|
||||
algType.toLowerCase().matches("hash")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: should this not be part of the abstract algorithm definition?
|
||||
Crypto::AlgorithmConsumer getConsumer() {
|
||||
AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result))
|
||||
}
|
||||
|
||||
override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) }
|
||||
|
||||
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import experimental.Quantum.Language
|
||||
import CtxFlow as CTXFlow
|
||||
|
||||
|
||||
//https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
|
||||
@@ -162,9 +162,9 @@ class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall {
|
||||
Expr resultExpr;
|
||||
|
||||
EVPCipherGetterCall() {
|
||||
// Flow out through the return pointer itself (trace the pointer, not what it is pointing to)
|
||||
resultExpr = this and
|
||||
resultNode.asExpr() = this and
|
||||
isPossibleOpenSSLFunction(this.getTarget()) and
|
||||
(
|
||||
this.getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and
|
||||
valueArgExpr = this.getArgument(0) and
|
||||
@@ -188,6 +188,38 @@ class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall {
|
||||
|
||||
override Expr getResultExpr() { result = resultExpr }
|
||||
}
|
||||
|
||||
class EVPDigestGetterCall extends OpenSSLAlgorithmGetterCall {
|
||||
DataFlow::Node valueArgNode;
|
||||
DataFlow::Node resultNode;
|
||||
Expr valueArgExpr;
|
||||
Expr resultExpr;
|
||||
|
||||
EVPDigestGetterCall() {
|
||||
resultExpr = this and
|
||||
resultNode.asExpr() = this and
|
||||
isPossibleOpenSSLFunction(this.getTarget()) and
|
||||
(
|
||||
this.getTarget().getName() in [
|
||||
"EVP_get_digestbyname", "EVP_get_digestbyobj", "EVP_get_digestbynid"
|
||||
] and
|
||||
valueArgExpr = this.getArgument(0) and
|
||||
valueArgNode.asExpr() = valueArgExpr
|
||||
or
|
||||
this.getTarget().getName() = "EVP_MD_fetch" and
|
||||
valueArgExpr = this.getArgument(1) and
|
||||
valueArgNode.asExpr() = valueArgExpr
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getValueArgNode() { result = valueArgNode }
|
||||
|
||||
override DataFlow::Node getResultNode() { result = resultNode }
|
||||
|
||||
override Expr getValueArgExpr() { result = valueArgExpr }
|
||||
|
||||
override Expr getResultExpr() { result = resultExpr }
|
||||
}
|
||||
// /**
|
||||
// * Predicates/classes for identifying algorithm sinks.
|
||||
// * An Algorithm Sink is a function that takes an algorithm as an argument.
|
||||
|
||||
@@ -123,7 +123,7 @@ module JCAModel {
|
||||
override Crypto::TCipherType getCipherFamily() {
|
||||
if this.cipherNameMappingKnown(_, super.getAlgorithmName())
|
||||
then this.cipherNameMappingKnown(result, super.getAlgorithmName())
|
||||
else result instanceof Crypto::OTHERCIPHERTYPE
|
||||
else result instanceof Crypto::OtherCipherType
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
@@ -135,7 +135,7 @@ module JCAModel {
|
||||
type instanceof Crypto::DES
|
||||
or
|
||||
name = "TripleDES" and
|
||||
type instanceof Crypto::TRIPLEDES
|
||||
type instanceof Crypto::TripleDES
|
||||
or
|
||||
name = "IDEA" and
|
||||
type instanceof Crypto::IDEA
|
||||
|
||||
@@ -140,7 +140,13 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* An element that represents a _known_ cryptographic algorithm.
|
||||
*/
|
||||
abstract class AlgorithmElement extends KnownElement { }
|
||||
abstract class AlgorithmElement extends KnownElement {
|
||||
/**
|
||||
* Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding".
|
||||
* This name is not parsed or formatted.
|
||||
*/
|
||||
abstract string getRawAlgorithmName();
|
||||
}
|
||||
|
||||
/**
|
||||
* An element that represents a _known_ cryptographic artifact.
|
||||
@@ -286,12 +292,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
abstract class CipherAlgorithmInstance extends AlgorithmElement {
|
||||
/**
|
||||
* Gets the raw name as it appears in source, e.g., "AES/CBC/PKCS7Padding".
|
||||
* This name is not parsed or formatted.
|
||||
*/
|
||||
abstract string getRawAlgorithmName();
|
||||
|
||||
/**
|
||||
* Gets the type of this cipher, e.g., "AES" or "ChaCha20".
|
||||
*/
|
||||
@@ -358,7 +358,12 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
abstract class HashOperationInstance extends KnownElement { }
|
||||
|
||||
abstract class HashAlgorithmInstance extends KnownElement { }
|
||||
abstract class HashAlgorithmInstance extends AlgorithmElement {
|
||||
/**
|
||||
* Gets the type of this digest algorithm, e.g., "SHA1", "SHA2", "MD5" etc.
|
||||
*/
|
||||
abstract THashType getHashFamily();
|
||||
}
|
||||
|
||||
abstract class KeyDerivationOperationInstance extends KnownElement { }
|
||||
|
||||
@@ -875,15 +880,15 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
IDEA() or
|
||||
KUZNYECHIK() or
|
||||
MAGMA() or
|
||||
TRIPLEDES() or
|
||||
DOUBLEDES() or
|
||||
TripleDES() or
|
||||
DoubleDES() or
|
||||
RC2() or
|
||||
RC4() or
|
||||
RC5() or
|
||||
RSA() or
|
||||
SEED() or
|
||||
SM4() or
|
||||
OTHERCIPHERTYPE()
|
||||
OtherCipherType()
|
||||
|
||||
final class CipherAlgorithmNode extends AlgorithmNode, TCipherAlgorithm {
|
||||
CipherAlgorithmInstance instance;
|
||||
@@ -932,27 +937,47 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
final private predicate cipherFamilyToNameAndStructure(
|
||||
TCipherType type, string name, TCipherStructureType s
|
||||
) {
|
||||
type instanceof AES and name = "AES" and s = Block() or
|
||||
type instanceof ARIA and name = "ARIA" and s = Block() or
|
||||
type instanceof BLOWFISH and name = "Blowfish" and s = Block() or
|
||||
type instanceof CAMELLIA and name = "Camellia" and s = Block() or
|
||||
type instanceof CAST5 and name = "CAST5" and s = Block() or
|
||||
type instanceof CHACHA20 and name = "ChaCha20" and s = Stream() or
|
||||
type instanceof DES and name = "DES" and s = Block() or
|
||||
type instanceof DESX and name = "DESX" and s = Block() or
|
||||
type instanceof GOST and name = "GOST" and s = Block() or
|
||||
type instanceof IDEA and name = "IDEA" and s = Block() or
|
||||
type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block() or
|
||||
type instanceof MAGMA and name = "Magma" and s = Block() or
|
||||
type instanceof TRIPLEDES and name = "TripleDES" and s = Block() or
|
||||
type instanceof DOUBLEDES and name = "DoubleDES" and s = Block() or
|
||||
type instanceof RC2 and name = "RC2" and s = Block() or
|
||||
type instanceof RC4 and name = "RC4" and s = Stream() or
|
||||
type instanceof RC5 and name = "RC5" and s = Block() or
|
||||
type instanceof RSA and name = "RSA" and s = Asymmetric() or
|
||||
type instanceof SEED and name = "SEED" and s = Block() or
|
||||
type instanceof SM4 and name = "SM4" and s = Block() or
|
||||
type instanceof OTHERCIPHERTYPE and
|
||||
type instanceof AES and name = "AES" and s = Block()
|
||||
or
|
||||
type instanceof ARIA and name = "ARIA" and s = Block()
|
||||
or
|
||||
type instanceof BLOWFISH and name = "Blowfish" and s = Block()
|
||||
or
|
||||
type instanceof CAMELLIA and name = "Camellia" and s = Block()
|
||||
or
|
||||
type instanceof CAST5 and name = "CAST5" and s = Block()
|
||||
or
|
||||
type instanceof CHACHA20 and name = "ChaCha20" and s = Stream()
|
||||
or
|
||||
type instanceof DES and name = "DES" and s = Block()
|
||||
or
|
||||
type instanceof DESX and name = "DESX" and s = Block()
|
||||
or
|
||||
type instanceof GOST and name = "GOST" and s = Block()
|
||||
or
|
||||
type instanceof IDEA and name = "IDEA" and s = Block()
|
||||
or
|
||||
type instanceof KUZNYECHIK and name = "Kuznyechik" and s = Block()
|
||||
or
|
||||
type instanceof MAGMA and name = "Magma" and s = Block()
|
||||
or
|
||||
type instanceof TripleDES and name = "TripleDES" and s = Block()
|
||||
or
|
||||
type instanceof DoubleDES and name = "DoubleDES" and s = Block()
|
||||
or
|
||||
type instanceof RC2 and name = "RC2" and s = Block()
|
||||
or
|
||||
type instanceof RC4 and name = "RC4" and s = Stream()
|
||||
or
|
||||
type instanceof RC5 and name = "RC5" and s = Block()
|
||||
or
|
||||
type instanceof RSA and name = "RSA" and s = Asymmetric()
|
||||
or
|
||||
type instanceof SEED and name = "SEED" and s = Block()
|
||||
or
|
||||
type instanceof SM4 and name = "SM4" and s = Block()
|
||||
or
|
||||
type instanceof OtherCipherType and
|
||||
name = this.getRawAlgorithmName() and
|
||||
s = UnknownCipherStructureType()
|
||||
}
|
||||
@@ -1004,13 +1029,18 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
newtype THashType =
|
||||
BLAKE2B() or
|
||||
BLAKE2S() or
|
||||
RIPEMD160() or
|
||||
MD2() or
|
||||
MD4() or
|
||||
MD5() or
|
||||
POLY1305() or
|
||||
SHA1() or
|
||||
SHA2() or
|
||||
SHA3() or
|
||||
RIPEMD160() or
|
||||
SHAKE() or
|
||||
SM3() or
|
||||
WHIRLPOOL() or
|
||||
OtherHashType()
|
||||
|
||||
@@ -1021,19 +1051,29 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override string getInternalType() { result = "HashAlgorithm" }
|
||||
|
||||
final predicate hashTypeToNameMapping(THashType type, string name) {
|
||||
type instanceof BLAKE2B and name = "BLAKE2B"
|
||||
or
|
||||
type instanceof BLAKE2S and name = "BLAKE2S"
|
||||
or
|
||||
type instanceof RIPEMD160 and name = "RIPEMD160"
|
||||
or
|
||||
type instanceof MD2 and name = "MD2"
|
||||
or
|
||||
type instanceof MD4 and name = "MD4"
|
||||
or
|
||||
type instanceof MD5 and name = "MD5"
|
||||
or
|
||||
type instanceof POLY1305 and name = "POLY1305"
|
||||
or
|
||||
type instanceof SHA1 and name = "SHA1"
|
||||
or
|
||||
type instanceof SHA2 and name = "SHA2"
|
||||
or
|
||||
type instanceof SHA3 and name = "SHA3"
|
||||
or
|
||||
type instanceof RIPEMD160 and name = "RIPEMD160"
|
||||
type instanceof SHAKE and name = "SHAKE"
|
||||
or
|
||||
type instanceof SM3 and name = "SM3"
|
||||
or
|
||||
type instanceof WHIRLPOOL and name = "WHIRLPOOL"
|
||||
or
|
||||
|
||||
Reference in New Issue
Block a user