Merge pull request #9157 from alexrford/crypto-op-block-mode

Ruby/Python: Add a `BlockMode` concept for `CryptographicOperations`
This commit is contained in:
Alex Ford
2022-06-13 21:32:36 +02:00
committed by GitHub
34 changed files with 478 additions and 113 deletions

View File

@@ -4,3 +4,4 @@
*/
import semmle.javascript.dataflow.DataFlow::DataFlow as DataFlow
import semmle.javascript.security.CryptoAlgorithms as CryptoAlgorithms

View File

@@ -11,3 +11,79 @@
*/
private import ConceptsImports
/**
* Provides models for cryptographic concepts.
*
* Note: The `CryptographicAlgorithm` class currently doesn't take weak keys into
* consideration for the `isWeak` member predicate. So RSA is always considered
* secure, although using a low number of bits will actually make it insecure. We plan
* to improve our libraries in the future to more precisely capture this aspect.
*/
module Cryptography {
class CryptographicAlgorithm = CryptoAlgorithms::CryptographicAlgorithm;
class EncryptionAlgorithm = CryptoAlgorithms::EncryptionAlgorithm;
class HashingAlgorithm = CryptoAlgorithms::HashingAlgorithm;
class PasswordHashingAlgorithm = CryptoAlgorithms::PasswordHashingAlgorithm;
/**
* A data-flow node that is an application of a cryptographic algorithm. For example,
* encryption, decryption, signature-validation.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `CryptographicOperation::Range` instead.
*/
class CryptographicOperation extends DataFlow::Node instanceof CryptographicOperation::Range {
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
DataFlow::Node getAnInput() { result = super.getAnInput() }
/**
* Gets the block mode used to perform this cryptographic operation.
* This may have no result - for example if the `CryptographicAlgorithm` used
* is a stream cipher rather than a block cipher.
*/
BlockMode getBlockMode() { result = super.getBlockMode() }
}
/** Provides classes for modeling new applications of a cryptographic algorithms. */
module CryptographicOperation {
/**
* A data-flow node that is an application of a cryptographic algorithm. For example,
* encryption, decryption, signature-validation.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `CryptographicOperation` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
abstract CryptographicAlgorithm getAlgorithm();
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
abstract DataFlow::Node getAnInput();
/**
* Gets the block mode used to perform this cryptographic operation.
* This may have no result - for example if the `CryptographicAlgorithm` used
* is a stream cipher rather than a block cipher.
*/
abstract BlockMode getBlockMode();
}
}
/**
* A cryptographic block cipher mode of operation. This can be used to encrypt
* data of arbitrary length using a block encryption algorithm.
*/
class BlockMode extends string {
BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] }
/** Holds if this block mode is considered to be insecure. */
predicate isWeak() { this = "ECB" }
}
}

View File

@@ -81,6 +81,9 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
override string getName() { result = name }
override predicate isWeak() { isWeak = true }
/** Holds if this algorithm is a stream cipher. */
predicate isStreamCipher() { isStreamCipher(name) }
}
/**

View File

@@ -67,6 +67,6 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
/**
* Holds if `name` corresponds to a weak block cipher mode of operation.
* Holds if `name` corresponds to a stream cipher.
*/
predicate isWeakBlockMode(string name) { name = "ECB" }
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }