Skip to content
Closed
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
@@ -0,0 +1,22 @@
/**
* @name Insecure nonce at a cipher operation
* @id java/quantum/insecure-nonce
* @description A nonce is generated from a source that is not secure. This can lead to
* vulnerabilities such as replay attacks or key recovery.
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import experimental.quantum.Language

predicate isInsecureNonceSource(Crypto::NonceArtifactNode n, Crypto::NodeBase src) {
src = n.getSourceNode() and
not src.asElement() instanceof SecureRandomnessInstance
}

from Crypto::KeyOperationNode op, Crypto::NodeBase src
where isInsecureNonceSource(op.getANonce(), src)
select op, "Operation uses insecure nonce source $@", src, src.toString()
24 changes: 24 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/NonAESGCMCipher.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @name Cipher not AES-GCM mode
* @id java/quantum/non-aes-gcm
* @description An AES cipher is in use without GCM
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import experimental.quantum.Language

class NonAESGCMAlgorithmNode extends Crypto::KeyOperationAlgorithmNode {
NonAESGCMAlgorithmNode() {
this.getAlgorithmType() = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::AES()) and
this.getModeOfOperation().getModeType() != Crypto::KeyOpAlg::GCM()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this.getModeOfOperation().getModeType() != Crypto::KeyOpAlg::GCM()
not this.getModeOfOperation().getModeType() = Crypto::KeyOpAlg::GCM()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not actually we want we want, chatting with @nicolaswill in a side channel, so disregard.

}
}

from Crypto::KeyOperationNode op, Crypto::KeyOperationOutputNode codeNode
where op.getAKnownAlgorithm() instanceof NonAESGCMAlgorithmNode and
codeNode = op.getAnOutputArtifact()
select op, "Non-AES-GCM instance."
17 changes: 17 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/NonceReuse.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @name Reuse of cryptographic nonce
* @description Reuse of nonce in cryptographic operations can lead to vulnerabilities.
* @id java/quantum/reused-nonce
* @kind problem
* @problem.severity error
* @precision medium
* @tags quantum
* experimental
*/

import java
import ArtifactReuse

from Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2
where isArtifactReuse(nonce1, nonce2)
select nonce1, "Reuse with nonce $@", nonce2, nonce2.toString()
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* @id java/quantum/unknown-kdf-iteration-count
* @kind problem
* @precision medium
* @severity warning
* @tags quantum
* experimental
*/
Expand Down
24 changes: 24 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/WeakAsymmetric.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @name Weak Asymetric Key Size
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Asymetric' to 'Asymmetric'.

Suggested change
* @name Weak Asymetric Key Size
* @name Weak Asymmetric Key Size

Copilot uses AI. Check for mistakes.

* @id java/quantum/weak-asymmetric-key-size
* @description An asymmetric cipher with a short key size is in use
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import java
import experimental.quantum.Language

from Crypto::KeyOperationAlgorithmNode op, DataFlow::Node configSrc, int keySize, string algName
where
keySize = op.getKeySizeFixed() and
keySize < 2048 and
algName = op.getAlgorithmName() and
// Can't be an elliptic curve
not Crypto::isEllipticCurveAlgorithmName(algName)
select op,
"Use of weak asymmetric key size (int bits)" + keySize.toString() + " for algorithm " +
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message formatting is unclear. '(int bits)' should be '(' + keySize.toString() + ' bits)' for proper readability.

Suggested change
"Use of weak asymmetric key size (int bits)" + keySize.toString() + " for algorithm " +
"Use of weak asymmetric key size (" + keySize.toString() + " bits) for algorithm " +

Copilot uses AI. Check for mistakes.

algName.toString() + " at config source $@", configSrc, configSrc.toString()
29 changes: 29 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/WeakBlockModes.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @name Weak AES Block mode
* @id java/quantum/weak-block-modes
* @description An AES cipher is in use with an insecure block mode
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import java
import experimental.quantum.Language

class WeakAESBlockModeAlgNode extends Crypto::KeyOperationAlgorithmNode {
WeakAESBlockModeAlgNode() {
this.getAlgorithmType() = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::AES()) and
(this.getModeOfOperation().getModeType() = Crypto::KeyOpAlg::ECB() or
this.getModeOfOperation().getModeType() = Crypto::KeyOpAlg::CFB() or
this.getModeOfOperation().getModeType() = Crypto::KeyOpAlg::OFB() or
this.getModeOfOperation().getModeType() = Crypto::KeyOpAlg::CTR()
)
}
}

