From f07d8ee493179118f3bf371f88833e25db42081e Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 7 Jul 2025 11:39:12 +0200 Subject: [PATCH] Remove duplicate copies of `CryptoAlgorithms` and `CryptoAlgorithmNames` --- config/identical-files.json | 12 -- .../javascript/security/CryptoAlgorithms.qll | 114 +----------------- .../internal/CryptoAlgorithmNames.qll | 84 ------------- .../python/concepts/CryptoAlgorithms.qll | 114 +----------------- .../internal/CryptoAlgorithmNames.qll | 84 ------------- .../codeql/ruby/security/CryptoAlgorithms.qll | 114 +----------------- .../internal/CryptoAlgorithmNames.qll | 84 ------------- .../codeql/rust/security/CryptoAlgorithms.qll | 114 +----------------- .../internal/CryptoAlgorithmNames.qll | 84 ------------- 9 files changed, 4 insertions(+), 800 deletions(-) delete mode 100644 javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll delete mode 100644 python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll delete mode 100644 ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll delete mode 100644 rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll diff --git a/config/identical-files.json b/config/identical-files.json index a3da11e15e4..977f3f4a647 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -231,18 +231,6 @@ "java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp", "java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp" ], - "CryptoAlgorithms Python/JS/Ruby": [ - "javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll", - "python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll", - "ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll", - "rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll" - ], - "CryptoAlgorithmNames Python/JS/Ruby": [ - "javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll", - "python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll", - "ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll", - "rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll" - ], "IncompleteUrlSubstringSanitization": [ "javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll", "ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll" diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index 01b568d234a..f13d72312fe 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -1,117 +1,5 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). */ -private import codeql.concepts.internal.CryptoAlgorithmNames - -/** - * A cryptographic algorithm. - */ -private newtype TCryptographicAlgorithm = - MkHashingAlgorithm(string name, boolean isWeak) { - isStrongHashingAlgorithm(name) and isWeak = false - or - isWeakHashingAlgorithm(name) and isWeak = true - } or - MkEncryptionAlgorithm(string name, boolean isWeak) { - isStrongEncryptionAlgorithm(name) and isWeak = false - or - isWeakEncryptionAlgorithm(name) and isWeak = true - } or - MkPasswordHashingAlgorithm(string name, boolean isWeak) { - isStrongPasswordHashingAlgorithm(name) and isWeak = false - or - isWeakPasswordHashingAlgorithm(name) and isWeak = true - } - -/** - * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. - * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. - * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. - */ -bindingset[name] -private CryptographicAlgorithm getBestAlgorithmForName(string name) { - result = - max(CryptographicAlgorithm algorithm | - algorithm.getName() = - [ - name.toUpperCase(), // the full name - name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces - name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores - ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces - | - algorithm order by algorithm.getName().length() - ) -} - -/** - * A cryptographic algorithm. - */ -abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { result = this.getName() } - - /** - * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). - */ - abstract string getName(); - - /** - * Holds if the name of this algorithm is the most specific match for `name`. - * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. - */ - bindingset[name] - predicate matchesName(string name) { this = getBestAlgorithmForName(name) } - - /** - * Holds if this algorithm is weak. - */ - abstract predicate isWeak(); -} - -/** - * A hashing algorithm such as `MD5` or `SHA512`. - */ -class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * An encryption algorithm such as `DES` or `AES512`. - */ -class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } - - /** Holds if this algorithm is a stream cipher. */ - predicate isStreamCipher() { isStreamCipher(name) } -} - -/** - * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. - */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} +private import codeql.concepts.CryptoAlgorithms diff --git a/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll b/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll deleted file mode 100644 index 8bb63d97876..00000000000 --- a/javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Names of cryptographic algorithms, separated into strong and weak variants. - * - * The names are normalized: upper-case, no spaces, dashes or underscores. - * - * The names are inspired by the names used in real world crypto libraries. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). - */ - -/** - * Holds if `name` corresponds to a strong hashing algorithm. - */ -predicate isStrongHashingAlgorithm(string name) { - name = - [ - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 - // and https://www.blake2.net/ - "BLAKE2", "BLAKE2B", "BLAKE2S", - // see https://github.com/BLAKE3-team/BLAKE3 - "BLAKE3", - // - "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 - "SHAKE128", "SHAKE256", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 - "SM3", - // see https://security.stackexchange.com/a/216297 - "WHIRLPOOL", - ] -} - -/** - * Holds if `name` corresponds to a weak hashing algorithm. - */ -predicate isWeakHashingAlgorithm(string name) { - name = - [ - "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", - "RIPEMD320", "SHA0", "SHA1" - ] -} - -/** - * Holds if `name` corresponds to a strong encryption algorithm. - */ -predicate isStrongEncryptionAlgorithm(string name) { - name = - [ - "AES", "AES128", "AES192", "AES256", "AES512", "AES-128", "AES-192", "AES-256", "AES-512", - "ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5", "CAMELLIA", "CAMELLIA128", "CAMELLIA192", - "CAMELLIA256", "CAMELLIA-128", "CAMELLIA-192", "CAMELLIA-256", "CHACHA", "GOST", "GOST89", - "IDEA", "RABBIT", "RSA", "SEED", "SM4" - ] -} - -/** - * Holds if `name` corresponds to a weak encryption algorithm. - */ -predicate isWeakEncryptionAlgorithm(string name) { - name = - [ - "DES", "3DES", "DES3", "TRIPLEDES", "DESX", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", - "ARCFOUR", "ARC5", "RC5" - ] -} - -/** - * Holds if `name` corresponds to a strong password hashing algorithm. - */ -predicate isStrongPasswordHashingAlgorithm(string name) { - name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] -} - -/** - * Holds if `name` corresponds to a weak password hashing algorithm. - */ -predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" } - -/** - * Holds if `name` corresponds to a stream cipher. - */ -predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] } diff --git a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll index 01b568d234a..13a03a3bd88 100644 --- a/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll +++ b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll @@ -1,117 +1,5 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). */ -private import codeql.concepts.internal.CryptoAlgorithmNames - -/** - * A cryptographic algorithm. - */ -private newtype TCryptographicAlgorithm = - MkHashingAlgorithm(string name, boolean isWeak) { - isStrongHashingAlgorithm(name) and isWeak = false - or - isWeakHashingAlgorithm(name) and isWeak = true - } or - MkEncryptionAlgorithm(string name, boolean isWeak) { - isStrongEncryptionAlgorithm(name) and isWeak = false - or - isWeakEncryptionAlgorithm(name) and isWeak = true - } or - MkPasswordHashingAlgorithm(string name, boolean isWeak) { - isStrongPasswordHashingAlgorithm(name) and isWeak = false - or - isWeakPasswordHashingAlgorithm(name) and isWeak = true - } - -/** - * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. - * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. - * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. - */ -bindingset[name] -private CryptographicAlgorithm getBestAlgorithmForName(string name) { - result = - max(CryptographicAlgorithm algorithm | - algorithm.getName() = - [ - name.toUpperCase(), // the full name - name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces - name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores - ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces - | - algorithm order by algorithm.getName().length() - ) -} - -/** - * A cryptographic algorithm. - */ -abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { result = this.getName() } - - /** - * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). - */ - abstract string getName(); - - /** - * Holds if the name of this algorithm is the most specific match for `name`. - * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. - */ - bindingset[name] - predicate matchesName(string name) { this = getBestAlgorithmForName(name) } - - /** - * Holds if this algorithm is weak. - */ - abstract predicate isWeak(); -} - -/** - * A hashing algorithm such as `MD5` or `SHA512`. - */ -class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * An encryption algorithm such as `DES` or `AES512`. - */ -class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } - - /** Holds if this algorithm is a stream cipher. */ - predicate isStreamCipher() { isStreamCipher(name) } -} - -/** - * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. - */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} +import codeql.concepts.CryptoAlgorithms diff --git a/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll b/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll deleted file mode 100644 index 8bb63d97876..00000000000 --- a/python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Names of cryptographic algorithms, separated into strong and weak variants. - * - * The names are normalized: upper-case, no spaces, dashes or underscores. - * - * The names are inspired by the names used in real world crypto libraries. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). - */ - -/** - * Holds if `name` corresponds to a strong hashing algorithm. - */ -predicate isStrongHashingAlgorithm(string name) { - name = - [ - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 - // and https://www.blake2.net/ - "BLAKE2", "BLAKE2B", "BLAKE2S", - // see https://github.com/BLAKE3-team/BLAKE3 - "BLAKE3", - // - "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 - "SHAKE128", "SHAKE256", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 - "SM3", - // see https://security.stackexchange.com/a/216297 - "WHIRLPOOL", - ] -} - -/** - * Holds if `name` corresponds to a weak hashing algorithm. - */ -predicate isWeakHashingAlgorithm(string name) { - name = - [ - "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", - "RIPEMD320", "SHA0", "SHA1" - ] -} - -/** - * Holds if `name` corresponds to a strong encryption algorithm. - */ -predicate isStrongEncryptionAlgorithm(string name) { - name = - [ - "AES", "AES128", "AES192", "AES256", "AES512", "AES-128", "AES-192", "AES-256", "AES-512", - "ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5", "CAMELLIA", "CAMELLIA128", "CAMELLIA192", - "CAMELLIA256", "CAMELLIA-128", "CAMELLIA-192", "CAMELLIA-256", "CHACHA", "GOST", "GOST89", - "IDEA", "RABBIT", "RSA", "SEED", "SM4" - ] -} - -/** - * Holds if `name` corresponds to a weak encryption algorithm. - */ -predicate isWeakEncryptionAlgorithm(string name) { - name = - [ - "DES", "3DES", "DES3", "TRIPLEDES", "DESX", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", - "ARCFOUR", "ARC5", "RC5" - ] -} - -/** - * Holds if `name` corresponds to a strong password hashing algorithm. - */ -predicate isStrongPasswordHashingAlgorithm(string name) { - name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] -} - -/** - * Holds if `name` corresponds to a weak password hashing algorithm. - */ -predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" } - -/** - * Holds if `name` corresponds to a stream cipher. - */ -predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] } diff --git a/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll b/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll index 01b568d234a..13a03a3bd88 100644 --- a/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll +++ b/ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll @@ -1,117 +1,5 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). */ -private import codeql.concepts.internal.CryptoAlgorithmNames - -/** - * A cryptographic algorithm. - */ -private newtype TCryptographicAlgorithm = - MkHashingAlgorithm(string name, boolean isWeak) { - isStrongHashingAlgorithm(name) and isWeak = false - or - isWeakHashingAlgorithm(name) and isWeak = true - } or - MkEncryptionAlgorithm(string name, boolean isWeak) { - isStrongEncryptionAlgorithm(name) and isWeak = false - or - isWeakEncryptionAlgorithm(name) and isWeak = true - } or - MkPasswordHashingAlgorithm(string name, boolean isWeak) { - isStrongPasswordHashingAlgorithm(name) and isWeak = false - or - isWeakPasswordHashingAlgorithm(name) and isWeak = true - } - -/** - * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. - * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. - * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. - */ -bindingset[name] -private CryptographicAlgorithm getBestAlgorithmForName(string name) { - result = - max(CryptographicAlgorithm algorithm | - algorithm.getName() = - [ - name.toUpperCase(), // the full name - name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces - name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores - ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces - | - algorithm order by algorithm.getName().length() - ) -} - -/** - * A cryptographic algorithm. - */ -abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { result = this.getName() } - - /** - * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). - */ - abstract string getName(); - - /** - * Holds if the name of this algorithm is the most specific match for `name`. - * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. - */ - bindingset[name] - predicate matchesName(string name) { this = getBestAlgorithmForName(name) } - - /** - * Holds if this algorithm is weak. - */ - abstract predicate isWeak(); -} - -/** - * A hashing algorithm such as `MD5` or `SHA512`. - */ -class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * An encryption algorithm such as `DES` or `AES512`. - */ -class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } - - /** Holds if this algorithm is a stream cipher. */ - predicate isStreamCipher() { isStreamCipher(name) } -} - -/** - * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. - */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} +import codeql.concepts.CryptoAlgorithms diff --git a/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll b/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll deleted file mode 100644 index 8bb63d97876..00000000000 --- a/ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Names of cryptographic algorithms, separated into strong and weak variants. - * - * The names are normalized: upper-case, no spaces, dashes or underscores. - * - * The names are inspired by the names used in real world crypto libraries. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). - */ - -/** - * Holds if `name` corresponds to a strong hashing algorithm. - */ -predicate isStrongHashingAlgorithm(string name) { - name = - [ - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 - // and https://www.blake2.net/ - "BLAKE2", "BLAKE2B", "BLAKE2S", - // see https://github.com/BLAKE3-team/BLAKE3 - "BLAKE3", - // - "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 - "SHAKE128", "SHAKE256", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 - "SM3", - // see https://security.stackexchange.com/a/216297 - "WHIRLPOOL", - ] -} - -/** - * Holds if `name` corresponds to a weak hashing algorithm. - */ -predicate isWeakHashingAlgorithm(string name) { - name = - [ - "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", - "RIPEMD320", "SHA0", "SHA1" - ] -} - -/** - * Holds if `name` corresponds to a strong encryption algorithm. - */ -predicate isStrongEncryptionAlgorithm(string name) { - name = - [ - "AES", "AES128", "AES192", "AES256", "AES512", "AES-128", "AES-192", "AES-256", "AES-512", - "ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5", "CAMELLIA", "CAMELLIA128", "CAMELLIA192", - "CAMELLIA256", "CAMELLIA-128", "CAMELLIA-192", "CAMELLIA-256", "CHACHA", "GOST", "GOST89", - "IDEA", "RABBIT", "RSA", "SEED", "SM4" - ] -} - -/** - * Holds if `name` corresponds to a weak encryption algorithm. - */ -predicate isWeakEncryptionAlgorithm(string name) { - name = - [ - "DES", "3DES", "DES3", "TRIPLEDES", "DESX", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", - "ARCFOUR", "ARC5", "RC5" - ] -} - -/** - * Holds if `name` corresponds to a strong password hashing algorithm. - */ -predicate isStrongPasswordHashingAlgorithm(string name) { - name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] -} - -/** - * Holds if `name` corresponds to a weak password hashing algorithm. - */ -predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" } - -/** - * Holds if `name` corresponds to a stream cipher. - */ -predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] } diff --git a/rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll b/rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll index 01b568d234a..13a03a3bd88 100644 --- a/rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll +++ b/rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll @@ -1,117 +1,5 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). */ -private import codeql.concepts.internal.CryptoAlgorithmNames - -/** - * A cryptographic algorithm. - */ -private newtype TCryptographicAlgorithm = - MkHashingAlgorithm(string name, boolean isWeak) { - isStrongHashingAlgorithm(name) and isWeak = false - or - isWeakHashingAlgorithm(name) and isWeak = true - } or - MkEncryptionAlgorithm(string name, boolean isWeak) { - isStrongEncryptionAlgorithm(name) and isWeak = false - or - isWeakEncryptionAlgorithm(name) and isWeak = true - } or - MkPasswordHashingAlgorithm(string name, boolean isWeak) { - isStrongPasswordHashingAlgorithm(name) and isWeak = false - or - isWeakPasswordHashingAlgorithm(name) and isWeak = true - } - -/** - * Gets the most specific `CryptographicAlgorithm` that matches the given `name`. - * A matching algorithm is one where the name of the algorithm matches the start of name, with allowances made for different name formats. - * In the case that multiple `CryptographicAlgorithm`s match the given `name`, the algorithm(s) with the longest name will be selected. This is intended to select more specific versions of algorithms when multiple versions could match - for example "SHA3_224" matches against both "SHA3" and "SHA3224", but the latter is a more precise match. - */ -bindingset[name] -private CryptographicAlgorithm getBestAlgorithmForName(string name) { - result = - max(CryptographicAlgorithm algorithm | - algorithm.getName() = - [ - name.toUpperCase(), // the full name - name.toUpperCase().regexpCapture("^([\\w]+)(?:-.*)?$", 1), // the name prior to any dashes or spaces - name.toUpperCase().regexpCapture("^([A-Z0-9]+)(?:(-|_).*)?$", 1) // the name prior to any dashes, spaces, or underscores - ].regexpReplaceAll("[-_ ]", "") // strip dashes, underscores, and spaces - | - algorithm order by algorithm.getName().length() - ) -} - -/** - * A cryptographic algorithm. - */ -abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { result = this.getName() } - - /** - * Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores). - */ - abstract string getName(); - - /** - * Holds if the name of this algorithm is the most specific match for `name`. - * This predicate matches quite liberally to account for different ways of formatting algorithm names, e.g. using dashes, underscores, or spaces as separators, including or not including block modes of operation, etc. - */ - bindingset[name] - predicate matchesName(string name) { this = getBestAlgorithmForName(name) } - - /** - * Holds if this algorithm is weak. - */ - abstract predicate isWeak(); -} - -/** - * A hashing algorithm such as `MD5` or `SHA512`. - */ -class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} - -/** - * An encryption algorithm such as `DES` or `AES512`. - */ -class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } - - /** Holds if this algorithm is a stream cipher. */ - predicate isStreamCipher() { isStreamCipher(name) } -} - -/** - * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. - */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - - PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - - override string getName() { result = name } - - override predicate isWeak() { isWeak = true } -} +import codeql.concepts.CryptoAlgorithms diff --git a/rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll b/rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll deleted file mode 100644 index 8bb63d97876..00000000000 --- a/rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Names of cryptographic algorithms, separated into strong and weak variants. - * - * The names are normalized: upper-case, no spaces, dashes or underscores. - * - * The names are inspired by the names used in real world crypto libraries. - * - * The classification into strong and weak are based on Wikipedia, OWASP and Google (2021). - */ - -/** - * Holds if `name` corresponds to a strong hashing algorithm. - */ -predicate isStrongHashingAlgorithm(string name) { - name = - [ - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#blake2 - // and https://www.blake2.net/ - "BLAKE2", "BLAKE2B", "BLAKE2S", - // see https://github.com/BLAKE3-team/BLAKE3 - "BLAKE3", - // - "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2", - "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#cryptography.hazmat.primitives.hashes.SHAKE128 - "SHAKE128", "SHAKE256", - // see https://cryptography.io/en/latest/hazmat/primitives/cryptographic-hashes/#sm3 - "SM3", - // see https://security.stackexchange.com/a/216297 - "WHIRLPOOL", - ] -} - -/** - * Holds if `name` corresponds to a weak hashing algorithm. - */ -predicate isWeakHashingAlgorithm(string name) { - name = - [ - "HAVEL128", "MD2", "MD4", "MD5", "PANAMA", "RIPEMD", "RIPEMD128", "RIPEMD256", "RIPEMD160", - "RIPEMD320", "SHA0", "SHA1" - ] -} - -/** - * Holds if `name` corresponds to a strong encryption algorithm. - */ -predicate isStrongEncryptionAlgorithm(string name) { - name = - [ - "AES", "AES128", "AES192", "AES256", "AES512", "AES-128", "AES-192", "AES-256", "AES-512", - "ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5", "CAMELLIA", "CAMELLIA128", "CAMELLIA192", - "CAMELLIA256", "CAMELLIA-128", "CAMELLIA-192", "CAMELLIA-256", "CHACHA", "GOST", "GOST89", - "IDEA", "RABBIT", "RSA", "SEED", "SM4" - ] -} - -/** - * Holds if `name` corresponds to a weak encryption algorithm. - */ -predicate isWeakEncryptionAlgorithm(string name) { - name = - [ - "DES", "3DES", "DES3", "TRIPLEDES", "DESX", "TDEA", "TRIPLEDEA", "ARC2", "RC2", "ARC4", "RC4", - "ARCFOUR", "ARC5", "RC5" - ] -} - -/** - * Holds if `name` corresponds to a strong password hashing algorithm. - */ -predicate isStrongPasswordHashingAlgorithm(string name) { - name = ["ARGON2", "PBKDF2", "BCRYPT", "SCRYPT"] -} - -/** - * Holds if `name` corresponds to a weak password hashing algorithm. - */ -predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" } - -/** - * Holds if `name` corresponds to a stream cipher. - */ -predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }