Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ predicate isSymmetricEncryptionAlgorithm(string name) {
predicate isKeyDerivationAlgorithm(string name) {
name =
[
"ARGON2", "CONCATKDF", "CONCATKDFHASH", "CONCATKDFHMAC", "KBKDFCMAC", "BCRYPT", "HKDF",
"HKDFEXPAND", "KBKDF", "KBKDFHMAC", "PBKDF1", "PBKDF2", "PBKDF2HMAC", "PKCS5", "SCRYPT",
"X963KDF", "EVPKDF"
"ARGON2", "ARGON2D", "ARGON2I", "ARGON2ID", "CONCATKDF", "CONCATKDFHASH", "CONCATKDFHMAC",
"KBKDFCMAC", "BCRYPT", "HKDF", "HKDFEXPAND", "KBKDF", "KBKDFHMAC", "PBKDF1", "PBKDF2",
"PBKDF2HMAC", "PKCS5", "SCRYPT", "X963KDF", "EVPKDF"
]
}

Expand Down
8 changes: 8 additions & 0 deletions python/ql/lib/experimental/cryptography/CryptoArtifact.qll
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ abstract class KeyDerivationOperation extends CryptographicOperation {

DataFlow::Node getHashConfigSrc() { none() }

DataFlow::Node getLanesConfigSrc() { none() }

DataFlow::Node getMemoryCostConfigSrc() { none() }

// TODO: get encryption algorithm for CBC-based KDF?
DataFlow::Node getDerivedKeySizeSrc() { none() }

Expand All @@ -147,6 +151,10 @@ abstract class KeyDerivationOperation extends CryptographicOperation {

abstract predicate requiresHash();

abstract predicate requiresLanes();

abstract predicate requiresMemoryCost();

//abstract predicate requiresKeySize(); // Going to assume all requires a size
abstract predicate requiresMode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ module KDF {
.getMember(algName) and
result = algModule.asSource() and
// https://github.com/pyca/cryptography/tree/main/src/cryptography/hazmat/primitives/kdf
member in ["concatkdf", "hkdf", "kbkdf", "pbkdf2", "scrypt", "x963kdf"] and
member in ["argon2", "concatkdf", "hkdf", "kbkdf", "pbkdf2", "scrypt", "x963kdf"] and
algName in [
"ConcatKDFHash", "ConcatKDFHMAC", "HKDF", "HKDFExpand", "KBKDFCMAC", "KBKDFHMAC",
"PBKDF2HMAC", "Scrypt", "X963KDF"
"Argon2d", "Argon2i", "Argon2id", "ConcatKDFHash", "ConcatKDFHMAC", "HKDF",
"HKDFExpand", "KBKDFCMAC", "KBKDFHMAC", "PBKDF2HMAC", "Scrypt", "X963KDF"
]
)
}
Expand Down Expand Up @@ -111,21 +111,31 @@ module KDF {
}

override predicate requiresSalt() {
this.getAlgorithm().getKDFName() in ["PBKDF2HMAC", "CONCATKDFHMAC", "HKDF"]
this.getAlgorithm().getKDFName() in ["PBKDF2HMAC", "CONCATKDFHMAC", "HKDF", "SCRYPT", "ARGON2"]
}

override predicate requiresIteration() { this.getAlgorithm().getKDFName() in ["PBKDF2HMAC"] }
override predicate requiresIteration() { this.getAlgorithm().getKDFName() in ["PBKDF2HMAC", "ARGON2"] }

override predicate requiresLanes() { this.getAlgorithm().getKDFName() in ["ARGON2"] }

override predicate requiresMemoryCost() { this.getAlgorithm().getKDFName() in ["ARGON2"] }

override DataFlow::Node getIterationSizeSrc() {
this.requiresIteration() and
// ASSUMPTION: ONLY EVER in arg 3 in PBKDF2HMAC
result = Utils::getUltimateSrcFromApiNode(this.getParameter(3, "iterations"))
if this.getAlgorithm().getKDFName() = "ARGON2"
then result = Utils::getUltimateSrcFromApiNode(this.getKeywordParameter("iterations"))
else
// ASSUMPTION: ONLY EVER in arg 3 in PBKDF2HMAC
result = Utils::getUltimateSrcFromApiNode(this.getParameter(3, "iterations"))
}

override DataFlow::Node getSaltConfigSrc() {
this.requiresSalt() and
// ARGON2 variants have it as a keyword-only parameter
if this.getAlgorithm().getKDFName() = "ARGON2"
then result = Utils::getUltimateSrcFromApiNode(this.getKeywordParameter("salt"))
// SCRYPT has it in arg 1
if this.getAlgorithm().getKDFName() = "SCRYPT"
else if this.getAlgorithm().getKDFName() = "SCRYPT"
then result = Utils::getUltimateSrcFromApiNode(this.getParameter(1, "salt"))
else
// EVERYTHING ELSE that uses salt is in arg 2
Expand All @@ -138,9 +148,23 @@ module KDF {
result = Utils::getUltimateSrcFromApiNode(this.getParameter(0, "algorithm"))
}

override DataFlow::Node getLanesConfigSrc() {
this.requiresLanes() and
// ASSUMPTION: ONLY EVER in keyword parameter
result = Utils::getUltimateSrcFromApiNode(this.getKeywordParameter("lanes"))
}

override DataFlow::Node getMemoryCostConfigSrc() {
this.requiresMemoryCost() and
// ASSUMPTION: ONLY EVER in keyword parameter
result = Utils::getUltimateSrcFromApiNode(this.getKeywordParameter("memory_cost"))
}

// TODO: get encryption algorithm for CBC-based KDF?
override DataFlow::Node getDerivedKeySizeSrc() {
if this.getAlgorithm().getKDFName() in ["KBKDFHMAC", "KBKDFCMAC"]
if this.getAlgorithm().getKDFName() = "ARGON2"
then result = Utils::getUltimateSrcFromApiNode(this.getKeywordParameter("length"))
else if this.getAlgorithm().getKDFName() in ["KBKDFHMAC", "KBKDFCMAC"]
then result = Utils::getUltimateSrcFromApiNode(this.getParameter(2, "length"))
else result = Utils::getUltimateSrcFromApiNode(this.getParameter(1, "length"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ module KDF {
override predicate requiresSalt() { any() }

override predicate requiresIteration() { any() }

override predicate requiresLanes() { none() }

override predicate requiresMemoryCost() { none() }
}

// TODO: better modeling of scrypt
Expand Down Expand Up @@ -233,5 +237,9 @@ module KDF {
override predicate requiresSalt() { any() }

override predicate requiresIteration() { none() }

override predicate requiresLanes() { none() }

override predicate requiresMemoryCost() { none() }
}
}