mirror of
https://github.com/github/codeql.git
synced 2026-04-24 16:25:15 +02:00
autoformat
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import experimental.cryptography.CryptoArtifact
|
||||
import experimental.cryptography.CryptoAlgorithmNames
|
||||
|
||||
import experimental.cryptography.modules.OpenSSL as OpenSSL
|
||||
|
||||
|
||||
@@ -11,35 +11,47 @@
|
||||
string unknownAlgorithm() { result = "UNKNOWN" }
|
||||
|
||||
string getHashType() { result = "HASH" }
|
||||
|
||||
string getSymmetricEncryptionType() { result = "SYMMETRIC_ENCRYPTION" }
|
||||
|
||||
string getAsymmetricEncryptionType() { result = "ASYMMETRIC_ENCRYPTION" }
|
||||
|
||||
string getKeyDerivationType() { result = "KEY_DERIVATION" }
|
||||
|
||||
string getCipherBlockModeType() { result = "BLOCK_MODE" }
|
||||
|
||||
string getSymmetricPaddingType() { result = "SYMMETRIC_PADDING" }
|
||||
|
||||
string getAsymmetricPaddingType() { result = "ASYMMETRIC_PADDING" }
|
||||
|
||||
string getEllipticCurveType() { result = "ELLIPTIC_CURVE" }
|
||||
|
||||
string getSignatureType() { result = "SIGNATURE" }
|
||||
|
||||
string getKeyExchangeType() { result = "KEY_EXCHANGE" }
|
||||
|
||||
string getAsymmetricType(){
|
||||
result in [getAsymmetricEncryptionType(), getSignatureType(), getKeyExchangeType(), getEllipticCurveType()]
|
||||
string getAsymmetricType() {
|
||||
result in [
|
||||
getAsymmetricEncryptionType(), getSignatureType(), getKeyExchangeType(),
|
||||
getEllipticCurveType()
|
||||
]
|
||||
}
|
||||
|
||||
predicate isKnownType(string algType){
|
||||
predicate isKnownType(string algType) {
|
||||
algType in [
|
||||
getHashType(), getSymmetricEncryptionType(), getAsymmetricEncryptionType(), getKeyDerivationType(),
|
||||
getCipherBlockModeType(), getSymmetricPaddingType(), getAsymmetricPaddingType(), getEllipticCurveType(),
|
||||
getSignatureType(), getKeyExchangeType()
|
||||
]
|
||||
getHashType(), getSymmetricEncryptionType(), getAsymmetricEncryptionType(),
|
||||
getKeyDerivationType(), getCipherBlockModeType(), getSymmetricPaddingType(),
|
||||
getAsymmetricPaddingType(), getEllipticCurveType(), getSignatureType(), getKeyExchangeType()
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
predicate isKnownAlgorithm(string name) { isKnownAlgorithm(name, _) }
|
||||
|
||||
predicate isKnownAlgorithm(string name, string algType) {
|
||||
isHashingAlgorithm(name) and algType = "HASH"
|
||||
or
|
||||
isEncryptionAlgorithm(name, algType) and algType in ["SYMMETRIC_ENCRYPTION", "ASYMMETRIC_ENCRYPTION"]
|
||||
isEncryptionAlgorithm(name, algType) and
|
||||
algType in ["SYMMETRIC_ENCRYPTION", "ASYMMETRIC_ENCRYPTION"]
|
||||
or
|
||||
isKeyDerivationAlgorithm(name) and algType = "KEY_DERIVATION"
|
||||
or
|
||||
@@ -60,11 +72,11 @@ predicate isKnownAlgorithm(string name, string algType) {
|
||||
predicate isHashingAlgorithm(string name) {
|
||||
name =
|
||||
[
|
||||
"BLAKE2", "BLAKE2B", "BLAKE2S",
|
||||
"SHA2", "SHA224", "SHA256", "SHA384", "SHA512", "SHA512224", "SHA512256",
|
||||
"SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHAKE128", "SHAKE256", "SM3",
|
||||
"WHIRLPOOL", "POLY1305", "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128",
|
||||
"RIPEMD256", "RIPEMD160", "RIPEMD320", "SHA0", "SHA1", "SHA", "MGF1","MGF1SHA1", "MDC2", "SIPHASH"
|
||||
"BLAKE2", "BLAKE2B", "BLAKE2S", "SHA2", "SHA224", "SHA256", "SHA384", "SHA512", "SHA512224",
|
||||
"SHA512256", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", "SHAKE128", "SHAKE256",
|
||||
"SM3", "WHIRLPOOL", "POLY1305", "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD",
|
||||
"RIPEMD128", "RIPEMD256", "RIPEMD160", "RIPEMD320", "SHA0", "SHA1", "SHA", "MGF1", "MGF1SHA1",
|
||||
"MDC2", "SIPHASH"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -86,10 +98,10 @@ predicate isSymmetricEncryptionAlgorithm(string name) {
|
||||
"AES", "AES128", "AES192", "AES256", "ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5",
|
||||
"CAMELLIA", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "CHACHA", "CHACHA20",
|
||||
"CHACHA20POLY1305", "GOST", "GOSTR34102001", "GOSTR341094", "GOSTR341194", "GOST2814789",
|
||||
"GOSTR341194", "GOST2814789", "GOST28147", "GOSTR341094", "GOST89", "GOST94", "GOST34102012",
|
||||
"GOST34112012", "IDEA", "RABBIT",
|
||||
"SEED", "SM4", "DES", "DESX", "3DES", "TDES", "2DES", "DES3", "TRIPLEDES", "TDEA", "TRIPLEDEA",
|
||||
"ARC2", "RC2", "ARC4", "RC4", "ARCFOUR", "ARC5", "RC5", "MAGMA", "KUZNYECHIK"
|
||||
"GOSTR341194", "GOST2814789", "GOST28147", "GOSTR341094", "GOST89", "GOST94", "GOST34102012",
|
||||
"GOST34112012", "IDEA", "RABBIT", "SEED", "SM4", "DES", "DESX", "3DES", "TDES", "2DES",
|
||||
"DES3", "TRIPLEDES", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", "ARCFOUR", "ARC5",
|
||||
"RC5", "MAGMA", "KUZNYECHIK"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -201,20 +213,25 @@ predicate isEllipticCurveAlgorithm(string curveName, int keySize) {
|
||||
curveName = "NUMSP512T1" and keySize = 512
|
||||
or
|
||||
curveName = "SM2" and keySize in [256, 512]
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` corresponds to a known signature algorithm.
|
||||
*/
|
||||
predicate isSignatureAlgorithm(string name) {
|
||||
name = ["DSA", "ECDSA", "EDDSA", "ES256", "ES256K", "ES384", "ES512", "ED25519", "ED448", "ECDSA256", "ECDSA384", "ECDSA512"]
|
||||
predicate isSignatureAlgorithm(string name) {
|
||||
name =
|
||||
[
|
||||
"DSA", "ECDSA", "EDDSA", "ES256", "ES256K", "ES384", "ES512", "ED25519", "ED448", "ECDSA256",
|
||||
"ECDSA384", "ECDSA512"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` is a key exchange algorithm.
|
||||
*/
|
||||
predicate isKeyExchangeAlgorithm(string name) { name = ["ECDH", "DH", "DIFFIEHELLMAN", "X25519", "X448"] }
|
||||
predicate isKeyExchangeAlgorithm(string name) {
|
||||
name = ["ECDH", "DH", "DIFFIEHELLMAN", "X25519", "X448"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` corresponds to a known asymmetric encryption.
|
||||
|
||||
@@ -2,20 +2,19 @@ import cpp
|
||||
private import experimental.cryptography.CryptoAlgorithmNames
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* A cryptographic artifact is a DataFlow::Node associated with some
|
||||
* operation, algorithm, or any other aspect of cryptography.
|
||||
*/
|
||||
abstract class CryptographicArtifact extends Expr {}
|
||||
* A cryptographic artifact is a DataFlow::Node associated with some
|
||||
* operation, algorithm, or any other aspect of cryptography.
|
||||
*/
|
||||
|
||||
abstract class CryptographicArtifact extends Expr { }
|
||||
|
||||
// /**
|
||||
// * Associates a symmetric encryption algorithm with a block mode.
|
||||
// * The DataFlow::Node representing this association should be the
|
||||
// * point where the algorithm and block mode are combined.
|
||||
// * This may be at the call to encryption or in the construction
|
||||
// * of an object prior to encryption.
|
||||
// * point where the algorithm and block mode are combined.
|
||||
// * This may be at the call to encryption or in the construction
|
||||
// * of an object prior to encryption.
|
||||
// */
|
||||
// abstract class SymmetricCipher extends CryptographicArtifact{
|
||||
// abstract SymmetricEncryptionAlgorithm getEncryptionAlgorithm();
|
||||
@@ -24,112 +23,91 @@ abstract class CryptographicArtifact extends Expr {}
|
||||
// exists(this.getBlockMode())
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * A cryptographic operation is a method call that invokes a cryptographic
|
||||
// * algorithm (encrypt/decrypt) or a function in support of a cryptographic algorithm
|
||||
// * (key generation).
|
||||
// *
|
||||
// *
|
||||
// * Since operations are related to or in support of algorithms, operations must
|
||||
// * provide a reference to their associated algorithm. Often operataions themselves
|
||||
// * encapsulate algorithms, so operations can also extend CryptographicAlgorithm
|
||||
// * and refer to themselves as the target algorithm.
|
||||
// * and refer to themselves as the target algorithm.
|
||||
// */
|
||||
// abstract class CryptographicOperation extends CryptographicArtifact, Call{
|
||||
|
||||
// // bindingset[paramName, ind]
|
||||
// // final DataFlow::Node getParameterSource(int ind, string paramName){
|
||||
// // result = Utils::getUltimateSrcFromApiNode(this.(API::CallNode).getParameter(ind, paramName))
|
||||
// // }
|
||||
|
||||
// final string getAlgorithmName(){
|
||||
// if exists(this.getAlgorithm().getName())
|
||||
// then result = this.getAlgorithm().getName()
|
||||
// else result = unknownAlgorithm()
|
||||
// }
|
||||
|
||||
// final predicate hasAlgorithm(){
|
||||
// exists(this.getAlgorithm())
|
||||
// }
|
||||
|
||||
// final predicate isUnknownAlgorithm(){
|
||||
// this.getAlgorithmName() = unknownAlgorithm()
|
||||
// or
|
||||
// not this.hasAlgorithm()
|
||||
// }
|
||||
|
||||
// // TODO: this might have to be parameterized by a configuration source for
|
||||
// // situations where an operation is passed an algorithm
|
||||
// abstract CryptographicAlgorithm getAlgorithm();
|
||||
|
||||
// }
|
||||
|
||||
// /** A key generation operation for asymmetric keys */
|
||||
// abstract class KeyGen extends CryptographicOperation{
|
||||
|
||||
|
||||
// int getAKeySizeInBits(){
|
||||
// result = getKeySizeInBits(_)
|
||||
// }
|
||||
|
||||
// final predicate hasKeySize(Expr configSrc){
|
||||
// exists(this.getKeySizeInBits(configSrc))
|
||||
// }
|
||||
|
||||
// final predicate hasKeySize(){
|
||||
// exists(this.getAKeySizeInBits())
|
||||
// }
|
||||
|
||||
// abstract Expr getKeyConfigSrc();
|
||||
// abstract int getKeySizeInBits(Expr configSrc);
|
||||
|
||||
// }
|
||||
|
||||
|
||||
abstract class CryptographicOperation extends CryptographicArtifact, Call{}
|
||||
abstract class CryptographicOperation extends CryptographicArtifact, Call { }
|
||||
|
||||
abstract class KeyGeneration extends CryptographicOperation {
|
||||
|
||||
// TODO: what if the algorithm is UNKNOWN?
|
||||
|
||||
abstract Expr getKeyConfigurationSource(CryptographicAlgorithm alg);
|
||||
|
||||
abstract CryptographicAlgorithm getAlgorithm();
|
||||
|
||||
int getKeySizeInBits(CryptographicAlgorithm alg){
|
||||
int getKeySizeInBits(CryptographicAlgorithm alg) {
|
||||
result = getKeyConfigurationSource(alg).(Literal).getValue().toInt()
|
||||
}
|
||||
|
||||
predicate hasConstantKeySize(CryptographicAlgorithm alg){
|
||||
exists(this.getKeySizeInBits(alg))
|
||||
}
|
||||
predicate hasConstantKeySize(CryptographicAlgorithm alg) { exists(this.getKeySizeInBits(alg)) }
|
||||
|
||||
predicate hasKeyConfigurationSource(CryptographicAlgorithm alg){
|
||||
predicate hasKeyConfigurationSource(CryptographicAlgorithm alg) {
|
||||
exists(this.getKeyConfigurationSource(alg))
|
||||
}
|
||||
|
||||
Expr getAKeyConfigurationSource(){
|
||||
result = getKeyConfigurationSource(_)
|
||||
}
|
||||
Expr getAKeyConfigurationSource() { result = getKeyConfigurationSource(_) }
|
||||
}
|
||||
|
||||
abstract class AsymmetricKeyGeneration extends KeyGeneration{}
|
||||
abstract class SymmetricKeyGeneration extends KeyGeneration{}
|
||||
abstract class AsymmetricKeyGeneration extends KeyGeneration { }
|
||||
|
||||
abstract class SymmetricKeyGeneration extends KeyGeneration { }
|
||||
|
||||
/**
|
||||
* A cryptographic algorithm is a `CryptographicArtifact`
|
||||
* A cryptographic algorithm is a `CryptographicArtifact`
|
||||
* representing a cryptographic algorithm (see `CryptoAlgorithmNames.qll`).
|
||||
* Cryptographic algorithms can be functions referencing common crypto algorithms (e.g., hashlib.md5)
|
||||
* or strings that are used in cryptographic operation configurations (e.g., hashlib.new("md5")).
|
||||
* Cryptogrpahic algorithms may also be operations that wrap or abstract one or
|
||||
* more algorithms (e.g., cyrptography.fernet.Fernet and AES, CBC and PKCS7).
|
||||
*
|
||||
*
|
||||
* In principle, this class should model the location where an algorithm enters the program, not
|
||||
* necessarily where it is used.
|
||||
* necessarily where it is used.
|
||||
*/
|
||||
abstract class CryptographicAlgorithm extends CryptographicArtifact
|
||||
{
|
||||
abstract class CryptographicAlgorithm extends CryptographicArtifact {
|
||||
abstract string getName();
|
||||
|
||||
abstract string getAlgType();
|
||||
|
||||
// string getAlgType(){
|
||||
@@ -145,97 +123,74 @@ abstract class CryptographicAlgorithm extends CryptographicArtifact
|
||||
// else if this instanceof SigningAlgorithm then result = getSignatureType()
|
||||
// else result = unknownAlgorithm()
|
||||
// }
|
||||
|
||||
// TODO: handle case where name isn't known, not just unknown?
|
||||
|
||||
// TODO: handle case where name isn't known, not just unknown?
|
||||
/**
|
||||
* Normalizes a raw name into a normalized name as found in `CryptoAlgorithmNames.qll`.
|
||||
* Subclassess should override for more api-specific normalization.
|
||||
* By deafult, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
* By deafult, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
*/
|
||||
bindingset[s]
|
||||
string normalizeName(string s)
|
||||
{
|
||||
exists(string normStr |
|
||||
normStr = s.toUpperCase().regexpReplaceAll("[-_ ]|/", "")
|
||||
|
|
||||
(result = normStr and isKnownAlgorithm(result))
|
||||
string normalizeName(string s) {
|
||||
exists(string normStr | normStr = s.toUpperCase().regexpReplaceAll("[-_ ]|/", "") |
|
||||
result = normStr and isKnownAlgorithm(result)
|
||||
or
|
||||
(result = unknownAlgorithm() and not isKnownAlgorithm(normStr))
|
||||
result = unknownAlgorithm() and not isKnownAlgorithm(normStr)
|
||||
)
|
||||
}
|
||||
|
||||
abstract Expr configurationSink();
|
||||
|
||||
predicate hasConfigurationSink(){
|
||||
exists(this.configurationSink())
|
||||
}
|
||||
predicate hasConfigurationSink() { exists(this.configurationSink()) }
|
||||
}
|
||||
|
||||
abstract class HashAlgorithm extends CryptographicAlgorithm{
|
||||
final string getHashName(){
|
||||
abstract class HashAlgorithm extends CryptographicAlgorithm {
|
||||
final string getHashName() {
|
||||
if exists(string n | n = this.getName() and isHashingAlgorithm(n))
|
||||
then (isHashingAlgorithm(result) and result = this.getName())
|
||||
then isHashingAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getHashType()
|
||||
}
|
||||
override string getAlgType() { result = getHashType() }
|
||||
}
|
||||
|
||||
|
||||
abstract class KeyDerivationAlgorithm extends CryptographicAlgorithm{
|
||||
final string getKDFName(){
|
||||
abstract class KeyDerivationAlgorithm extends CryptographicAlgorithm {
|
||||
final string getKDFName() {
|
||||
if exists(string n | n = this.getName() and isKeyDerivationAlgorithm(n))
|
||||
then (isKeyDerivationAlgorithm(result) and result = this.getName())
|
||||
then isKeyDerivationAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getKeyDerivationType()
|
||||
}
|
||||
override string getAlgType() { result = getKeyDerivationType() }
|
||||
}
|
||||
|
||||
// abstract class KeyDerivationOperation extends CryptographicOperation{
|
||||
// DataFlow::Node getIterationSizeSrc(){
|
||||
// none()
|
||||
// }
|
||||
|
||||
// DataFlow::Node getSaltConfigSrc(){
|
||||
// none()
|
||||
// }
|
||||
|
||||
// DataFlow::Node getHashConfigSrc(){
|
||||
// none()
|
||||
// }
|
||||
|
||||
// // TODO: get encryption algorithm for CBC-based KDF?
|
||||
|
||||
// DataFlow::Node getDerivedKeySizeSrc(){
|
||||
// none()
|
||||
// }
|
||||
|
||||
// DataFlow::Node getModeSrc(){
|
||||
// none()
|
||||
// }
|
||||
|
||||
// // TODO: add more to cover all the parameters of most KDF operations? Perhaps subclass for each type?
|
||||
|
||||
// abstract predicate requiresIteration();
|
||||
// abstract predicate requiresSalt();
|
||||
// abstract predicate requiresHash();
|
||||
// //abstract predicate requiresKeySize(); // Going to assume all requires a size
|
||||
// abstract predicate requiresMode();
|
||||
|
||||
// }
|
||||
|
||||
|
||||
abstract class EncryptionAlgorithm extends CryptographicAlgorithm
|
||||
{
|
||||
abstract class EncryptionAlgorithm extends CryptographicAlgorithm {
|
||||
final predicate isAsymmetric() { this instanceof AsymmetricEncryptionAlgorithm }
|
||||
final predicate isSymmetric() { not this.isAsymmetric() }
|
||||
|
||||
final predicate isSymmetric() { not this.isAsymmetric() }
|
||||
// NOTE: DO_NOT add getEncryptionName here, we rely on the fact the parent
|
||||
// class does not have this common predicate.
|
||||
}
|
||||
@@ -244,141 +199,118 @@ abstract class EncryptionAlgorithm extends CryptographicAlgorithm
|
||||
* A parent class to represent any algorithm for which
|
||||
* asymmetric cryptography is involved.
|
||||
* Intended to be distinct from AsymmetricEncryptionAlgorithm
|
||||
* which is intended only for asymmetric algorithms that specifically encrypt.
|
||||
* which is intended only for asymmetric algorithms that specifically encrypt.
|
||||
*/
|
||||
abstract class AsymmetricAlgorithm extends CryptographicAlgorithm{}
|
||||
abstract class AsymmetricAlgorithm extends CryptographicAlgorithm { }
|
||||
|
||||
/**
|
||||
* Algorithms directly or indirectly related to asymmetric encryption,
|
||||
* e.g., RSA, DSA, but also RSA padding algorithms
|
||||
*/
|
||||
abstract class AsymmetricEncryptionAlgorithm extends AsymmetricAlgorithm, EncryptionAlgorithm{
|
||||
final string getEncryptionName(){
|
||||
abstract class AsymmetricEncryptionAlgorithm extends AsymmetricAlgorithm, EncryptionAlgorithm {
|
||||
final string getEncryptionName() {
|
||||
if exists(string n | n = this.getName() and isAsymmetricEncryptionAlgorithm(n))
|
||||
then (isAsymmetricEncryptionAlgorithm(result) and result = this.getName())
|
||||
then isAsymmetricEncryptionAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getAsymmetricEncryptionType()
|
||||
}
|
||||
override string getAlgType() { result = getAsymmetricEncryptionType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithms directly or indirectly related to symmetric encryption,
|
||||
* e.g., AES, DES, but also block modes and padding
|
||||
*/
|
||||
abstract class SymmetricEncryptionAlgorithm extends EncryptionAlgorithm
|
||||
{
|
||||
final string getEncryptionName(){
|
||||
abstract class SymmetricEncryptionAlgorithm extends EncryptionAlgorithm {
|
||||
final string getEncryptionName() {
|
||||
if exists(string n | n = this.getName() and isSymmetricEncryptionAlgorithm(n))
|
||||
then (isSymmetricEncryptionAlgorithm(result) and result = this.getName())
|
||||
then isSymmetricEncryptionAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
// TODO: add a stream cipher predicate?
|
||||
|
||||
override string getAlgType(){
|
||||
result = getSymmetricEncryptionType()
|
||||
}
|
||||
// TODO: add a stream cipher predicate?
|
||||
override string getAlgType() { result = getSymmetricEncryptionType() }
|
||||
}
|
||||
|
||||
// Used only to categorize all padding into a single object,
|
||||
// DO_NOT add predicates here. Only for categorization purposes.
|
||||
abstract class PaddingAlgorithm extends CryptographicAlgorithm{}
|
||||
// DO_NOT add predicates here. Only for categorization purposes.
|
||||
abstract class PaddingAlgorithm extends CryptographicAlgorithm { }
|
||||
|
||||
abstract class SymmetricPadding extends PaddingAlgorithm {
|
||||
final string getPaddingName(){
|
||||
final string getPaddingName() {
|
||||
if exists(string n | n = this.getName() and isSymmetricPaddingAlgorithm(n))
|
||||
then (isSymmetricPaddingAlgorithm(result) and result = this.getName())
|
||||
then isSymmetricPaddingAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getSymmetricPaddingType()
|
||||
}
|
||||
override string getAlgType() { result = getSymmetricPaddingType() }
|
||||
}
|
||||
|
||||
abstract class AsymmetricPadding extends PaddingAlgorithm {
|
||||
final string getPaddingName(){
|
||||
final string getPaddingName() {
|
||||
if exists(string n | n = this.getName() and isAsymmetricPaddingAlgorithm(n))
|
||||
then (isAsymmetricPaddingAlgorithm(result) and result = this.getName())
|
||||
then isAsymmetricPaddingAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getAsymmetricPaddingType()
|
||||
}
|
||||
override string getAlgType() { result = getAsymmetricPaddingType() }
|
||||
}
|
||||
|
||||
abstract class EllipticCurveAlgorithm extends AsymmetricAlgorithm{
|
||||
final string getCurveName(){
|
||||
abstract class EllipticCurveAlgorithm extends AsymmetricAlgorithm {
|
||||
final string getCurveName() {
|
||||
if exists(string n | n = this.getName() and isEllipticCurveAlgorithm(n))
|
||||
then (isEllipticCurveAlgorithm(result) and result = this.getName())
|
||||
then isEllipticCurveAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
final int getCurveBitSize(){
|
||||
isEllipticCurveAlgorithm(this.getCurveName(), result)
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getEllipticCurveType()
|
||||
}
|
||||
final int getCurveBitSize() { isEllipticCurveAlgorithm(this.getCurveName(), result) }
|
||||
|
||||
override string getAlgType() { result = getEllipticCurveType() }
|
||||
}
|
||||
|
||||
|
||||
abstract class BlockModeAlgorithm extends CryptographicAlgorithm{
|
||||
final string getBlockModeName(){
|
||||
abstract class BlockModeAlgorithm extends CryptographicAlgorithm {
|
||||
final string getBlockModeName() {
|
||||
if exists(string n | n = this.getName() and isCipherBlockModeAlgorithm(n))
|
||||
then (isCipherBlockModeAlgorithm(result) and result = this.getName())
|
||||
then isCipherBlockModeAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source of the IV configuration.
|
||||
* Gets the source of the IV configuration.
|
||||
*/
|
||||
abstract Expr getIVorNonce();
|
||||
|
||||
final predicate hasIVorNonce() { exists(this.getIVorNonce()) }
|
||||
|
||||
override string getAlgType(){
|
||||
result = getCipherBlockModeType()
|
||||
}
|
||||
override string getAlgType() { result = getCipherBlockModeType() }
|
||||
}
|
||||
|
||||
// abstract class KeyWrapOperation extends CryptographicOperation{
|
||||
// }
|
||||
|
||||
abstract class AuthenticatedEncryptionAlgorithm extends SymmetricEncryptionAlgorithm{
|
||||
final string getAuthticatedEncryptionName(){
|
||||
abstract class AuthenticatedEncryptionAlgorithm extends SymmetricEncryptionAlgorithm {
|
||||
final string getAuthticatedEncryptionName() {
|
||||
if exists(string n | n = this.getName() and isSymmetricEncryptionAlgorithm(n))
|
||||
then (isSymmetricEncryptionAlgorithm(result) and result = this.getName())
|
||||
then isSymmetricEncryptionAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class KeyExchangeAlgorithm extends AsymmetricAlgorithm{
|
||||
final string getKeyExchangeName(){
|
||||
abstract class KeyExchangeAlgorithm extends AsymmetricAlgorithm {
|
||||
final string getKeyExchangeName() {
|
||||
if exists(string n | n = this.getName() and isKeyExchangeAlgorithm(n))
|
||||
then (isKeyExchangeAlgorithm(result) and result = this.getName())
|
||||
then isKeyExchangeAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getKeyExchangeType()
|
||||
}
|
||||
override string getAlgType() { result = getKeyExchangeType() }
|
||||
}
|
||||
|
||||
abstract class SigningAlgorithm extends AsymmetricAlgorithm{
|
||||
final string getSigningName(){
|
||||
abstract class SigningAlgorithm extends AsymmetricAlgorithm {
|
||||
final string getSigningName() {
|
||||
if exists(string n | n = this.getName() and isSignatureAlgorithm(n))
|
||||
then (isSignatureAlgorithm(result) and result = this.getName())
|
||||
then isSignatureAlgorithm(result) and result = this.getName()
|
||||
else result = unknownAlgorithm()
|
||||
}
|
||||
|
||||
override string getAlgType(){
|
||||
result = getSignatureType()
|
||||
}
|
||||
override string getAlgType() { result = getSignatureType() }
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Predicates/classes for identifying algorithm sinks.
|
||||
* Predicates/classes for identifying algorithm sinks.
|
||||
* An Algorithm Sink is a function that takes an algorithm as an argument.
|
||||
* In particular, any function that takes in an algorithm that until the call
|
||||
* In particular, any function that takes in an algorithm that until the call
|
||||
* the algorithm is not definitely known to be an algorithm (e.g., an integer used as an identifier to fetch an algorithm)
|
||||
*/
|
||||
|
||||
@@ -10,274 +10,287 @@ import cpp
|
||||
import experimental.cryptography.utils.OpenSSL.LibraryFunction
|
||||
import experimental.cryptography.CryptoAlgorithmNames
|
||||
|
||||
predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType){
|
||||
arg.algType() = algType
|
||||
}
|
||||
|
||||
predicate isAlgorithmSink(AlgorithmSinkArgument arg, string algType) { arg.algType() = algType }
|
||||
|
||||
abstract class AlgorithmSinkArgument extends Expr {
|
||||
AlgorithmSinkArgument() {
|
||||
exists(Call c| c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget()))
|
||||
}
|
||||
AlgorithmSinkArgument() {
|
||||
exists(Call c | c.getAnArgument() = this and openSSLLibraryFunc(c.getTarget()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the function call in which the argument exists
|
||||
*/
|
||||
Call getSinkCall(){
|
||||
result.getAnArgument() = this
|
||||
}
|
||||
/**
|
||||
* Gets the function call in which the argument exists
|
||||
*/
|
||||
Call getSinkCall() { result.getAnArgument() = this }
|
||||
|
||||
abstract string algType();
|
||||
abstract string algType();
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
|
||||
predicate cipherAlgorithmSink(string funcName, int argInd){
|
||||
(funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0)
|
||||
or
|
||||
(funcName = "EVP_CIPHER_fetch" and argInd = 1)
|
||||
predicate cipherAlgorithmSink(string funcName, int argInd) {
|
||||
funcName in ["EVP_get_cipherbyname", "EVP_get_cipherbynid", "EVP_get_cipherbyobj"] and argInd = 0
|
||||
or
|
||||
funcName = "EVP_CIPHER_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class CipherAlgorithmSink extends AlgorithmSinkArgument {
|
||||
CipherAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
cipherAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
CipherAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
cipherAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getSymmetricEncryptionType() }
|
||||
override string algType() { result = getSymmetricEncryptionType() }
|
||||
}
|
||||
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_MAC_fetch
|
||||
predicate macAlgorithmSink(string funcName, int argInd){
|
||||
(funcName = "EVP_MAC_fetch" and argInd = 1)
|
||||
predicate macAlgorithmSink(string funcName, int argInd) {
|
||||
(funcName = "EVP_MAC_fetch" and argInd = 1)
|
||||
}
|
||||
|
||||
class MACAlgorithmSink extends AlgorithmSinkArgument {
|
||||
MACAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
macAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
MACAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
macAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = "TBD" }
|
||||
override string algType() { result = "TBD" }
|
||||
}
|
||||
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_MD_fetch
|
||||
predicate messageDigestAlgorithmSink(string funcName, int argInd){
|
||||
(funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0)
|
||||
or
|
||||
funcName = "EVP_MD_fetch" and argInd = 1
|
||||
predicate messageDigestAlgorithmSink(string funcName, int argInd) {
|
||||
funcName in ["EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"] and argInd = 0
|
||||
or
|
||||
funcName = "EVP_MD_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class MessageDigestAlgorithmSink extends AlgorithmSinkArgument {
|
||||
MessageDigestAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
messageDigestAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
MessageDigestAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
messageDigestAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getHashType() }
|
||||
override string algType() { result = getHashType() }
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_KEYEXCH_fetch
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_KEM_fetch
|
||||
predicate keyExchangeAlgorithmSink(string funcName, int argInd){
|
||||
funcName = "EVP_KEYEXCH_fetch" and argInd = 1
|
||||
or
|
||||
funcName = "EVP_KEM_fetch" and argInd = 1
|
||||
predicate keyExchangeAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_KEYEXCH_fetch" and argInd = 1
|
||||
or
|
||||
funcName = "EVP_KEM_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class KeyExchangeAlgorithmSink extends AlgorithmSinkArgument {
|
||||
KeyExchangeAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
keyExchangeAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
KeyExchangeAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
keyExchangeAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getKeyExchangeType() }
|
||||
override string algType() { result = getKeyExchangeType() }
|
||||
}
|
||||
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_KEYMGMT_fetch
|
||||
predicate keyManagementAlgorithmSink(string funcName, int argInd){
|
||||
funcName = "EVP_KEYMGMT_fetch" and argInd = 1
|
||||
predicate keyManagementAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_KEYMGMT_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class KeyManagementAlgorithmSink extends AlgorithmSinkArgument {
|
||||
KeyManagementAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
keyManagementAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
KeyManagementAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
keyManagementAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = "TBD" }
|
||||
override string algType() { result = "TBD" }
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_KDF
|
||||
predicate keyDerivationAlgorithmSink(string funcName, int argInd){
|
||||
funcName = "EVP_KDF_fetch" and argInd = 1
|
||||
predicate keyDerivationAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_KDF_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class KeyDerivationAlgorithmSink extends AlgorithmSinkArgument {
|
||||
KeyDerivationAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
keyDerivationAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
KeyDerivationAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
keyDerivationAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getKeyDerivationType() }
|
||||
override string algType() { result = getKeyDerivationType() }
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_ASYM_CIPHER_fetch
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new_CMAC_key.html
|
||||
predicate asymmetricCipherAlgorithmSink(string funcName, int argInd){
|
||||
(funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1)
|
||||
or
|
||||
(funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3)
|
||||
// NOTE: other cases are handled by AsymmetricAlgorithmSink
|
||||
predicate asymmetricCipherAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_ASYM_CIPHER_fetch" and argInd = 1
|
||||
or
|
||||
funcName = "EVP_PKEY_new_CMAC_key" and argInd = 3
|
||||
// NOTE: other cases are handled by AsymmetricAlgorithmSink
|
||||
}
|
||||
|
||||
class AsymmetricCipherAlgorithmSink extends AlgorithmSinkArgument {
|
||||
AsymmetricCipherAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
asymmetricCipherAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
AsymmetricCipherAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
asymmetricCipherAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = "ASYMMETRIC_ENCRYPTION"}
|
||||
override string algType() { result = "ASYMMETRIC_ENCRYPTION" }
|
||||
}
|
||||
|
||||
class AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
|
||||
AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(3) |
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType
|
||||
)
|
||||
}
|
||||
AsymmetricCipherAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(3)
|
||||
|
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
c.getArgument(3).getType().getUnderlyingType() instanceof IntegralType
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = "ASYMMETRIC_ENCRYPTION"}
|
||||
override string algType() { result = "ASYMMETRIC_ENCRYPTION" }
|
||||
}
|
||||
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch
|
||||
predicate randomAlgorithmSink(string funcName, int argInd){
|
||||
funcName = "EVP_RAND_fetch" and argInd = 1
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_RAND_fetch
|
||||
predicate randomAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_RAND_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class RandomAlgorithmSink extends AlgorithmSinkArgument {
|
||||
RandomAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
randomAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
RandomAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
randomAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = "TBD" }
|
||||
override string algType() { result = "TBD" }
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch
|
||||
predicate signatureAlgorithmSink(string funcName, int argInd){
|
||||
funcName = "EVP_SIGNATURE_fetch" and argInd = 1
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_SIGNATURE_fetch
|
||||
predicate signatureAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_SIGNATURE_fetch" and argInd = 1
|
||||
}
|
||||
|
||||
class SignatureAlgorithmSink extends AlgorithmSinkArgument {
|
||||
SignatureAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
signatureAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
SignatureAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
signatureAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getSignatureType() }
|
||||
override string algType() { result = getSignatureType() }
|
||||
}
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EC_KEY_new_by_curve_name.html
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html
|
||||
predicate ellipticCurveAlgorithmSink(string funcName, int argInd){
|
||||
funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0
|
||||
or
|
||||
funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2
|
||||
or
|
||||
funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1
|
||||
|
||||
predicate ellipticCurveAlgorithmSink(string funcName, int argInd) {
|
||||
funcName in ["EC_KEY_new_by_curve_name", "EVP_EC_gen"] and argInd = 0
|
||||
or
|
||||
funcName = "EC_KEY_new_by_curve_name_ex" and argInd = 2
|
||||
or
|
||||
funcName in ["EVP_PKEY_CTX_set_ec_paramgen_curve_nid"] and argInd = 1
|
||||
}
|
||||
|
||||
class EllipticCurveAlgorithmSink extends AlgorithmSinkArgument {
|
||||
EllipticCurveAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
ellipticCurveAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
EllipticCurveAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
ellipticCurveAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getEllipticCurveType() }
|
||||
override string algType() { result = getEllipticCurveType() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Special cased to address the fact that arg index 3 (zero offset based) is the curve name.
|
||||
* Special cased to address the fact that arg index 3 (zero offset based) is the curve name.
|
||||
* ASSUMPTION: if the arg ind 3 is a char* assume it is an elliptic curve
|
||||
*/
|
||||
class EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
|
||||
EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(3) |
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and
|
||||
c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType
|
||||
)
|
||||
}
|
||||
EllipticCurveAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(3)
|
||||
|
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
c.getArgument(3).getType().getUnderlyingType() instanceof PointerType and
|
||||
c.getArgument(3).getType().getUnderlyingType().stripType() instanceof CharType
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getEllipticCurveType() }
|
||||
override string algType() { result = getEllipticCurveType() }
|
||||
}
|
||||
|
||||
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_new_id.html
|
||||
// https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_new.html
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_Q_keygen.html
|
||||
// https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_ctrl.html
|
||||
predicate asymmetricAlgorithmSink(string funcName, int argInd){
|
||||
|
||||
funcName = "EVP_PKEY_CTX_new_id" and argInd = 0
|
||||
or
|
||||
funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1
|
||||
or
|
||||
funcName in ["EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key"] and argInd = 0
|
||||
or
|
||||
funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1
|
||||
|
||||
// special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs
|
||||
// funcName = "EVP_PKEY_Q_keygen" and argInd = 2
|
||||
or
|
||||
funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1
|
||||
// TODO consider void cases EVP_PKEY_new
|
||||
predicate asymmetricAlgorithmSink(string funcName, int argInd) {
|
||||
funcName = "EVP_PKEY_CTX_new_id" and argInd = 0
|
||||
or
|
||||
funcName = "EVP_PKEY_CTX_new_from_name" and argInd = 1
|
||||
or
|
||||
funcName in [
|
||||
"EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", "EVP_PKEY_new_mac_key"
|
||||
] and
|
||||
argInd = 0
|
||||
or
|
||||
funcName in ["EVP_PKEY_new_raw_private_key_ex", "EVP_PKEY_new_raw_public_key_ex"] and argInd = 1
|
||||
or
|
||||
// special casing this as arg index 3 must be specified depending on if RSA or ECC, and otherwise not specified for other algs
|
||||
// funcName = "EVP_PKEY_Q_keygen" and argInd = 2
|
||||
funcName in ["EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"] and argInd = 1
|
||||
// TODO consider void cases EVP_PKEY_new
|
||||
}
|
||||
|
||||
class AsymmetricAlgorithmSink extends AlgorithmSinkArgument {
|
||||
AsymmetricAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd | funcName = c.getTarget().getName() and this = c.getArgument(argInd) |
|
||||
asymmetricAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
AsymmetricAlgorithmSink() {
|
||||
exists(Call c, string funcName, int argInd |
|
||||
funcName = c.getTarget().getName() and this = c.getArgument(argInd)
|
||||
|
|
||||
asymmetricAlgorithmSink(funcName, argInd)
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getAsymmetricType() }
|
||||
override string algType() { result = getAsymmetricType() }
|
||||
}
|
||||
|
||||
class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
|
||||
AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(2)
|
||||
|
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
not exists(c.getArgument(3))
|
||||
)
|
||||
}
|
||||
|
||||
class AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen extends AlgorithmSinkArgument {
|
||||
AsymmetricAlgorithmSink_EVP_PKEY_Q_keygen() {
|
||||
exists(Call c, string funcName |
|
||||
funcName = c.getTarget().getName() and
|
||||
this = c.getArgument(2) |
|
||||
funcName = "EVP_PKEY_Q_keygen" and
|
||||
not exists(c.getArgument(3))
|
||||
)
|
||||
}
|
||||
|
||||
override string algType() { result = getAsymmetricType() }
|
||||
override string algType() { result = getAsymmetricType() }
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,37 +2,33 @@ import cpp
|
||||
import experimental.cryptography.utils.OpenSSL.LibraryFunction
|
||||
import experimental.cryptography.CryptoAlgorithmNames
|
||||
|
||||
predicate inferredOpenSSLCryptoFunctionCall(Call c , string normalized, string algType){
|
||||
inferredOpenSSLCryptoFunction(c.getTarget(), normalized, algType)
|
||||
predicate inferredOpenSSLCryptoFunctionCall(Call c, string normalized, string algType) {
|
||||
inferredOpenSSLCryptoFunction(c.getTarget(), normalized, algType)
|
||||
}
|
||||
|
||||
predicate inferredOpenSSLCryptoFunction(Function f, string normalized, string algType){
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
normalizeFunctionName(f, algType) = normalized
|
||||
predicate inferredOpenSSLCryptoFunction(Function f, string normalized, string algType) {
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
normalizeFunctionName(f, algType) = normalized
|
||||
}
|
||||
|
||||
|
||||
predicate isOpenSSLCryptoFunction(Function f, string normalized, string algType){
|
||||
// NOTE: relying on inference as there are thousands of functions for crypto
|
||||
// enumerating them all and maintaining the list seems problematic.
|
||||
// For now, we will rely on dynamically inferring algorithms for function names.
|
||||
// This has been seen to be reasonably efficient and accurate.
|
||||
inferredOpenSSLCryptoFunction(f, normalized, algType)
|
||||
predicate isOpenSSLCryptoFunction(Function f, string normalized, string algType) {
|
||||
// NOTE: relying on inference as there are thousands of functions for crypto
|
||||
// enumerating them all and maintaining the list seems problematic.
|
||||
// For now, we will rely on dynamically inferring algorithms for function names.
|
||||
// This has been seen to be reasonably efficient and accurate.
|
||||
inferredOpenSSLCryptoFunction(f, normalized, algType)
|
||||
}
|
||||
|
||||
predicate isOpenSSLCryptoFunctionCall(Call c, string normalized, string algType){
|
||||
isOpenSSLCryptoFunction(c.getTarget(), normalized, algType)
|
||||
predicate isOpenSSLCryptoFunctionCall(Call c, string normalized, string algType) {
|
||||
isOpenSSLCryptoFunction(c.getTarget(), normalized, algType)
|
||||
}
|
||||
|
||||
|
||||
private string basicNormalizeFunctionName(Function f, string algType) {
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
isKnownAlgorithm(result, algType) and
|
||||
exists(string normStr |
|
||||
normStr = f.getName().toUpperCase().regexpReplaceAll("[-_ ]|/", "")
|
||||
|
|
||||
normStr.matches("%" + result + "%")
|
||||
)
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
isKnownAlgorithm(result, algType) and
|
||||
exists(string normStr | normStr = f.getName().toUpperCase().regexpReplaceAll("[-_ ]|/", "") |
|
||||
normStr.matches("%" + result + "%")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,71 +38,84 @@ private string basicNormalizeFunctionName(Function f, string algType) {
|
||||
* string (max in terms of string length) e.g., matching AES128 to AES128 and not simply AES.
|
||||
*
|
||||
* An unknown algorithm is only identified if there exists no known algorithm found for any algorithm type.
|
||||
*
|
||||
* `f` is the function name to normalize.
|
||||
*
|
||||
* `f` is the function name to normalize.
|
||||
* `algType` is a string representing the classification of the algorithm (see `CryptoAlgorithmNames`)
|
||||
*/
|
||||
private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
(
|
||||
result = basicNormalizeFunctionName(f, algType)
|
||||
) and
|
||||
not exists(string res2 |
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
result = basicNormalizeFunctionName(f, algType) and
|
||||
not exists(string res2 |
|
||||
result != res2 and
|
||||
res2 = basicNormalizeFunctionName(f, algType) and
|
||||
res2.length() > result.length()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a function name to a known algorithm name, similar to `normalizeName`.
|
||||
* A function is not, however, allowed to be UNKNOWN. The function either
|
||||
* normalizes to a known algorithm name, or the predicate does not hold (no result).
|
||||
*
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
*/
|
||||
private string normalizeFunctionName(Function f, string algType) {
|
||||
algType != "UNKNOWN" and
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
result = privateNormalizeFunctionName(f, algType) and
|
||||
// Addressing false positives
|
||||
// For algorithm names less than or equal to 4, we must see the algorithm name
|
||||
// in the original function as upper case (it can't be split between tokens)
|
||||
// One exception found is DES_xcbc_encrypt, this is DESX
|
||||
((result.length() <= 4 and result != "DESX") implies (f.getName().toUpperCase().matches("%" + result + "%")))
|
||||
and
|
||||
((result.length() <= 4 and result = "DESX") implies (f.getName().toUpperCase().matches("%DESX%") or f.getName().toUpperCase().matches("%DES_X%")))
|
||||
and
|
||||
// (result.length() <= 3 implies (not f.getName().toUpperCase().regexpMatch(".*" + result + "[a-zA-Z0-9].*|.*[a-zA-Z0-9]" + result + ".*")))
|
||||
// and
|
||||
// DES specific false positives
|
||||
(result.matches("DES") implies (not f.getName().toUpperCase().regexpMatch(".*DES[a-zA-Z0-9].*|.*[a-zA-Z0-9]DES.*")))
|
||||
and
|
||||
// ((result.matches("%DES%")) implies not exists(string s | s in ["DESCRIBE", "DESTROY", "DESCRIPTION", "DESCRIPTOR", "NODES"] |
|
||||
// f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// SEED specific false positives
|
||||
((result.matches("SEED")) implies not exists(string s | s in ["SEED_SRC_GENERATE", "RAND","NEW_SEED", "GEN_SEED", "SEED_GEN", "SET_SEED", "GET_SEED", "GET0_SEED", "RESEED", "SEEDING"] |
|
||||
f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// ARIA specific false positives
|
||||
((result.matches("ARIA")) implies not f.getName().toUpperCase().matches("%VARIANT%")) and
|
||||
// CTR false positives
|
||||
((result.matches("CTR") implies not f.getName().toUpperCase().matches("%CTRL%"))) and
|
||||
// ES false positives (e.g., ES256 from AES256)
|
||||
((result.matches("ES%")) implies not f.getName().toUpperCase().matches("%AES%")) and
|
||||
// RSA false positives
|
||||
(((result.matches("RSA")) implies not f.getName().toUpperCase().matches("%UNIVERSAL%")))
|
||||
and
|
||||
//rsaz functions deemed to be too low level, and can be ignored
|
||||
not f.getLocation().getFile().getBaseName().matches("rsaz_exp.c") and
|
||||
// General False positives
|
||||
// Functions that 'get' do not set an algorithm, and therefore are considered ignorable
|
||||
not f.getName().toLowerCase().matches("%get%")
|
||||
algType != "UNKNOWN" and
|
||||
isPossibleOpenSSLFunction(f) and
|
||||
result = privateNormalizeFunctionName(f, algType) and
|
||||
// Addressing false positives
|
||||
// For algorithm names less than or equal to 4, we must see the algorithm name
|
||||
// in the original function as upper case (it can't be split between tokens)
|
||||
// One exception found is DES_xcbc_encrypt, this is DESX
|
||||
(
|
||||
(result.length() <= 4 and result != "DESX")
|
||||
implies
|
||||
f.getName().toUpperCase().matches("%" + result + "%")
|
||||
) and
|
||||
(
|
||||
(result.length() <= 4 and result = "DESX")
|
||||
implies
|
||||
(f.getName().toUpperCase().matches("%DESX%") or f.getName().toUpperCase().matches("%DES_X%"))
|
||||
) and
|
||||
// (result.length() <= 3 implies (not f.getName().toUpperCase().regexpMatch(".*" + result + "[a-zA-Z0-9].*|.*[a-zA-Z0-9]" + result + ".*")))
|
||||
// and
|
||||
// DES specific false positives
|
||||
(
|
||||
result.matches("DES")
|
||||
implies
|
||||
not f.getName().toUpperCase().regexpMatch(".*DES[a-zA-Z0-9].*|.*[a-zA-Z0-9]DES.*")
|
||||
) and
|
||||
// ((result.matches("%DES%")) implies not exists(string s | s in ["DESCRIBE", "DESTROY", "DESCRIPTION", "DESCRIPTOR", "NODES"] |
|
||||
// f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// SEED specific false positives
|
||||
(
|
||||
result.matches("SEED")
|
||||
implies
|
||||
not exists(string s |
|
||||
s in [
|
||||
"SEED_SRC_GENERATE", "RAND", "NEW_SEED", "GEN_SEED", "SEED_GEN", "SET_SEED", "GET_SEED",
|
||||
"GET0_SEED", "RESEED", "SEEDING"
|
||||
]
|
||||
|
|
||||
f.getName().toUpperCase().matches("%" + s + "%")
|
||||
)
|
||||
) and
|
||||
// ARIA specific false positives
|
||||
(result.matches("ARIA") implies not f.getName().toUpperCase().matches("%VARIANT%")) and
|
||||
// CTR false positives
|
||||
(result.matches("CTR") implies not f.getName().toUpperCase().matches("%CTRL%")) and
|
||||
// ES false positives (e.g., ES256 from AES256)
|
||||
(result.matches("ES%") implies not f.getName().toUpperCase().matches("%AES%")) and
|
||||
// RSA false positives
|
||||
(result.matches("RSA") implies not f.getName().toUpperCase().matches("%UNIVERSAL%")) and
|
||||
//rsaz functions deemed to be too low level, and can be ignored
|
||||
not f.getLocation().getFile().getBaseName().matches("rsaz_exp.c") and
|
||||
// General False positives
|
||||
// Functions that 'get' do not set an algorithm, and therefore are considered ignorable
|
||||
not f.getName().toLowerCase().matches("%get%")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/**
|
||||
* This file contains predicates create to build up initial data sets for OpenSSL
|
||||
* predicates. E.g., These predicates were used to assist in associating all
|
||||
* openSSL functions with their known crypto algorithms.
|
||||
* openSSL functions with their known crypto algorithms.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import experimental.cryptography.CryptoAlgorithmNames
|
||||
import experimental.cryptography.utils.OpenSSL.CryptoFunction
|
||||
|
||||
|
||||
private string basicNormalizeFunctionName(Function f, string algType) {
|
||||
isKnownAlgorithm(result, algType) and
|
||||
exists(string normStr |
|
||||
normStr = f.getName().toUpperCase().regexpReplaceAll("[-_ ]|/", "")
|
||||
|
|
||||
normStr.matches("%" + result + "%")
|
||||
)
|
||||
isKnownAlgorithm(result, algType) and
|
||||
exists(string normStr | normStr = f.getName().toUpperCase().regexpReplaceAll("[-_ ]|/", "") |
|
||||
normStr.matches("%" + result + "%")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,14 +22,12 @@ private string basicNormalizeFunctionName(Function f, string algType) {
|
||||
* string (max in terms of string length) e.g., matching AES128 to AES128 and not simply AES.
|
||||
*
|
||||
* An unknown algorithm is only identified if there exists no known algorithm found for any algorithm type.
|
||||
*
|
||||
* `f` is the function name to normalize.
|
||||
*
|
||||
* `f` is the function name to normalize.
|
||||
* `algType` is a string representing the classification of the algorithm (see `CryptoAlgorithmNames`)
|
||||
*/
|
||||
private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
(
|
||||
result = basicNormalizeFunctionName(f, algType)
|
||||
) and
|
||||
result = basicNormalizeFunctionName(f, algType) and
|
||||
not exists(string res2 |
|
||||
result != res2 and
|
||||
res2 = basicNormalizeFunctionName(f, algType) and
|
||||
@@ -40,56 +35,74 @@ private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
) and
|
||||
// Addressing bad normalization case-by-case
|
||||
// CASE: ES256 being identified when the algorithm is AES256
|
||||
(result.matches("ES256") implies not exists(string res2 | res2 = basicNormalizeFunctionName(f, _) and res2.matches("AES%")))
|
||||
(
|
||||
result.matches("ES256")
|
||||
implies
|
||||
not exists(string res2 | res2 = basicNormalizeFunctionName(f, _) and res2.matches("AES%"))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes a function name to a known algorithm name, similar to `normalizeName`.
|
||||
* A function is not, however, allowed to be UNKNOWN. The function either
|
||||
* normalizes to a known algorithm name, or the predicate does not hold (no result).
|
||||
*
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
*/
|
||||
string normalizeFunctionName(Function f, string algType) {
|
||||
algType != "UNKNOWN" and
|
||||
result = privateNormalizeFunctionName(f, algType) and
|
||||
openSSLLibraryFunc(f) and
|
||||
// Addressing false positives
|
||||
// For algorithm names less than or equal to 4, we must see the algorithm name
|
||||
// in the original function as upper case (it can't be split between tokens)
|
||||
// One exception found is DES_xcbc_encrypt, this is DESX
|
||||
((result.length() <= 4 and result != "DESX") implies (f.getName().toUpperCase().matches("%" + result + "%")))
|
||||
and
|
||||
((result.length() <= 4 and result = "DESX") implies (f.getName().toUpperCase().matches("%DESX%") or f.getName().toUpperCase().matches("%DES_X%")))
|
||||
and
|
||||
// (result.length() <= 3 implies (not f.getName().toUpperCase().regexpMatch(".*" + result + "[a-zA-Z0-9].*|.*[a-zA-Z0-9]" + result + ".*")))
|
||||
// and
|
||||
// DES specific false positives
|
||||
(result.matches("DES") implies (not f.getName().toUpperCase().regexpMatch(".*DES[a-zA-Z0-9].*|.*[a-zA-Z0-9]DES.*")))
|
||||
and
|
||||
// ((result.matches("%DES%")) implies not exists(string s | s in ["DESCRIBE", "DESTROY", "DESCRIPTION", "DESCRIPTOR", "NODES"] |
|
||||
// f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// SEED specific false positives
|
||||
((result.matches("%SEED%")) implies not not exists(string s | s in ["NEW_SEED", "GEN_SEED", "SET_SEED", "GET_SEED", "GET0_SEED", "RESEED", "SEEDING"] |
|
||||
f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// ARIA specific false positives
|
||||
((result.matches("%ARIA%")) implies not f.getName().toUpperCase().matches("%VARIANT%"))
|
||||
algType != "UNKNOWN" and
|
||||
result = privateNormalizeFunctionName(f, algType) and
|
||||
openSSLLibraryFunc(f) and
|
||||
// Addressing false positives
|
||||
// For algorithm names less than or equal to 4, we must see the algorithm name
|
||||
// in the original function as upper case (it can't be split between tokens)
|
||||
// One exception found is DES_xcbc_encrypt, this is DESX
|
||||
(
|
||||
(result.length() <= 4 and result != "DESX")
|
||||
implies
|
||||
f.getName().toUpperCase().matches("%" + result + "%")
|
||||
) and
|
||||
(
|
||||
(result.length() <= 4 and result = "DESX")
|
||||
implies
|
||||
(f.getName().toUpperCase().matches("%DESX%") or f.getName().toUpperCase().matches("%DES_X%"))
|
||||
) and
|
||||
// (result.length() <= 3 implies (not f.getName().toUpperCase().regexpMatch(".*" + result + "[a-zA-Z0-9].*|.*[a-zA-Z0-9]" + result + ".*")))
|
||||
// and
|
||||
// DES specific false positives
|
||||
(
|
||||
result.matches("DES")
|
||||
implies
|
||||
not f.getName().toUpperCase().regexpMatch(".*DES[a-zA-Z0-9].*|.*[a-zA-Z0-9]DES.*")
|
||||
) and
|
||||
// ((result.matches("%DES%")) implies not exists(string s | s in ["DESCRIBE", "DESTROY", "DESCRIPTION", "DESCRIPTOR", "NODES"] |
|
||||
// f.getName().toUpperCase().matches("%" + s + "%"))) and
|
||||
// SEED specific false positives
|
||||
(
|
||||
result.matches("%SEED%")
|
||||
implies
|
||||
not not exists(string s |
|
||||
s in ["NEW_SEED", "GEN_SEED", "SET_SEED", "GET_SEED", "GET0_SEED", "RESEED", "SEEDING"]
|
||||
|
|
||||
f.getName().toUpperCase().matches("%" + s + "%")
|
||||
)
|
||||
) and
|
||||
// ARIA specific false positives
|
||||
(result.matches("%ARIA%") implies not f.getName().toUpperCase().matches("%VARIANT%"))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate to support name normalization.
|
||||
* Converts the raw name upper-case with no hyphen, slash, underscore, hash, or space.
|
||||
* Looks for substrings that are known algorithms, and normalizes the name.
|
||||
* If the algorithm cannot be determined or is in the ignorable list (`isIgnorableOpenSSLAlgorithm`)
|
||||
* this predicate will not resolve a name.
|
||||
*
|
||||
* this predicate will not resolve a name.
|
||||
*
|
||||
* Rationale for private: For normalization, we want to get the longest string for a normalized name match
|
||||
* for a given algorithm type. I found this easier to express if the public normalizeName
|
||||
* checks that the name is the longest, and that UNKNOWN is reserved if there exists no
|
||||
@@ -100,14 +113,11 @@ string privateNormalizeName(string name, string algType) {
|
||||
//not isIgnorableOpenSSLAlgorithm(name, _, _) and
|
||||
// targetOpenSSLAlgorithm(name, _) and
|
||||
isKnownAlgorithm(result, algType) and
|
||||
exists(string normStr |
|
||||
normStr = name.toUpperCase().regexpReplaceAll("[-_ ]|/", "")
|
||||
|
|
||||
exists(string normStr | normStr = name.toUpperCase().regexpReplaceAll("[-_ ]|/", "") |
|
||||
normStr.matches("%" + result + "%")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a raw OpenSSL algorithm to a normalized algorithm name.
|
||||
*
|
||||
@@ -115,8 +125,8 @@ string privateNormalizeName(string name, string algType) {
|
||||
* string (max in terms of string length) e.g., matching AES128 to AES128 and not simply AES.
|
||||
*
|
||||
* An unknown algorithm is only identified if there exists no known algorithm found for any algorithm type.
|
||||
*
|
||||
* `name` is the name to normalize.
|
||||
*
|
||||
* `name` is the name to normalize.
|
||||
* `algType` is a string representing the classification of the algorithm (see `CryptoAlgorithmNames`)
|
||||
*/
|
||||
bindingset[name]
|
||||
@@ -135,5 +145,9 @@ string normalizeName(string name, string algType) {
|
||||
) and
|
||||
// Addressing bad normalization case-by-case
|
||||
// CASE: ES256 being identified when the algorithm is AES256
|
||||
(result.matches("ES256") implies not exists(string res2 | res2 = privateNormalizeName(name, _) and res2.matches("AES%")))
|
||||
(
|
||||
result.matches("ES256")
|
||||
implies
|
||||
not exists(string res2 | res2 = privateNormalizeName(name, _) and res2.matches("AES%"))
|
||||
)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,60 +1,59 @@
|
||||
import cpp
|
||||
import cpp
|
||||
import experimental.cryptography.utils.OpenSSL.LibraryFunction
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
|
||||
|
||||
// TODO: possible use of extensible predicates here
|
||||
// NOTE: -1 for outInd represents the return value
|
||||
predicate knownPassthroughFunction(Function f, int inInd, int outInd){
|
||||
// Trace through functions
|
||||
// See https://www.openssl.org/docs/man1.1.1/man3/OBJ_obj2txt
|
||||
// https://www.openssl.org/docs/man3.0/man3/EVP_CIPHER_get0_name
|
||||
openSSLLibraryFunc(f)
|
||||
and
|
||||
(
|
||||
(
|
||||
f.getName() in [
|
||||
"OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn",
|
||||
"OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid",
|
||||
"OBJ_txt2nid","OBJ_txt2obj", "OBJ_dup",
|
||||
"EVP_CIPHER_get0_name"]
|
||||
and inInd = 0 and outInd = -1)
|
||||
or
|
||||
(
|
||||
f.getName() in ["OBJ_obj2txt","i2t_ASN1_OBJECT"] and
|
||||
inInd = 2 and outInd = 0
|
||||
)
|
||||
or
|
||||
// Dup/copy pattern occurs in more places,
|
||||
//see: https://www.openssl.org/docs/manmaster/man3/EC_KEY_copy.html and https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_dup.html
|
||||
f.getName().matches("%_dup") and inInd = 0 and outInd = -1
|
||||
or
|
||||
f.getName().matches("%_copy") and inInd = 0 and outInd = -1
|
||||
)
|
||||
predicate knownPassthroughFunction(Function f, int inInd, int outInd) {
|
||||
// Trace through functions
|
||||
// See https://www.openssl.org/docs/man1.1.1/man3/OBJ_obj2txt
|
||||
// https://www.openssl.org/docs/man3.0/man3/EVP_CIPHER_get0_name
|
||||
openSSLLibraryFunc(f) and
|
||||
(
|
||||
f.getName() in [
|
||||
"OBJ_nid2obj", "OBJ_nid2ln", "OBJ_nid2sn", "OBJ_obj2nid", "OBJ_ln2nid", "OBJ_sn2nid",
|
||||
"OBJ_txt2nid", "OBJ_txt2obj", "OBJ_dup", "EVP_CIPHER_get0_name"
|
||||
] and
|
||||
inInd = 0 and
|
||||
outInd = -1
|
||||
or
|
||||
f.getName() in ["OBJ_obj2txt", "i2t_ASN1_OBJECT"] and
|
||||
inInd = 2 and
|
||||
outInd = 0
|
||||
or
|
||||
// Dup/copy pattern occurs in more places,
|
||||
//see: https://www.openssl.org/docs/manmaster/man3/EC_KEY_copy.html and https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_dup.html
|
||||
f.getName().matches("%_dup") and inInd = 0 and outInd = -1
|
||||
or
|
||||
f.getName().matches("%_copy") and inInd = 0 and outInd = -1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* `c` is a call to a function that preserves the algorithm but changes its form.
|
||||
* `c` is a call to a function that preserves the algorithm but changes its form.
|
||||
* `onExpr` is the input argument passing through to, `outExpr` is the next expression in a dataflow step associated with `c`
|
||||
*/
|
||||
predicate knownPassthoughCall(Call c, Expr inExpr, Expr outExpr){
|
||||
exists(int inInd, int outInd |
|
||||
knownPassthroughFunction(c.getTarget(), inInd, outInd) and
|
||||
inExpr = c.getArgument(inInd) and
|
||||
if(outInd = -1)
|
||||
then outExpr = c
|
||||
else outExpr = c.getArgument(outInd)
|
||||
)
|
||||
predicate knownPassthoughCall(Call c, Expr inExpr, Expr outExpr) {
|
||||
exists(int inInd, int outInd |
|
||||
knownPassthroughFunction(c.getTarget(), inInd, outInd) and
|
||||
inExpr = c.getArgument(inInd) and
|
||||
if outInd = -1 then outExpr = c else outExpr = c.getArgument(outInd)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly add flow through openssl functions that preserve the algorithm but alter the form (e.g., from NID to string)
|
||||
*/
|
||||
predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2){
|
||||
exists(Expr cur, Expr next |
|
||||
(cur = node1.asExpr() or cur = node1.asIndirectArgument()) and
|
||||
(next = node2.asExpr() or next = node2.asIndirectArgument() or next = node2.asDefiningArgument())
|
||||
|
|
||||
exists(Call c | knownPassthoughCall(c, cur, next)))
|
||||
}
|
||||
* Explicitly add flow through openssl functions that preserve the algorithm but alter the form (e.g., from NID to string)
|
||||
*/
|
||||
|
||||
predicate knownPassThroughStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(Expr cur, Expr next |
|
||||
(cur = node1.asExpr() or cur = node1.asIndirectArgument()) and
|
||||
(
|
||||
next = node2.asExpr() or
|
||||
next = node2.asIndirectArgument() or
|
||||
next = node2.asDefiningArgument()
|
||||
)
|
||||
|
|
||||
exists(Call c | knownPassthoughCall(c, cur, next))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
/**
|
||||
* @name Unknown key generation key size
|
||||
* @description
|
||||
* @description
|
||||
* @id cpp/unknown-asymmetric-key-gen-size
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags external/cwe/cwe-326
|
||||
*/
|
||||
import cpp
|
||||
|
||||
import cpp
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
from AsymmetricKeyGeneration op, AsymmetricAlgorithm alg
|
||||
where
|
||||
alg = op.getAlgorithm() and
|
||||
not alg instanceof EllipticCurveAlgorithm and
|
||||
not exists(op.getKeySizeInBits(alg))
|
||||
where
|
||||
alg = op.getAlgorithm() and
|
||||
not alg instanceof EllipticCurveAlgorithm and
|
||||
not exists(op.getKeySizeInBits(alg))
|
||||
select op, "Use of unknown asymmetric key size for algorithm $@", alg, alg.getName().toString()
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/**
|
||||
* @name Weak asymmetric key generation key size (< 2048 bits)
|
||||
* @description
|
||||
* @description
|
||||
* @id cpp/weak-asymmetric-key-gen-size
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags external/cwe/cwe-326
|
||||
*/
|
||||
import cpp
|
||||
|
||||
import cpp
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
from AsymmetricKeyGeneration op, AsymmetricAlgorithm alg, Expr configSrc, int size
|
||||
where
|
||||
alg = op.getAlgorithm() and
|
||||
not alg instanceof EllipticCurveAlgorithm and
|
||||
configSrc = op.getKeyConfigurationSource(alg) and
|
||||
size = configSrc.getValue().toInt() and
|
||||
size < 2048
|
||||
select op, "Use of weak asymmetric key size (in bits) " + size + " configured at $@ for algorithm $@", configSrc, configSrc.toString(), alg, alg.getName().toString()
|
||||
where
|
||||
alg = op.getAlgorithm() and
|
||||
not alg instanceof EllipticCurveAlgorithm and
|
||||
configSrc = op.getKeyConfigurationSource(alg) and
|
||||
size = configSrc.getValue().toInt() and
|
||||
size < 2048
|
||||
select op,
|
||||
"Use of weak asymmetric key size (in bits) " + size + " configured at $@ for algorithm $@",
|
||||
configSrc, configSrc.toString(), alg, alg.getName().toString()
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
/**
|
||||
* @name Weak block mode
|
||||
* @description Finds uses of symmetric encryption block modes that are weak, obsolete, or otherwise unaccepted.
|
||||
* @id cpp/weak-block-mode
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags external/cwe/cwe-327
|
||||
*/
|
||||
/**
|
||||
* @name Weak block mode
|
||||
* @description Finds uses of symmetric encryption block modes that are weak, obsolete, or otherwise unaccepted.
|
||||
* @id cpp/weak-block-mode
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags external/cwe/cwe-327
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
from BlockModeAlgorithm alg, string name, string msg, Expr confSink
|
||||
where
|
||||
exists(string tmpMsg |
|
||||
exists(string tmpMsg |
|
||||
(
|
||||
(name = alg.getBlockModeName() and name = unknownAlgorithm() and tmpMsg = "Use of unrecognized block mode algorithm.")
|
||||
or
|
||||
(
|
||||
name != unknownAlgorithm() and
|
||||
name = alg.getBlockModeName() and
|
||||
not name = ["CBC","CTS","XTS"] and
|
||||
tmpMsg = "Use of weak block mode algorithm " + name + "."
|
||||
)
|
||||
)
|
||||
and
|
||||
name = alg.getBlockModeName() and
|
||||
name = unknownAlgorithm() and
|
||||
tmpMsg = "Use of unrecognized block mode algorithm."
|
||||
or
|
||||
name != unknownAlgorithm() and
|
||||
name = alg.getBlockModeName() and
|
||||
not name = ["CBC", "CTS", "XTS"] and
|
||||
tmpMsg = "Use of weak block mode algorithm " + name + "."
|
||||
) and
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (confSink = alg.configurationSink() and msg = tmpMsg + " Algorithm used at sink: $@.")
|
||||
else (confSink = alg and msg = tmpMsg)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
then (
|
||||
confSink = alg.configurationSink() and msg = tmpMsg + " Algorithm used at sink: $@."
|
||||
) else (
|
||||
confSink = alg and msg = tmpMsg
|
||||
)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
|
||||
@@ -7,28 +7,34 @@
|
||||
* @precision high
|
||||
* @tags external/cwe/cwe-327
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
from EllipticCurveAlgorithm alg, string name, string msg, Expr confSink
|
||||
where
|
||||
exists(string tmpMsg |
|
||||
exists(string tmpMsg |
|
||||
(
|
||||
(name = alg.getCurveName() and name = unknownAlgorithm() and tmpMsg = "Use of unrecognized curve algorithm.")
|
||||
or
|
||||
(
|
||||
name != unknownAlgorithm() and
|
||||
name = alg.getCurveName() and
|
||||
not name = ["SECP256R1", "PRIME256V1",//P-256
|
||||
"SECP384R1", //P-384
|
||||
"SECP521R1", //P-521
|
||||
"ED25519", "X25519"] and
|
||||
tmpMsg = "Use of weak curve algorithm " + name + "."
|
||||
)
|
||||
)
|
||||
and
|
||||
name = alg.getCurveName() and
|
||||
name = unknownAlgorithm() and
|
||||
tmpMsg = "Use of unrecognized curve algorithm."
|
||||
or
|
||||
name != unknownAlgorithm() and
|
||||
name = alg.getCurveName() and
|
||||
not name =
|
||||
[
|
||||
"SECP256R1", "PRIME256V1", //P-256
|
||||
"SECP384R1", //P-384
|
||||
"SECP521R1", //P-521
|
||||
"ED25519", "X25519"
|
||||
] and
|
||||
tmpMsg = "Use of weak curve algorithm " + name + "."
|
||||
) and
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (confSink = alg.configurationSink() and msg = tmpMsg + " Algorithm used at sink: $@.")
|
||||
else (confSink = alg and msg = tmpMsg)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
then (
|
||||
confSink = alg.configurationSink() and msg = tmpMsg + " Algorithm used at sink: $@."
|
||||
) else (
|
||||
confSink = alg and msg = tmpMsg
|
||||
)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
|
||||
@@ -11,24 +11,31 @@
|
||||
import cpp
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
|
||||
from SymmetricEncryptionAlgorithm alg, Expr confSink, string msg
|
||||
where
|
||||
exists (string resMsg |
|
||||
(
|
||||
if alg.getEncryptionName() = unknownAlgorithm()
|
||||
then (
|
||||
alg instanceof Literal and resMsg = "Use of unrecognized symmetric encryption algorithm: " + alg.(Literal).getValueText().toString() + "."
|
||||
or
|
||||
not alg instanceof Literal and resMsg = "Use of unrecognized symmetric encryption algorithm."
|
||||
where
|
||||
exists(string resMsg |
|
||||
(
|
||||
if alg.getEncryptionName() = unknownAlgorithm()
|
||||
then (
|
||||
alg instanceof Literal and
|
||||
resMsg =
|
||||
"Use of unrecognized symmetric encryption algorithm: " +
|
||||
alg.(Literal).getValueText().toString() + "."
|
||||
or
|
||||
not alg instanceof Literal and
|
||||
resMsg = "Use of unrecognized symmetric encryption algorithm."
|
||||
) else (
|
||||
not alg.getEncryptionName().matches("AES%") and
|
||||
resMsg = "Use of banned symmetric encryption algorithm: " + alg.getEncryptionName() + "."
|
||||
)
|
||||
) and
|
||||
(
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (
|
||||
confSink = alg.configurationSink() and msg = resMsg + " Algorithm used at sink: $@."
|
||||
) else (
|
||||
confSink = alg and msg = resMsg
|
||||
)
|
||||
)
|
||||
else (not alg.getEncryptionName().matches("AES%") and resMsg = "Use of banned symmetric encryption algorithm: " + alg.getEncryptionName() + ".")
|
||||
)
|
||||
and
|
||||
(
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (confSink = alg.configurationSink() and msg = resMsg + " Algorithm used at sink: $@.")
|
||||
else (confSink = alg and msg = resMsg)
|
||||
)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @name Weak cryptography
|
||||
* @description Finds explicit uses of cryptographic hash algorithms that are weak and obsolete.
|
||||
* @description Finds explicit uses of cryptographic hash algorithms that are weak and obsolete.
|
||||
* @kind problem
|
||||
* @id cpp/weak-crypto/banned-hash-algorithms
|
||||
* @problem.severity error
|
||||
@@ -11,25 +11,26 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow as ASTDataFlow
|
||||
import experimental.cryptography.Concepts
|
||||
|
||||
from HashAlgorithm alg, Expr confSink, string msg
|
||||
where
|
||||
exists(string name, string msgTmp | name = alg.getHashName() |
|
||||
not name = ["SHA256", "SHA384", "SHA512"] and
|
||||
(
|
||||
if name = unknownAlgorithm()
|
||||
then
|
||||
(
|
||||
not alg instanceof Literal and msgTmp = "Use of unrecognized hash algorithm."
|
||||
or
|
||||
alg instanceof Literal and msgTmp = "Use of unrecognized hash algorithm: " + alg.(Literal).getValueText().toString() + "."
|
||||
|
||||
)
|
||||
else msgTmp = "Use of banned hash algorithm " + name + "."
|
||||
)
|
||||
and
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (confSink = alg.configurationSink() and msg = msgTmp + " Algorithm used at sink: $@.")
|
||||
else (confSink = alg and msg = msgTmp)
|
||||
)
|
||||
from HashAlgorithm alg, Expr confSink, string msg
|
||||
where
|
||||
exists(string name, string msgTmp | name = alg.getHashName() |
|
||||
not name = ["SHA256", "SHA384", "SHA512"] and
|
||||
(
|
||||
if name = unknownAlgorithm()
|
||||
then
|
||||
not alg instanceof Literal and msgTmp = "Use of unrecognized hash algorithm."
|
||||
or
|
||||
alg instanceof Literal and
|
||||
msgTmp =
|
||||
"Use of unrecognized hash algorithm: " + alg.(Literal).getValueText().toString() + "."
|
||||
else msgTmp = "Use of banned hash algorithm " + name + "."
|
||||
) and
|
||||
if alg.hasConfigurationSink() and alg.configurationSink() != alg
|
||||
then (
|
||||
confSink = alg.configurationSink() and msg = msgTmp + " Algorithm used at sink: $@."
|
||||
) else (
|
||||
confSink = alg and msg = msgTmp
|
||||
)
|
||||
)
|
||||
select alg, msg, confSink, confSink.toString()
|
||||
|
||||
Reference in New Issue
Block a user