mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Crypto: Refactor type name mapping and fix QL-for-QL alerts
This commit is contained in:
@@ -5,36 +5,37 @@ private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmCon
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import AlgToAVCFlow
|
||||
private import codeql.quantum.experimental.Standardization::Types::KeyOpAlg as KeyOpAlg
|
||||
|
||||
/**
|
||||
* Given a `KnownOpenSslBlockModeAlgorithmExpr`, converts this to a block family type.
|
||||
* Does not bind if there is no mapping (no mapping to 'unknown' or 'other').
|
||||
*/
|
||||
predicate knownOpenSslConstantToBlockModeFamilyType(
|
||||
KnownOpenSslBlockModeAlgorithmExpr e, Crypto::TBlockCipherModeOfOperationType type
|
||||
KnownOpenSslBlockModeAlgorithmExpr e, KeyOpAlg::ModeOfOperationType type
|
||||
) {
|
||||
exists(string name |
|
||||
name = e.(KnownOpenSslAlgorithmExpr).getNormalizedName() and
|
||||
(
|
||||
name = "CBC" and type instanceof Crypto::CBC
|
||||
name = "CBC" and type instanceof KeyOpAlg::CBC
|
||||
or
|
||||
name = "CFB%" and type instanceof Crypto::CFB
|
||||
name = "CFB%" and type instanceof KeyOpAlg::CFB
|
||||
or
|
||||
name = "CTR" and type instanceof Crypto::CTR
|
||||
name = "CTR" and type instanceof KeyOpAlg::CTR
|
||||
or
|
||||
name = "GCM" and type instanceof Crypto::GCM
|
||||
name = "GCM" and type instanceof KeyOpAlg::GCM
|
||||
or
|
||||
name = "OFB" and type instanceof Crypto::OFB
|
||||
name = "OFB" and type instanceof KeyOpAlg::OFB
|
||||
or
|
||||
name = "XTS" and type instanceof Crypto::XTS
|
||||
name = "XTS" and type instanceof KeyOpAlg::XTS
|
||||
or
|
||||
name = "CCM" and type instanceof Crypto::CCM
|
||||
name = "CCM" and type instanceof KeyOpAlg::CCM
|
||||
or
|
||||
name = "GCM" and type instanceof Crypto::GCM
|
||||
name = "GCM" and type instanceof KeyOpAlg::GCM
|
||||
or
|
||||
name = "CCM" and type instanceof Crypto::CCM
|
||||
name = "CCM" and type instanceof KeyOpAlg::CCM
|
||||
or
|
||||
name = "ECB" and type instanceof Crypto::ECB
|
||||
name = "ECB" and type instanceof KeyOpAlg::ECB
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -64,10 +65,10 @@ class KnownOpenSslBlockModeConstantAlgorithmInstance extends OpenSslAlgorithmIns
|
||||
getterCall = this
|
||||
}
|
||||
|
||||
override Crypto::TBlockCipherModeOfOperationType getModeType() {
|
||||
override KeyOpAlg::ModeOfOperationType getModeType() {
|
||||
knownOpenSslConstantToBlockModeFamilyType(this, result)
|
||||
or
|
||||
not knownOpenSslConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode()
|
||||
not knownOpenSslConstantToBlockModeFamilyType(this, _) and result = KeyOpAlg::OtherMode()
|
||||
}
|
||||
|
||||
// NOTE: I'm not going to attempt to parse out the mode specific part, so returning
|
||||
|
||||
@@ -113,7 +113,7 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
|
||||
this.(KnownOpenSslCipherAlgorithmExpr).getExplicitKeySize() = result
|
||||
}
|
||||
|
||||
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
|
||||
override KeyOpAlg::AlgorithmType getAlgorithmType() {
|
||||
knownOpenSslConstantToCipherFamilyType(this, result)
|
||||
or
|
||||
not knownOpenSslConstantToCipherFamilyType(this, _) and
|
||||
|
||||
@@ -39,8 +39,14 @@ class KnownOpenSslEllipticCurveConstantAlgorithmInstance extends OpenSslAlgorith
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override Crypto::TEllipticCurveType getEllipticCurveType() {
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getParsedEllipticCurveName(), _, result)
|
||||
override Crypto::EllipticCurveFamilyType getEllipticCurveFamilyType() {
|
||||
if
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.getParsedEllipticCurveName(), _,
|
||||
_)
|
||||
then
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.getParsedEllipticCurveName(), _,
|
||||
result)
|
||||
else result = Crypto::OtherEllipticCurveType()
|
||||
}
|
||||
|
||||
override string getParsedEllipticCurveName() {
|
||||
@@ -48,7 +54,7 @@ class KnownOpenSslEllipticCurveConstantAlgorithmInstance extends OpenSslAlgorith
|
||||
}
|
||||
|
||||
override int getKeySize() {
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.(KnownOpenSslAlgorithmExpr)
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.(KnownOpenSslAlgorithmExpr)
|
||||
.getNormalizedName(), result, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override Crypto::TMacType getMacType() {
|
||||
this instanceof KnownOpenSslHMacAlgorithmExpr and result instanceof Crypto::THMAC
|
||||
override Crypto::MacType getMacType() {
|
||||
this instanceof KnownOpenSslHMacAlgorithmExpr and result = Crypto::HMAC()
|
||||
or
|
||||
this instanceof KnownOpenSslCMacAlgorithmExpr and result instanceof Crypto::TCMAC
|
||||
this instanceof KnownOpenSslCMacAlgorithmExpr and result = Crypto::CMAC()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmCon
|
||||
private import AlgToAVCFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import codeql.quantum.experimental.Standardization::Types::KeyOpAlg as KeyOpAlg
|
||||
|
||||
/**
|
||||
* A class to define padding specific integer values.
|
||||
@@ -28,18 +29,18 @@ class OpenSslPaddingLiteral extends Literal {
|
||||
* Does not bind if there is no mapping (no mapping to 'unknown' or 'other').
|
||||
*/
|
||||
predicate knownOpenSslConstantToPaddingFamilyType(
|
||||
KnownOpenSslPaddingAlgorithmExpr e, Crypto::TPaddingType type
|
||||
KnownOpenSslPaddingAlgorithmExpr e, KeyOpAlg::PaddingSchemeType type
|
||||
) {
|
||||
exists(string name |
|
||||
name = e.(KnownOpenSslAlgorithmExpr).getNormalizedName() and
|
||||
(
|
||||
name = "OAEP" and type = Crypto::OAEP()
|
||||
name = "OAEP" and type = KeyOpAlg::OAEP()
|
||||
or
|
||||
name = "PSS" and type = Crypto::PSS()
|
||||
name = "PSS" and type = KeyOpAlg::PSS()
|
||||
or
|
||||
name = "PKCS7" and type = Crypto::PKCS7()
|
||||
name = "PKCS7" and type = KeyOpAlg::PKCS7()
|
||||
or
|
||||
name = "PKCS1V15" and type = Crypto::PKCS1_v1_5()
|
||||
name = "PKCS1V15" and type = KeyOpAlg::PKCS1_v1_5()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -98,24 +99,24 @@ class KnownOpenSslPaddingConstantAlgorithmInstance extends OpenSslAlgorithmInsta
|
||||
|
||||
override OpenSslAlgorithmValueConsumer getAvc() { result = getterCall }
|
||||
|
||||
Crypto::TPaddingType getKnownPaddingType() {
|
||||
this.(Literal).getValue().toInt() in [1, 7, 8] and result = Crypto::PKCS1_v1_5()
|
||||
KeyOpAlg::PaddingSchemeType getKnownPaddingType() {
|
||||
this.(Literal).getValue().toInt() in [1, 7, 8] and result = KeyOpAlg::PKCS1_v1_5()
|
||||
or
|
||||
this.(Literal).getValue().toInt() = 3 and result = Crypto::NoPadding()
|
||||
this.(Literal).getValue().toInt() = 3 and result = KeyOpAlg::NoPadding()
|
||||
or
|
||||
this.(Literal).getValue().toInt() = 4 and result = Crypto::OAEP()
|
||||
this.(Literal).getValue().toInt() = 4 and result = KeyOpAlg::OAEP()
|
||||
or
|
||||
this.(Literal).getValue().toInt() = 5 and result = Crypto::ANSI_X9_23()
|
||||
this.(Literal).getValue().toInt() = 5 and result = KeyOpAlg::ANSI_X9_23()
|
||||
or
|
||||
this.(Literal).getValue().toInt() = 6 and result = Crypto::PSS()
|
||||
this.(Literal).getValue().toInt() = 6 and result = KeyOpAlg::PSS()
|
||||
}
|
||||
|
||||
override Crypto::TPaddingType getPaddingType() {
|
||||
override KeyOpAlg::PaddingSchemeType getPaddingType() {
|
||||
isPaddingSpecificConsumer = true and
|
||||
(
|
||||
result = this.getKnownPaddingType()
|
||||
or
|
||||
not exists(this.getKnownPaddingType()) and result = Crypto::OtherPadding()
|
||||
not exists(this.getKnownPaddingType()) and result = KeyOpAlg::OtherPadding()
|
||||
)
|
||||
or
|
||||
isPaddingSpecificConsumer = false and
|
||||
@@ -165,7 +166,7 @@ class OaepPaddingAlgorithmInstance extends Crypto::OaepPaddingAlgorithmInstance,
|
||||
KnownOpenSslPaddingConstantAlgorithmInstance
|
||||
{
|
||||
OaepPaddingAlgorithmInstance() {
|
||||
this.(Crypto::PaddingAlgorithmInstance).getPaddingType() = Crypto::OAEP()
|
||||
this.(Crypto::PaddingAlgorithmInstance).getPaddingType() = KeyOpAlg::OAEP()
|
||||
}
|
||||
|
||||
override Crypto::HashAlgorithmInstance getOaepEncodingHashAlgorithm() {
|
||||
|
||||
@@ -73,7 +73,7 @@ class KnownOpenSslSignatureConstantAlgorithmInstance extends OpenSslAlgorithmIns
|
||||
none()
|
||||
}
|
||||
|
||||
override KeyOpAlg::Algorithm getAlgorithmType() {
|
||||
override KeyOpAlg::AlgorithmType getAlgorithmType() {
|
||||
knownOpenSslConstantToSignatureFamilyType(this, result)
|
||||
or
|
||||
not knownOpenSslConstantToSignatureFamilyType(this, _) and
|
||||
|
||||
@@ -5,7 +5,7 @@ import semmle.code.java.controlflow.Dominance
|
||||
|
||||
module JCAModel {
|
||||
import Language
|
||||
import Crypto::KeyOpAlg as KeyOpAlg
|
||||
import codeql.quantum.experimental.Standardization::Types::KeyOpAlg as KeyOpAlg
|
||||
|
||||
abstract class CipherAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
|
||||
|
||||
@@ -115,7 +115,7 @@ module JCAModel {
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
Crypto::THashType hash_name_to_type_known(string name, int digestLength) {
|
||||
Crypto::HashType hash_name_to_type_known(string name, int digestLength) {
|
||||
name = "SHA-1" and result instanceof Crypto::SHA1 and digestLength = 160
|
||||
or
|
||||
name = ["SHA-256", "SHA-384", "SHA-512"] and
|
||||
@@ -152,24 +152,22 @@ module JCAModel {
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
private predicate mode_name_to_type_known(
|
||||
Crypto::TBlockCipherModeOfOperationType type, string name
|
||||
) {
|
||||
type = Crypto::ECB() and name = "ECB"
|
||||
private predicate mode_name_to_type_known(KeyOpAlg::ModeOfOperationType type, string name) {
|
||||
type = KeyOpAlg::ECB() and name = "ECB"
|
||||
or
|
||||
type = Crypto::CBC() and name = "CBC"
|
||||
type = KeyOpAlg::CBC() and name = "CBC"
|
||||
or
|
||||
type = Crypto::GCM() and name = "GCM"
|
||||
type = KeyOpAlg::GCM() and name = "GCM"
|
||||
or
|
||||
type = Crypto::CTR() and name = "CTR"
|
||||
type = KeyOpAlg::CTR() and name = "CTR"
|
||||
or
|
||||
type = Crypto::XTS() and name = "XTS"
|
||||
type = KeyOpAlg::XTS() and name = "XTS"
|
||||
or
|
||||
type = Crypto::CCM() and name = "CCM"
|
||||
type = KeyOpAlg::CCM() and name = "CCM"
|
||||
or
|
||||
type = Crypto::SIV() and name = "SIV"
|
||||
type = KeyOpAlg::SIV() and name = "SIV"
|
||||
or
|
||||
type = Crypto::OCB() and name = "OCB"
|
||||
type = KeyOpAlg::OCB() and name = "OCB"
|
||||
}
|
||||
|
||||
bindingset[name]
|
||||
@@ -206,7 +204,7 @@ module JCAModel {
|
||||
|
||||
bindingset[name]
|
||||
predicate mac_name_to_mac_type_known(Crypto::TMacType type, string name) {
|
||||
type = Crypto::THMAC() and
|
||||
type = Crypto::HMAC() and
|
||||
name.toUpperCase().matches("HMAC%")
|
||||
}
|
||||
|
||||
@@ -298,18 +296,18 @@ module JCAModel {
|
||||
override string getRawPaddingAlgorithmName() { result = super.getPadding() }
|
||||
|
||||
bindingset[name]
|
||||
private predicate paddingToNameMappingKnown(Crypto::TPaddingType type, string name) {
|
||||
type instanceof Crypto::NoPadding and name = "NOPADDING"
|
||||
private predicate paddingToNameMappingKnown(KeyOpAlg::PaddingSchemeType type, string name) {
|
||||
type instanceof KeyOpAlg::NoPadding and name = "NOPADDING"
|
||||
or
|
||||
type instanceof Crypto::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA?
|
||||
type instanceof KeyOpAlg::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA?
|
||||
or
|
||||
type instanceof Crypto::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith%
|
||||
type instanceof KeyOpAlg::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith%
|
||||
}
|
||||
|
||||
override Crypto::TPaddingType getPaddingType() {
|
||||
override KeyOpAlg::PaddingSchemeType getPaddingType() {
|
||||
if this.paddingToNameMappingKnown(_, super.getPadding())
|
||||
then this.paddingToNameMappingKnown(result, super.getPadding())
|
||||
else result instanceof Crypto::OtherPadding
|
||||
else result instanceof KeyOpAlg::OtherPadding
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,10 +318,10 @@ module JCAModel {
|
||||
|
||||
override string getRawModeAlgorithmName() { result = super.getMode() }
|
||||
|
||||
override Crypto::TBlockCipherModeOfOperationType getModeType() {
|
||||
override KeyOpAlg::ModeOfOperationType getModeType() {
|
||||
if mode_name_to_type_known(_, super.getMode())
|
||||
then mode_name_to_type_known(result, super.getMode())
|
||||
else result instanceof Crypto::OtherMode
|
||||
else result instanceof KeyOpAlg::OtherMode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +345,7 @@ module JCAModel {
|
||||
|
||||
override string getRawAlgorithmName() { result = super.getValue() }
|
||||
|
||||
override KeyOpAlg::Algorithm getAlgorithmType() {
|
||||
override KeyOpAlg::AlgorithmType getAlgorithmType() {
|
||||
if cipher_name_to_type_known(_, super.getAlgorithmName())
|
||||
then cipher_name_to_type_known(result, super.getAlgorithmName())
|
||||
else result instanceof KeyOpAlg::TUnknownKeyOperationAlgorithmType
|
||||
@@ -1249,7 +1247,7 @@ module JCAModel {
|
||||
result = super.getRawKdfAlgorithmName().splitAt("WithHmac", 1)
|
||||
}
|
||||
|
||||
override Crypto::TMacType getMacType() { result instanceof Crypto::THMAC }
|
||||
override Crypto::MacType getMacType() { result = Crypto::HMAC() }
|
||||
|
||||
override Crypto::AlgorithmValueConsumer getHmacAlgorithmValueConsumer() { result = this }
|
||||
|
||||
@@ -1487,10 +1485,10 @@ module JCAModel {
|
||||
|
||||
override string getRawMacAlgorithmName() { result = super.getValue() }
|
||||
|
||||
override Crypto::TMacType getMacType() {
|
||||
override Crypto::MacType getMacType() {
|
||||
if mac_name_to_mac_type_known(_, super.getValue())
|
||||
then mac_name_to_mac_type_known(result, super.getValue())
|
||||
else result instanceof Crypto::TOtherMACType
|
||||
else result = Crypto::OtherMacType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1597,15 +1595,18 @@ module JCAModel {
|
||||
|
||||
override string getRawEllipticCurveName() { result = super.getValue() }
|
||||
|
||||
override Crypto::TEllipticCurveType getEllipticCurveType() {
|
||||
if Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, _)
|
||||
override Crypto::EllipticCurveFamilyType getEllipticCurveFamilyType() {
|
||||
if
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, _)
|
||||
then
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _, result)
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), _,
|
||||
result)
|
||||
else result = Crypto::OtherEllipticCurveType()
|
||||
}
|
||||
|
||||
override int getKeySize() {
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), result, _)
|
||||
Crypto::ellipticCurveNameToKnownKeySizeAndFamilyMapping(this.getRawEllipticCurveName(),
|
||||
result, _)
|
||||
}
|
||||
|
||||
EllipticCurveAlgorithmValueConsumer getConsumer() { result = consumer }
|
||||
|
||||
@@ -29,6 +29,8 @@ signature module InputSig<LocationSig Location> {
|
||||
}
|
||||
|
||||
module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
import Standardization::Types
|
||||
|
||||
final class LocatableElement = Input::LocatableElement;
|
||||
|
||||
final class UnknownLocation = Input::UnknownLocation;
|
||||
@@ -552,192 +554,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
final override ConsumerInputDataFlowNode getInputNode() { result = inputNode }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `KeyOpAlg` module defines key operation algorithms types (e.g., symmetric ciphers, signatures, etc.)
|
||||
* and provides mapping of those types to string names and structural properties.
|
||||
*/
|
||||
module KeyOpAlg {
|
||||
/**
|
||||
* An algorithm used in key operations.
|
||||
*/
|
||||
newtype TAlgorithm =
|
||||
TSymmetricCipher(TSymmetricCipherType t) or
|
||||
TAsymmetricCipher(TAsymmetricCipherType t) or
|
||||
TSignature(TSignatureAlgorithmType t) or
|
||||
TKeyEncapsulation(TKEMAlgorithmType t) or
|
||||
TUnknownKeyOperationAlgorithmType()
|
||||
|
||||
// Parameterized algorithm types
|
||||
newtype TSymmetricCipherType =
|
||||
AES() or
|
||||
ARIA() or
|
||||
BLOWFISH() or
|
||||
CAMELLIA() or
|
||||
CAST5() or
|
||||
CHACHA20() or
|
||||
DES() or
|
||||
DESX() or
|
||||
GOST() or
|
||||
IDEA() or
|
||||
KUZNYECHIK() or
|
||||
MAGMA() or
|
||||
TripleDES() or
|
||||
DoubleDES() or
|
||||
RC2() or
|
||||
RC4() or
|
||||
RC5() or
|
||||
SEED() or
|
||||
SM4() or
|
||||
OtherSymmetricCipherType()
|
||||
|
||||
newtype TAsymmetricCipherType =
|
||||
RSA() or
|
||||
OtherAsymmetricCipherType()
|
||||
|
||||
newtype TSignatureAlgorithmType =
|
||||
DSA() or
|
||||
ECDSA() or
|
||||
EDDSA() or // e.g., ED25519 or ED448
|
||||
OtherSignatureAlgorithmType()
|
||||
|
||||
newtype TKEMAlgorithmType =
|
||||
Kyber() or
|
||||
FrodoKEM() or
|
||||
OtherKEMAlgorithmType()
|
||||
|
||||
newtype TCipherStructureType =
|
||||
Block() or
|
||||
Stream() or
|
||||
UnknownCipherStructureType()
|
||||
|
||||
class CipherStructureType extends TCipherStructureType {
|
||||
string toString() {
|
||||
result = "Block" and this = Block()
|
||||
or
|
||||
result = "Stream" and this = Stream()
|
||||
or
|
||||
result = "Unknown" and this = UnknownCipherStructureType()
|
||||
}
|
||||
}
|
||||
|
||||
predicate fixedImplicitCipherKeySize(TAlgorithm type, int size) {
|
||||
type = TSymmetricCipher(DES()) and size = 56
|
||||
or
|
||||
type = TSymmetricCipher(DESX()) and size = 184
|
||||
or
|
||||
type = TSymmetricCipher(DoubleDES()) and size = 112
|
||||
or
|
||||
type = TSymmetricCipher(TripleDES()) and size = 168
|
||||
or
|
||||
type = TSymmetricCipher(CHACHA20()) and size = 256
|
||||
or
|
||||
type = TSymmetricCipher(IDEA()) and size = 128
|
||||
or
|
||||
type = TSymmetricCipher(KUZNYECHIK()) and size = 256
|
||||
or
|
||||
type = TSymmetricCipher(MAGMA()) and size = 256
|
||||
or
|
||||
type = TSymmetricCipher(SM4()) and size = 128
|
||||
or
|
||||
type = TSymmetricCipher(SEED()) and size = 128
|
||||
}
|
||||
|
||||
predicate symmetric_cipher_to_name_and_structure(
|
||||
TSymmetricCipherType type, string name, CipherStructureType s
|
||||
) {
|
||||
type = AES() and name = "AES" and s = Block()
|
||||
or
|
||||
type = ARIA() and name = "ARIA" and s = Block()
|
||||
or
|
||||
type = BLOWFISH() and name = "Blowfish" and s = Block()
|
||||
or
|
||||
type = CAMELLIA() and name = "Camellia" and s = Block()
|
||||
or
|
||||
type = CAST5() and name = "CAST5" and s = Block()
|
||||
or
|
||||
type = CHACHA20() and name = "ChaCha20" and s = Stream()
|
||||
or
|
||||
type = DES() and name = "DES" and s = Block()
|
||||
or
|
||||
type = DESX() and name = "DESX" and s = Block()
|
||||
or
|
||||
type = GOST() and name = "GOST" and s = Block()
|
||||
or
|
||||
type = IDEA() and name = "IDEA" and s = Block()
|
||||
or
|
||||
type = KUZNYECHIK() and name = "Kuznyechik" and s = Block()
|
||||
or
|
||||
type = MAGMA() and name = "Magma" and s = Block()
|
||||
or
|
||||
type = TripleDES() and name = "TripleDES" and s = Block()
|
||||
or
|
||||
type = DoubleDES() and name = "DoubleDES" and s = Block()
|
||||
or
|
||||
type = RC2() and name = "RC2" and s = Block()
|
||||
or
|
||||
type = RC4() and name = "RC4" and s = Stream()
|
||||
or
|
||||
type = RC5() and name = "RC5" and s = Block()
|
||||
or
|
||||
type = SEED() and name = "SEED" and s = Block()
|
||||
or
|
||||
type = SM4() and name = "SM4" and s = Block()
|
||||
or
|
||||
type = OtherSymmetricCipherType() and
|
||||
name = "UnknownSymmetricCipher" and
|
||||
s = UnknownCipherStructureType()
|
||||
}
|
||||
|
||||
predicate type_to_name(Algorithm type, string name) {
|
||||
// Symmetric cipher algorithm
|
||||
symmetric_cipher_to_name_and_structure(type.(SymmetricCipherAlgorithm).getType(), name, _)
|
||||
or
|
||||
// Asymmetric cipher algorithms
|
||||
type = TAsymmetricCipher(RSA()) and name = "RSA"
|
||||
or
|
||||
type = TAsymmetricCipher(OtherAsymmetricCipherType()) and name = "UnknownAsymmetricCipher"
|
||||
or
|
||||
// Signature algorithms
|
||||
type = TSignature(DSA()) and name = "DSA"
|
||||
or
|
||||
type = TSignature(ECDSA()) and name = "ECDSA"
|
||||
or
|
||||
type = TSignature(EDDSA()) and name = "EDSA"
|
||||
or
|
||||
type = TSignature(OtherSignatureAlgorithmType()) and name = "UnknownSignature"
|
||||
or
|
||||
// Key Encapsulation Mechanisms
|
||||
type = TKeyEncapsulation(Kyber()) and name = "Kyber"
|
||||
or
|
||||
type = TKeyEncapsulation(FrodoKEM()) and name = "FrodoKEM"
|
||||
or
|
||||
type = TKeyEncapsulation(OtherKEMAlgorithmType()) and name = "UnknownKEM"
|
||||
or
|
||||
// Unknown
|
||||
type = TUnknownKeyOperationAlgorithmType() and name = "Unknown"
|
||||
}
|
||||
|
||||
class Algorithm extends TAlgorithm {
|
||||
string toString() { type_to_name(this, result) }
|
||||
}
|
||||
|
||||
class SymmetricCipherAlgorithm extends Algorithm, TSymmetricCipher {
|
||||
TSymmetricCipherType type;
|
||||
|
||||
SymmetricCipherAlgorithm() { this = TSymmetricCipher(type) }
|
||||
|
||||
TSymmetricCipherType getType() { result = type }
|
||||
}
|
||||
|
||||
class AsymmetricCipherAlgorithm extends Algorithm, TAsymmetricCipher {
|
||||
TAsymmetricCipherType type;
|
||||
|
||||
AsymmetricCipherAlgorithm() { this = TAsymmetricCipher(type) }
|
||||
|
||||
TAsymmetricCipherType getType() { result = type }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A key-based cryptographic operation instance, encompassing:
|
||||
* 1. **Ciphers**: Encryption and decryption, both symmetric and asymmetric
|
||||
@@ -836,7 +652,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*
|
||||
* This predicate should always hold.
|
||||
*/
|
||||
abstract KeyOpAlg::Algorithm getAlgorithmType();
|
||||
abstract KeyOpAlg::AlgorithmType getAlgorithmType();
|
||||
|
||||
/**
|
||||
* Gets the mode of operation, such as "CBC", "GCM", or "ECB".
|
||||
@@ -888,19 +704,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
predicate shouldHavePaddingScheme() { any() }
|
||||
}
|
||||
|
||||
newtype TBlockCipherModeOfOperationType =
|
||||
ECB() or // Not secure, widely used
|
||||
CBC() or // Vulnerable to padding oracle attacks
|
||||
CFB() or
|
||||
GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec)
|
||||
CTR() or // Fast stream-like encryption (SSH, disk encryption)
|
||||
XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault)
|
||||
CCM() or // Used in lightweight cryptography (IoT, WPA2)
|
||||
SIV() or // Misuse-resistant encryption, used in secure storage
|
||||
OCB() or // Efficient AEAD mode
|
||||
OFB() or
|
||||
OtherMode()
|
||||
|
||||
abstract class ModeOfOperationAlgorithmInstance extends AlgorithmInstance {
|
||||
/**
|
||||
* Gets the type of this mode of operation, e.g., "ECB" or "CBC".
|
||||
@@ -909,7 +712,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*
|
||||
* If a type cannot be determined, the result is `OtherMode`.
|
||||
*/
|
||||
abstract TBlockCipherModeOfOperationType getModeType();
|
||||
abstract KeyOpAlg::ModeOfOperationType getModeType();
|
||||
|
||||
/**
|
||||
* Gets the isolated name as it appears in source, e.g., "CBC" in "AES/CBC/PKCS7Padding".
|
||||
@@ -934,11 +737,11 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*
|
||||
* If a type cannot be determined, the result is `OtherPadding`.
|
||||
*/
|
||||
abstract TPaddingType getPaddingType();
|
||||
abstract KeyOpAlg::PaddingSchemeType getPaddingType();
|
||||
}
|
||||
|
||||
abstract class OaepPaddingAlgorithmInstance extends PaddingAlgorithmInstance {
|
||||
OaepPaddingAlgorithmInstance() { this.getPaddingType() instanceof OAEP }
|
||||
OaepPaddingAlgorithmInstance() { this.getPaddingType() instanceof KeyOpAlg::OAEP }
|
||||
|
||||
/**
|
||||
* Gets the hash algorithm used in this padding scheme.
|
||||
@@ -951,16 +754,11 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
abstract HashAlgorithmInstance getMgf1HashAlgorithm();
|
||||
}
|
||||
|
||||
newtype TMacType =
|
||||
THMAC() or
|
||||
TCMAC() or
|
||||
TOtherMACType()
|
||||
|
||||
abstract class MacAlgorithmInstance extends AlgorithmInstance {
|
||||
/**
|
||||
* Gets the type of this MAC algorithm, e.g., "HMAC" or "CMAC".
|
||||
*/
|
||||
abstract TMacType getMacType();
|
||||
abstract MacType getMacType();
|
||||
|
||||
/**
|
||||
* Gets the isolated name as it appears in source, e.g., "HMAC-SHA256" in "HMAC-SHA256/UnrelatedInformation".
|
||||
@@ -983,7 +781,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
abstract class HmacAlgorithmInstance extends MacAlgorithmInstance {
|
||||
HmacAlgorithmInstance() { this.getMacType() instanceof THMAC }
|
||||
HmacAlgorithmInstance() { this.getMacType() = HMAC() }
|
||||
|
||||
/**
|
||||
* Gets the hash algorithm used by this HMAC algorithm.
|
||||
@@ -999,7 +797,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*/
|
||||
abstract string getRawEllipticCurveName();
|
||||
|
||||
abstract TEllipticCurveType getEllipticCurveType();
|
||||
abstract TEllipticCurveFamilyType getEllipticCurveFamilyType();
|
||||
|
||||
abstract int getKeySize();
|
||||
|
||||
@@ -1165,24 +963,14 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
final override string getKeyCreationTypeDescription() { result = "KeyLoad" }
|
||||
}
|
||||
|
||||
// Key agreement algorithms
|
||||
newtype TKeyAgreementType =
|
||||
DH() or // Diffie-Hellman
|
||||
EDH() or // Ephemeral Diffie-Hellman
|
||||
ECDH() or // Elliptic Curve Diffie-Hellman
|
||||
// NOTE: for now ESDH is considered simply EDH
|
||||
//ESDH() or // Ephemeral-Static Diffie-Hellman
|
||||
// Note: x25519 and x448 are applications of ECDH
|
||||
OtherKeyAgreementType()
|
||||
|
||||
abstract class KeyAgreementAlgorithmInstance extends AlgorithmInstance {
|
||||
abstract TKeyAgreementType getKeyAgreementType();
|
||||
|
||||
abstract string getRawKeyAgreementAlgorithmName();
|
||||
}
|
||||
|
||||
abstract class ECDHKeyAgreementAlgorithmInstance extends KeyAgreementAlgorithmInstance {
|
||||
ECDHKeyAgreementAlgorithmInstance() { this.getKeyAgreementType() instanceof ECDH }
|
||||
abstract class EcdhKeyAgreementAlgorithmInstance extends KeyAgreementAlgorithmInstance {
|
||||
EcdhKeyAgreementAlgorithmInstance() { this.getKeyAgreementType() instanceof ECDH }
|
||||
|
||||
/**
|
||||
* Gets the consumer for the elliptic curve used in the key agreement operation.
|
||||
@@ -1265,7 +1053,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
|
||||
private predicate isEllipticCurveAvc(AlgorithmValueConsumer avc) {
|
||||
exists(ECDHKeyAgreementAlgorithmInstance alg |
|
||||
exists(EcdhKeyAgreementAlgorithmInstance alg |
|
||||
avc = alg.getEllipticCurveAlgorithmValueConsumer()
|
||||
) or
|
||||
exists(KeyGenerationOperationInstance op | op.getAnAlgorithmValueConsumer() = avc)
|
||||
@@ -1320,13 +1108,13 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
TPaddingAlgorithm(PaddingAlgorithmInstance e) or
|
||||
// All other operations
|
||||
THashOperation(HashOperationInstance e) or
|
||||
TMACOperation(MacOperationInstance e) or
|
||||
TMacOperation(MacOperationInstance e) or
|
||||
TKeyAgreementOperation(KeyAgreementSecretGenerationOperationInstance e) or
|
||||
// All other algorithms
|
||||
TEllipticCurve(EllipticCurveInstanceOrValueConsumer e) or
|
||||
THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or
|
||||
TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or
|
||||
TMACAlgorithm(MacAlgorithmInstanceOrValueConsumer e) or
|
||||
TMacAlgorithm(MacAlgorithmInstanceOrValueConsumer e) or
|
||||
TKeyAgreementAlgorithm(KeyAgreementAlgorithmInstanceOrValueConsumer e) or
|
||||
// Generic source nodes, i.e., sources of data that are not resolvable to a specific known asset.
|
||||
TGenericSourceNode(GenericSourceInstance e) {
|
||||
@@ -1774,10 +1562,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* A MAC operation that produces a MAC value.
|
||||
*/
|
||||
final class MacOperationNode extends OperationNode, TMACOperation {
|
||||
final class MacOperationNode extends OperationNode, TMacOperation {
|
||||
MacOperationInstance instance;
|
||||
|
||||
MacOperationNode() { this = TMACOperation(instance) }
|
||||
MacOperationNode() { this = TMacOperation(instance) }
|
||||
|
||||
final override string getInternalType() { result = "MACOperation" }
|
||||
|
||||
@@ -1809,10 +1597,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* A MAC algorithm, such as HMAC or CMAC.
|
||||
*/
|
||||
class MacAlgorithmNode extends AlgorithmNode, TMACAlgorithm {
|
||||
class MacAlgorithmNode extends AlgorithmNode, TMacAlgorithm {
|
||||
MacAlgorithmInstanceOrValueConsumer instance;
|
||||
|
||||
MacAlgorithmNode() { this = TMACAlgorithm(instance) }
|
||||
MacAlgorithmNode() { this = TMacAlgorithm(instance) }
|
||||
|
||||
final override string getInternalType() { result = "MACAlgorithm" }
|
||||
|
||||
@@ -1822,14 +1610,9 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
result = instance.asAlg().getRawMacAlgorithmName()
|
||||
}
|
||||
|
||||
TMacType getMacType() { result = instance.asAlg().getMacType() }
|
||||
MacType getMacType() { result = instance.asAlg().getMacType() }
|
||||
|
||||
final private predicate macToNameMapping(TMacType type, string name) {
|
||||
type instanceof THMAC and
|
||||
name = "HMAC"
|
||||
}
|
||||
|
||||
override string getAlgorithmName() { this.macToNameMapping(this.getMacType(), result) }
|
||||
override string getAlgorithmName() { result = this.getMacType().toString() }
|
||||
}
|
||||
|
||||
final class HmacAlgorithmNode extends MacAlgorithmNode {
|
||||
@@ -2248,42 +2031,11 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
*
|
||||
* If a type cannot be determined, the result is `OtherMode`.
|
||||
*/
|
||||
TBlockCipherModeOfOperationType getModeType() { result = instance.getModeType() }
|
||||
KeyOpAlg::ModeOfOperationType getModeType() { result = instance.getModeType() }
|
||||
|
||||
final private predicate modeToNameMapping(TBlockCipherModeOfOperationType type, string name) {
|
||||
type = ECB() and name = "ECB"
|
||||
or
|
||||
type = CBC() and name = "CBC"
|
||||
or
|
||||
type = GCM() and name = "GCM"
|
||||
or
|
||||
type = CTR() and name = "CTR"
|
||||
or
|
||||
type = XTS() and name = "XTS"
|
||||
or
|
||||
type = CCM() and name = "CCM"
|
||||
or
|
||||
type = SIV() and name = "SIV"
|
||||
or
|
||||
type = OCB() and name = "OCB"
|
||||
or
|
||||
type = CFB() and name = "CFB"
|
||||
or
|
||||
type = OFB() and name = "OFB"
|
||||
}
|
||||
|
||||
override string getAlgorithmName() { this.modeToNameMapping(this.getModeType(), result) }
|
||||
override string getAlgorithmName() { result = this.getModeType().toString() }
|
||||
}
|
||||
|
||||
newtype TPaddingType =
|
||||
PKCS1_v1_5() or // RSA encryption/signing padding
|
||||
PSS() or
|
||||
PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks)
|
||||
ANSI_X9_23() or // Zero-padding except last byte = padding length
|
||||
NoPadding() or // Explicit no-padding
|
||||
OAEP() or // RSA OAEP padding
|
||||
OtherPadding()
|
||||
|
||||
class PaddingAlgorithmNode extends AlgorithmNode, TPaddingAlgorithm {
|
||||
PaddingAlgorithmInstance instance;
|
||||
|
||||
@@ -2293,23 +2045,9 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
override LocatableElement asElement() { result = instance }
|
||||
|
||||
TPaddingType getPaddingType() { result = instance.getPaddingType() }
|
||||
KeyOpAlg::PaddingSchemeType getPaddingType() { result = instance.getPaddingType() }
|
||||
|
||||
final private predicate paddingToNameMapping(TPaddingType type, string name) {
|
||||
type = ANSI_X9_23() and name = "ANSI_X9_23"
|
||||
or
|
||||
type = NoPadding() and name = "NoPadding"
|
||||
or
|
||||
type = OAEP() and name = "OAEP"
|
||||
or
|
||||
type = PKCS1_v1_5() and name = "PKCS1_v1_5"
|
||||
or
|
||||
type = PKCS7() and name = "PKCS7"
|
||||
or
|
||||
type = PSS() and name = "PSS"
|
||||
}
|
||||
|
||||
override string getAlgorithmName() { this.paddingToNameMapping(this.getPaddingType(), result) }
|
||||
override string getAlgorithmName() { result = this.getPaddingType().toString() }
|
||||
|
||||
override string getRawAlgorithmName() { result = instance.getRawPaddingAlgorithmName() }
|
||||
}
|
||||
@@ -2354,14 +2092,10 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
override string getInternalType() { result = "KeyOperationAlgorithm" }
|
||||
|
||||
final KeyOpAlg::CipherStructureType getSymmetricCipherStructure() {
|
||||
KeyOpAlg::symmetric_cipher_to_name_and_structure(this.getAlgorithmType()
|
||||
.(KeyOpAlg::SymmetricCipherAlgorithm)
|
||||
.getType(), _, result)
|
||||
result = this.getAlgorithmType().(KeyOpAlg::SymmetricCipherAlgorithmType).getStructureType()
|
||||
}
|
||||
|
||||
final override string getAlgorithmName() {
|
||||
KeyOpAlg::type_to_name(this.getAlgorithmType(), result)
|
||||
}
|
||||
final override string getAlgorithmName() { result = this.getAlgorithmType().toString() }
|
||||
|
||||
final override string getRawAlgorithmName() { result = instance.asAlg().getRawAlgorithmName() }
|
||||
|
||||
@@ -2371,7 +2105,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
int getKeySizeFixed() {
|
||||
result = instance.asAlg().getKeySizeFixed()
|
||||
or
|
||||
KeyOpAlg::fixedImplicitCipherKeySize(instance.asAlg().getAlgorithmType(), result)
|
||||
result = instance.asAlg().getAlgorithmType().getImplicitKeySize()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2384,7 +2118,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
/**
|
||||
* Gets the type of this key operation algorithm, e.g., "SymmetricEncryption(_)" or ""
|
||||
*/
|
||||
KeyOpAlg::Algorithm getAlgorithmType() { result = instance.asAlg().getAlgorithmType() }
|
||||
KeyOpAlg::AlgorithmType getAlgorithmType() { result = instance.asAlg().getAlgorithmType() }
|
||||
|
||||
predicate isAsymmetric() {
|
||||
this.getAlgorithmType() instanceof KeyOpAlg::TAsymmetricCipher
|
||||
@@ -2490,24 +2224,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
}
|
||||
|
||||
newtype THashType =
|
||||
BLAKE2B() or
|
||||
BLAKE2S() or
|
||||
GOSTHash() or
|
||||
MD2() or
|
||||
MD4() or
|
||||
MD5() or
|
||||
MDC2() or
|
||||
POLY1305() or
|
||||
SHA1() or
|
||||
SHA2() or
|
||||
SHA3() or
|
||||
SHAKE() or
|
||||
SM3() or
|
||||
RIPEMD160() or
|
||||
WHIRLPOOL() or
|
||||
OtherHashType()
|
||||
|
||||
/**
|
||||
* A hashing algorithm that transforms variable-length input into a fixed-size hash value.
|
||||
*/
|
||||
@@ -2522,42 +2238,14 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
override string getRawAlgorithmName() { result = instance.asAlg().getRawHashAlgorithmName() }
|
||||
|
||||
final private predicate hashTypeToNameMapping(THashType type, string name) {
|
||||
type = BLAKE2B() and name = "BLAKE2B"
|
||||
or
|
||||
type = BLAKE2S() and name = "BLAKE2S"
|
||||
or
|
||||
type = RIPEMD160() and name = "RIPEMD160"
|
||||
or
|
||||
type = MD2() and name = "MD2"
|
||||
or
|
||||
type = MD4() and name = "MD4"
|
||||
or
|
||||
type = MD5() and name = "MD5"
|
||||
or
|
||||
type = POLY1305() and name = "POLY1305"
|
||||
or
|
||||
type = SHA1() and name = "SHA1"
|
||||
or
|
||||
type = SHA2() and name = "SHA2"
|
||||
or
|
||||
type = SHA3() and name = "SHA3"
|
||||
or
|
||||
type = SHAKE() and name = "SHAKE"
|
||||
or
|
||||
type = SM3() and name = "SM3"
|
||||
or
|
||||
type = WHIRLPOOL() and name = "WHIRLPOOL"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this hashing algorithm, e.g., MD5 or SHA.
|
||||
*
|
||||
* When modeling a new hashing algorithm, use this predicate to specify the type of the algorithm.
|
||||
*/
|
||||
THashType getHashFamily() { result = instance.asAlg().getHashFamily() }
|
||||
HashType getHashFamily() { result = instance.asAlg().getHashFamily() }
|
||||
|
||||
override string getAlgorithmName() { this.hashTypeToNameMapping(this.getHashFamily(), result) }
|
||||
override string getAlgorithmName() { result = this.getHashFamily().toString() }
|
||||
|
||||
int getDigestLength() {
|
||||
result = instance.asAlg().getFixedDigestLength() or
|
||||
@@ -2577,116 +2265,6 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic curve algorithms
|
||||
*/
|
||||
newtype TEllipticCurveType =
|
||||
NIST() or
|
||||
SEC() or
|
||||
NUMS() or
|
||||
PRIME() or
|
||||
BRAINPOOL() or
|
||||
CURVE25519() or
|
||||
CURVE448() or
|
||||
C2() or
|
||||
SM2() or
|
||||
ES() or
|
||||
OtherEllipticCurveType()
|
||||
|
||||
private predicate isBrainpoolCurve(string curveName, int keySize) {
|
||||
// ALL BRAINPOOL CURVES
|
||||
keySize in [160, 192, 224, 256, 320, 384, 512] and
|
||||
(
|
||||
curveName = "BRAINPOOLP" + keySize + "R1"
|
||||
or
|
||||
curveName = "BRAINPOOLP" + keySize + "T1"
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSecCurve(string curveName, int keySize) {
|
||||
// ALL SEC CURVES
|
||||
keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and
|
||||
exists(string suff | suff in ["R1", "R2", "K1"] |
|
||||
curveName = "SECT" + keySize + suff or
|
||||
curveName = "SECP" + keySize + suff
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isC2Curve(string curveName, int keySize) {
|
||||
// ALL C2 CURVES
|
||||
keySize in [163, 176, 191, 208, 239, 272, 304, 359, 368, 431] and
|
||||
exists(string pre, string suff |
|
||||
pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"]
|
||||
|
|
||||
curveName = "C2" + pre + keySize + suff
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isPrimeCurve(string curveName, int keySize) {
|
||||
// ALL PRIME CURVES
|
||||
keySize in [192, 239, 256] and
|
||||
exists(string suff | suff in ["V1", "V2", "V3"] | curveName = "PRIME" + keySize + suff)
|
||||
}
|
||||
|
||||
private predicate isNumsCurve(string curveName, int keySize) {
|
||||
// ALL NUMS CURVES
|
||||
keySize in [256, 384, 512] and
|
||||
exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize + suff)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` corresponds to a known elliptic curve.
|
||||
*
|
||||
* Note: As an exception, this predicate may be used for library modeling, as curve names are largely standardized.
|
||||
*
|
||||
* When modeling, verify that this predicate offers sufficient coverage for the library and handle edge-cases.
|
||||
*/
|
||||
bindingset[curveName]
|
||||
predicate isEllipticCurveAlgorithmName(string curveName) {
|
||||
ellipticCurveNameToKeySizeAndFamilyMapping(curveName, _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates elliptic curve names to their key size and family.
|
||||
*
|
||||
* Note: As an exception, this predicate may be used for library modeling, as curve names are largely standardized.
|
||||
*
|
||||
* When modeling, verify that this predicate offers sufficient coverage for the library and handle edge-cases.
|
||||
*/
|
||||
bindingset[rawName]
|
||||
predicate ellipticCurveNameToKeySizeAndFamilyMapping(
|
||||
string rawName, int keySize, TEllipticCurveType curveFamily
|
||||
) {
|
||||
exists(string curveName | curveName = rawName.toUpperCase() |
|
||||
isSecCurve(curveName, keySize) and curveFamily = SEC()
|
||||
or
|
||||
isBrainpoolCurve(curveName, keySize) and curveFamily = BRAINPOOL()
|
||||
or
|
||||
isC2Curve(curveName, keySize) and curveFamily = C2()
|
||||
or
|
||||
isPrimeCurve(curveName, keySize) and curveFamily = PRIME()
|
||||
or
|
||||
isNumsCurve(curveName, keySize) and curveFamily = NUMS()
|
||||
or
|
||||
curveName = "ES256" and keySize = 256 and curveFamily = ES()
|
||||
or
|
||||
curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
or
|
||||
curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448()
|
||||
or
|
||||
// TODO: separate these into key agreement logic or sign/verify (ECDSA / ECDH)
|
||||
// or
|
||||
// curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
// or
|
||||
// curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
// or
|
||||
// curveName = "ED448" and keySize = 448 and curveFamily = CURVE448()
|
||||
// or
|
||||
// curveName = "X448" and keySize = 448 and curveFamily = CURVE448()
|
||||
curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2()
|
||||
)
|
||||
}
|
||||
|
||||
final class EllipticCurveNode extends AlgorithmNode, TEllipticCurve {
|
||||
EllipticCurveInstanceOrValueConsumer instance;
|
||||
|
||||
@@ -2712,7 +2290,9 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
|
||||
|
||||
override string getAlgorithmName() { result = this.getRawAlgorithmName() }
|
||||
|
||||
TEllipticCurveType getEllipticCurveType() { result = instance.asAlg().getEllipticCurveType() }
|
||||
EllipticCurveFamilyType getEllipticCurveFamilyType() {
|
||||
result = instance.asAlg().getEllipticCurveFamilyType()
|
||||
}
|
||||
|
||||
override predicate properties(string key, string value, Location location) {
|
||||
super.properties(key, value, location)
|
||||
|
||||
477
shared/quantum/codeql/quantum/experimental/Standardization.qll
Normal file
477
shared/quantum/codeql/quantum/experimental/Standardization.qll
Normal file
@@ -0,0 +1,477 @@
|
||||
/**
|
||||
* The `KeyOpAlg` module defines key operation algorithms types (e.g., symmetric ciphers, signatures, etc.)
|
||||
* and provides mapping of those types to string names and structural properties.
|
||||
*/
|
||||
module Types {
|
||||
module KeyOpAlg {
|
||||
/**
|
||||
* An algorithm used in key operations.
|
||||
*/
|
||||
newtype TAlgorithm =
|
||||
TSymmetricCipher(TSymmetricCipherType t) or
|
||||
TAsymmetricCipher(TAsymmetricCipherType t) or
|
||||
TSignature(TSignatureAlgorithmType t) or
|
||||
TKeyEncapsulation(TKemAlgorithmType t) or
|
||||
TUnknownKeyOperationAlgorithmType()
|
||||
|
||||
// Parameterized algorithm types
|
||||
newtype TSymmetricCipherType =
|
||||
AES() or
|
||||
ARIA() or
|
||||
BLOWFISH() or
|
||||
CAMELLIA() or
|
||||
CAST5() or
|
||||
CHACHA20() or
|
||||
DES() or
|
||||
DESX() or
|
||||
GOST() or
|
||||
IDEA() or
|
||||
KUZNYECHIK() or
|
||||
MAGMA() or
|
||||
TripleDES() or
|
||||
DoubleDES() or
|
||||
RC2() or
|
||||
RC4() or
|
||||
RC5() or
|
||||
SEED() or
|
||||
SM4() or
|
||||
OtherSymmetricCipherType()
|
||||
|
||||
newtype TAsymmetricCipherType =
|
||||
RSA() or
|
||||
OtherAsymmetricCipherType()
|
||||
|
||||
newtype TSignatureAlgorithmType =
|
||||
DSA() or
|
||||
ECDSA() or
|
||||
EDDSA() or // e.g., ED25519 or ED448
|
||||
OtherSignatureAlgorithmType()
|
||||
|
||||
newtype TKemAlgorithmType =
|
||||
Kyber() or
|
||||
FrodoKEM() or
|
||||
OtherKEMAlgorithmType()
|
||||
|
||||
newtype TCipherStructureType =
|
||||
Block() or
|
||||
Stream() or
|
||||
UnknownCipherStructureType()
|
||||
|
||||
class CipherStructureType extends TCipherStructureType {
|
||||
string toString() {
|
||||
result = "Block" and this = Block()
|
||||
or
|
||||
result = "Stream" and this = Stream()
|
||||
or
|
||||
result = "Unknown" and this = UnknownCipherStructureType()
|
||||
}
|
||||
}
|
||||
|
||||
private predicate symmetric_cipher_to_name_and_structure(
|
||||
TSymmetricCipherType type, string name, CipherStructureType s
|
||||
) {
|
||||
type = AES() and name = "AES" and s = Block()
|
||||
or
|
||||
type = ARIA() and name = "ARIA" and s = Block()
|
||||
or
|
||||
type = BLOWFISH() and name = "Blowfish" and s = Block()
|
||||
or
|
||||
type = CAMELLIA() and name = "Camellia" and s = Block()
|
||||
or
|
||||
type = CAST5() and name = "CAST5" and s = Block()
|
||||
or
|
||||
type = CHACHA20() and name = "ChaCha20" and s = Stream()
|
||||
or
|
||||
type = DES() and name = "DES" and s = Block()
|
||||
or
|
||||
type = DESX() and name = "DESX" and s = Block()
|
||||
or
|
||||
type = GOST() and name = "GOST" and s = Block()
|
||||
or
|
||||
type = IDEA() and name = "IDEA" and s = Block()
|
||||
or
|
||||
type = KUZNYECHIK() and name = "Kuznyechik" and s = Block()
|
||||
or
|
||||
type = MAGMA() and name = "Magma" and s = Block()
|
||||
or
|
||||
type = TripleDES() and name = "TripleDES" and s = Block()
|
||||
or
|
||||
type = DoubleDES() and name = "DoubleDES" and s = Block()
|
||||
or
|
||||
type = RC2() and name = "RC2" and s = Block()
|
||||
or
|
||||
type = RC4() and name = "RC4" and s = Stream()
|
||||
or
|
||||
type = RC5() and name = "RC5" and s = Block()
|
||||
or
|
||||
type = SEED() and name = "SEED" and s = Block()
|
||||
or
|
||||
type = SM4() and name = "SM4" and s = Block()
|
||||
or
|
||||
type = OtherSymmetricCipherType() and
|
||||
name = "UnknownSymmetricCipher" and
|
||||
s = UnknownCipherStructureType()
|
||||
}
|
||||
|
||||
class AlgorithmType extends TAlgorithm {
|
||||
string toString() {
|
||||
// Symmetric cipher algorithm
|
||||
symmetric_cipher_to_name_and_structure(this.(SymmetricCipherAlgorithmType).getType(),
|
||||
result, _)
|
||||
or
|
||||
// Asymmetric cipher algorithms
|
||||
this = TAsymmetricCipher(RSA()) and result = "RSA"
|
||||
or
|
||||
this = TAsymmetricCipher(OtherAsymmetricCipherType()) and result = "UnknownAsymmetricCipher"
|
||||
or
|
||||
// Signature algorithms
|
||||
this = TSignature(DSA()) and result = "DSA"
|
||||
or
|
||||
this = TSignature(ECDSA()) and result = "ECDSA"
|
||||
or
|
||||
this = TSignature(EDDSA()) and result = "EDSA"
|
||||
or
|
||||
this = TSignature(OtherSignatureAlgorithmType()) and result = "UnknownSignature"
|
||||
or
|
||||
// Key Encapsulation Mechanisms
|
||||
this = TKeyEncapsulation(Kyber()) and result = "Kyber"
|
||||
or
|
||||
this = TKeyEncapsulation(FrodoKEM()) and result = "FrodoKEM"
|
||||
or
|
||||
this = TKeyEncapsulation(OtherKEMAlgorithmType()) and result = "UnknownKEM"
|
||||
or
|
||||
// Unknown
|
||||
this = TUnknownKeyOperationAlgorithmType() and result = "Unknown"
|
||||
}
|
||||
|
||||
int getImplicitKeySize() {
|
||||
this = TSymmetricCipher(DES()) and result = 56
|
||||
or
|
||||
this = TSymmetricCipher(DESX()) and result = 184
|
||||
or
|
||||
this = TSymmetricCipher(DoubleDES()) and result = 112
|
||||
or
|
||||
this = TSymmetricCipher(TripleDES()) and result = 168
|
||||
or
|
||||
this = TSymmetricCipher(CHACHA20()) and result = 256
|
||||
or
|
||||
this = TSymmetricCipher(IDEA()) and result = 128
|
||||
or
|
||||
this = TSymmetricCipher(KUZNYECHIK()) and result = 256
|
||||
or
|
||||
this = TSymmetricCipher(MAGMA()) and result = 256
|
||||
or
|
||||
this = TSymmetricCipher(SM4()) and result = 128
|
||||
or
|
||||
this = TSymmetricCipher(SEED()) and result = 128
|
||||
}
|
||||
}
|
||||
|
||||
class SymmetricCipherAlgorithmType extends AlgorithmType, TSymmetricCipher {
|
||||
TSymmetricCipherType type;
|
||||
|
||||
SymmetricCipherAlgorithmType() { this = TSymmetricCipher(type) }
|
||||
|
||||
TSymmetricCipherType getType() { result = type }
|
||||
|
||||
TCipherStructureType getStructureType() {
|
||||
symmetric_cipher_to_name_and_structure(type, _, result)
|
||||
}
|
||||
}
|
||||
|
||||
class AsymmetricCipherAlgorithmType extends AlgorithmType, TAsymmetricCipher {
|
||||
TAsymmetricCipherType type;
|
||||
|
||||
AsymmetricCipherAlgorithmType() { this = TAsymmetricCipher(type) }
|
||||
|
||||
TAsymmetricCipherType getType() { result = type }
|
||||
}
|
||||
|
||||
newtype TModeOfOperationType =
|
||||
ECB() or // Not secure, widely used
|
||||
CBC() or // Vulnerable to padding oracle attacks
|
||||
CFB() or
|
||||
GCM() or // Widely used AEAD mode (TLS 1.3, SSH, IPsec)
|
||||
CTR() or // Fast stream-like encryption (SSH, disk encryption)
|
||||
XTS() or // Standard for full-disk encryption (BitLocker, LUKS, FileVault)
|
||||
CCM() or // Used in lightweight cryptography (IoT, WPA2)
|
||||
SIV() or // Misuse-resistant encryption, used in secure storage
|
||||
OCB() or // Efficient AEAD mode
|
||||
OFB() or
|
||||
OtherMode()
|
||||
|
||||
class ModeOfOperationType extends TModeOfOperationType {
|
||||
string toString() {
|
||||
this = ECB() and result = "ECB"
|
||||
or
|
||||
this = CBC() and result = "CBC"
|
||||
or
|
||||
this = GCM() and result = "GCM"
|
||||
or
|
||||
this = CTR() and result = "CTR"
|
||||
or
|
||||
this = XTS() and result = "XTS"
|
||||
or
|
||||
this = CCM() and result = "CCM"
|
||||
or
|
||||
this = SIV() and result = "SIV"
|
||||
or
|
||||
this = OCB() and result = "OCB"
|
||||
or
|
||||
this = CFB() and result = "CFB"
|
||||
or
|
||||
this = OFB() and result = "OFB"
|
||||
}
|
||||
}
|
||||
|
||||
newtype TPaddingSchemeType =
|
||||
PKCS1_v1_5() or // RSA encryption/signing padding
|
||||
PSS() or
|
||||
PKCS7() or // Standard block cipher padding (PKCS5 for 8-byte blocks)
|
||||
ANSI_X9_23() or // Zero-padding except last byte = padding length
|
||||
NoPadding() or // Explicit no-padding
|
||||
OAEP() or // RSA OAEP padding
|
||||
OtherPadding()
|
||||
|
||||
class PaddingSchemeType extends TPaddingSchemeType {
|
||||
string toString() {
|
||||
this = ANSI_X9_23() and result = "ANSI_X9_23"
|
||||
or
|
||||
this = NoPadding() and result = "NoPadding"
|
||||
or
|
||||
this = OAEP() and result = "OAEP"
|
||||
or
|
||||
this = PKCS1_v1_5() and result = "PKCS1_v1_5"
|
||||
or
|
||||
this = PKCS7() and result = "PKCS7"
|
||||
or
|
||||
this = PSS() and result = "PSS"
|
||||
or
|
||||
this = OtherPadding() and result = "UnknownPadding"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newtype THashType =
|
||||
BLAKE2B() or
|
||||
BLAKE2S() or
|
||||
GOSTHash() or
|
||||
MD2() or
|
||||
MD4() or
|
||||
MD5() or
|
||||
MDC2() or
|
||||
POLY1305() or
|
||||
SHA1() or
|
||||
SHA2() or
|
||||
SHA3() or
|
||||
SHAKE() or
|
||||
SM3() or
|
||||
RIPEMD160() or
|
||||
WHIRLPOOL() or
|
||||
OtherHashType()
|
||||
|
||||
class HashType extends THashType {
|
||||
final string toString() {
|
||||
this = BLAKE2B() and result = "BLAKE2B"
|
||||
or
|
||||
this = BLAKE2S() and result = "BLAKE2S"
|
||||
or
|
||||
this = RIPEMD160() and result = "RIPEMD160"
|
||||
or
|
||||
this = MD2() and result = "MD2"
|
||||
or
|
||||
this = MD4() and result = "MD4"
|
||||
or
|
||||
this = MD5() and result = "MD5"
|
||||
or
|
||||
this = POLY1305() and result = "POLY1305"
|
||||
or
|
||||
this = SHA1() and result = "SHA1"
|
||||
or
|
||||
this = SHA2() and result = "SHA2"
|
||||
or
|
||||
this = SHA3() and result = "SHA3"
|
||||
or
|
||||
this = SHAKE() and result = "SHAKE"
|
||||
or
|
||||
this = SM3() and result = "SM3"
|
||||
or
|
||||
this = WHIRLPOOL() and result = "WHIRLPOOL"
|
||||
or
|
||||
this = OtherHashType() and result = "UnknownHash"
|
||||
}
|
||||
}
|
||||
|
||||
newtype TMacType =
|
||||
HMAC() or
|
||||
CMAC() or
|
||||
OtherMacType()
|
||||
|
||||
class MacType extends TMacType {
|
||||
string toString() {
|
||||
this = HMAC() and result = "HMAC"
|
||||
or
|
||||
this = CMAC() and result = "CMAC"
|
||||
or
|
||||
this = OtherMacType() and result = "UnknownMacType"
|
||||
}
|
||||
}
|
||||
|
||||
// Key agreement algorithms
|
||||
newtype TKeyAgreementType =
|
||||
DH() or // Diffie-Hellman
|
||||
EDH() or // Ephemeral Diffie-Hellman
|
||||
ECDH() or // Elliptic Curve Diffie-Hellman
|
||||
// NOTE: for now ESDH is considered simply EDH
|
||||
//ESDH() or // Ephemeral-Static Diffie-Hellman
|
||||
// Note: x25519 and x448 are applications of ECDH
|
||||
OtherKeyAgreementType()
|
||||
|
||||
class KeyAgreementType extends TKeyAgreementType {
|
||||
string toString() {
|
||||
this = DH() and result = "DH"
|
||||
or
|
||||
this = EDH() and result = "EDH"
|
||||
or
|
||||
this = ECDH() and result = "ECDH"
|
||||
or
|
||||
this = OtherKeyAgreementType() and result = "UnknownKeyAgreementType"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic curve algorithms
|
||||
*/
|
||||
newtype TEllipticCurveFamilyType =
|
||||
NIST() or
|
||||
SEC() or
|
||||
NUMS() or
|
||||
PRIME() or
|
||||
BRAINPOOL() or
|
||||
CURVE25519() or
|
||||
CURVE448() or
|
||||
C2() or
|
||||
SM2() or
|
||||
ES() or
|
||||
OtherEllipticCurveType()
|
||||
|
||||
class EllipticCurveFamilyType extends TEllipticCurveFamilyType {
|
||||
string toString() {
|
||||
this = NIST() and result = "NIST"
|
||||
or
|
||||
this = SEC() and result = "SEC"
|
||||
or
|
||||
this = NUMS() and result = "NUMS"
|
||||
or
|
||||
this = PRIME() and result = "PRIME"
|
||||
or
|
||||
this = BRAINPOOL() and result = "BRAINPOOL"
|
||||
or
|
||||
this = CURVE25519() and result = "CURVE25519"
|
||||
or
|
||||
this = CURVE448() and result = "CURVE448"
|
||||
or
|
||||
this = C2() and result = "C2"
|
||||
or
|
||||
this = SM2() and result = "SM2"
|
||||
or
|
||||
this = ES() and result = "ES"
|
||||
or
|
||||
this = OtherEllipticCurveType() and result = "UnknownEllipticCurveType"
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isBrainpoolCurve(string curveName, int keySize) {
|
||||
// ALL BRAINPOOL CURVES
|
||||
keySize in [160, 192, 224, 256, 320, 384, 512] and
|
||||
(
|
||||
curveName = "BRAINPOOLP" + keySize + "R1"
|
||||
or
|
||||
curveName = "BRAINPOOLP" + keySize + "T1"
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSecCurve(string curveName, int keySize) {
|
||||
// ALL SEC CURVES
|
||||
keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and
|
||||
exists(string suff | suff in ["R1", "R2", "K1"] |
|
||||
curveName = "SECT" + keySize + suff or
|
||||
curveName = "SECP" + keySize + suff
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isC2Curve(string curveName, int keySize) {
|
||||
// ALL C2 CURVES
|
||||
keySize in [163, 176, 191, 208, 239, 272, 304, 359, 368, 431] and
|
||||
exists(string pre, string suff |
|
||||
pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"]
|
||||
|
|
||||
curveName = "C2" + pre + keySize + suff
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isPrimeCurve(string curveName, int keySize) {
|
||||
// ALL PRIME CURVES
|
||||
keySize in [192, 239, 256] and
|
||||
exists(string suff | suff in ["V1", "V2", "V3"] | curveName = "PRIME" + keySize + suff)
|
||||
}
|
||||
|
||||
private predicate isNumsCurve(string curveName, int keySize) {
|
||||
// ALL NUMS CURVES
|
||||
keySize in [256, 384, 512] and
|
||||
exists(string suff | suff = "T1" | curveName = "NUMSP" + keySize + suff)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `name` corresponds to a known elliptic curve.
|
||||
*
|
||||
* Note: As an exception, this predicate may be used for library modeling, as curve names are largely standardized.
|
||||
*
|
||||
* When modeling, verify that this predicate offers sufficient coverage for the library and handle edge-cases.
|
||||
*/
|
||||
bindingset[curveName]
|
||||
predicate isEllipticCurveAlgorithmName(string curveName) {
|
||||
ellipticCurveNameToKnownKeySizeAndFamilyMapping(curveName, _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates elliptic curve names to their key size and family.
|
||||
*
|
||||
* Note: As an exception, this predicate may be used for library modeling, as curve names are largely standardized.
|
||||
*
|
||||
* When modeling, verify that this predicate offers sufficient coverage for the library and handle edge-cases.
|
||||
*/
|
||||
bindingset[rawName]
|
||||
predicate ellipticCurveNameToKnownKeySizeAndFamilyMapping(
|
||||
string rawName, int keySize, TEllipticCurveFamilyType curveFamily
|
||||
) {
|
||||
exists(string curveName | curveName = rawName.toUpperCase() |
|
||||
isSecCurve(curveName, keySize) and curveFamily = SEC()
|
||||
or
|
||||
isBrainpoolCurve(curveName, keySize) and curveFamily = BRAINPOOL()
|
||||
or
|
||||
isC2Curve(curveName, keySize) and curveFamily = C2()
|
||||
or
|
||||
isPrimeCurve(curveName, keySize) and curveFamily = PRIME()
|
||||
or
|
||||
isNumsCurve(curveName, keySize) and curveFamily = NUMS()
|
||||
or
|
||||
curveName = "ES256" and keySize = 256 and curveFamily = ES()
|
||||
or
|
||||
curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
or
|
||||
curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448()
|
||||
or
|
||||
// TODO: separate these into key agreement logic or sign/verify (ECDSA / ECDH)
|
||||
// or
|
||||
// curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
// or
|
||||
// curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519()
|
||||
// or
|
||||
// curveName = "ED448" and keySize = 448 and curveFamily = CURVE448()
|
||||
// or
|
||||
// curveName = "X448" and keySize = 448 and curveFamily = CURVE448()
|
||||
curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2()
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user