from Crypto::KeyOperationNode op, Crypto::KeyOperationOutputNode codeNode
where op.getAKnownAlgorithm() instanceof WeakAESBlockModeAlgNode and
codeNode = op.getAnOutputArtifact()
select op, "Weak AES block mode instance."
19 changes: 19 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/WeakHashing.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @name Weak hashes
* @description Finds uses of cryptographic hashing algorithms that are unapproved or otherwise weak.
* @id java/quantum/slices/weak-hashes
* @kind problem
* @problem.severity error
* @precision high
* @tags external/cwe/cwe-327
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs quantum and experimental tags.

*/

import java
import experimental.quantum.Language

from Crypto::HashAlgorithmNode alg, string name, string msg
where
name = alg.getAlgorithmName() and
not name in ["SHA256", "SHA384", "SHA512", "SHA-256", "SHA-384", "SHA-512"] and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like the comment on symmetric algorithms, the hash family and hash digest size should be used rather than string comparisons. The appropriate predicates/classes to use would be HashType (getHashFamily()) and getDigestLength().

Typing this out also makes me realize we need to standardize those predicate and class names...

msg = "Use of unapproved hash algorithm or API " + name + "."
select alg, msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @name Weak known key derivation function iteration count
* @description Detects key derivation operations with a known weak iteration count.
* @id java/quantum/weak-kdf-iteration-count
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import java
import experimental.quantum.Language

from Crypto::KeyDerivationOperationNode op, Literal l
where
op.getIterationCount().asElement() = l and
l.getValue().toInt() < 100000
select op, "Key derivation operation configures iteration count below 100k: $@", l,
l.getValue().toString()
20 changes: 20 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/WeakKDFKeySize.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @name Weak known key derivation function output length
* @description Detects key derivation operations with a known weak output length
* @id java/quantum/weak-kdf-iteration-count
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @id should be 'java/quantum/weak-kdf-key-size' to match the query name and purpose, not 'weak-kdf-iteration-count'.

Suggested change
* @id java/quantum/weak-kdf-iteration-count
* @id java/quantum/weak-kdf-key-size

Copilot uses AI. Check for mistakes.

* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import java
import experimental.quantum.Language

from Crypto::KeyDerivationOperationNode op, Literal l
where
op.getOutputKeySize().asElement() = l and
l.getValue().toInt() < 256
select op, "Key derivation operation configures output key length below 256: $@", l,
l.getValue().toString()
24 changes: 24 additions & 0 deletions java/ql/src/experimental/quantum/Analysis/WeakRSA.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @name Cipher is Weak RSA Implementation
* @id java/quantum/weak-rsa
* @description RSA with a key length <2048 found
* @kind problem
* @problem.severity error
* @precision high
* @tags quantum
* experimental
*/

import experimental.quantum.Language

class WeakRSAAlgorithmNode extends Crypto::KeyOperationAlgorithmNode {

Check warning

Code scanning / CodeQL

Acronyms should be PascalCase/camelCase. Warning

Acronyms in WeakRSAAlgorithmNode should be PascalCase/camelCase.
WeakRSAAlgorithmNode() {
this.getAlgorithmType() = Crypto::KeyOpAlg::TAsymmetricCipher(Crypto::KeyOpAlg::RSA()) and
this.getKeySizeFixed() < 2048
}
}

from Crypto::KeyOperationNode op, string message
where op.getAKnownAlgorithm() instanceof WeakRSAAlgorithmNode and
message = "Weak RSA instance found with key length <2048"
select op, message
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @name Weak symmetric ciphers
* @description Finds uses of cryptographic symmetric cipher algorithms that are unapproved or otherwise weak.
* @id java/quantum/slices/weak-ciphers
* @kind problem
* @problem.severity error
* @precision high
* @tags external/cwe/cwe-327
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs quantum and experimental tags.

*/

import java
import experimental.quantum.Language

from Crypto::KeyOperationAlgorithmNode alg, string name, string msg
where
name = alg.getAlgorithmName() and
name in ["DES", "TripleDES", "DoubleDES", "RC2", "RC4", "IDEA", "Blowfish"] and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than comparing name strings, the standardized types in Crypto::KeyOpAlg should be compared against getAlgorithmType. Here is an example of that syntax: this.getAlgorithmType() = KeyOpAlg::TMac(KeyOpAlg::CMAC()). To avoid redundant typing of the module namespaces, the KeyOpAlg module could optionally also be imported as follows: import Crypto::KeyOpAlg as Alg.

msg = "Use of unapproved symmetric cipher algorithm or API: " + name + "."
select alg, msg
Loading