Crypto: Refactor type name mapping and fix QL-for-QL alerts

This commit is contained in:
Nicolas Will
2025-06-25 20:08:14 +02:00
parent 710e08088f
commit 14472bf744
9 changed files with 584 additions and 518 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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, _)
}
}

View File

@@ -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()
}
}

View File

@@ -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() {

View File

@@ -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

View File

@@ -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 }

View File

@@ -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)

View 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()
)
}
}