diff --git a/java/ql/lib/change-notes/2026-03-27-add-ec-to-secure-algorithms.md b/java/ql/lib/change-notes/2026-03-27-add-ec-to-secure-algorithms.md new file mode 100644 index 000000000000..ee53bedd4176 --- /dev/null +++ b/java/ql/lib/change-notes/2026-03-27-add-ec-to-secure-algorithms.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* The `java/potentially-weak-cryptographic-algorithm` query no longer flags Elliptic Curve algorithms (`EC`, `ECDSA`, `ECDH`, `EdDSA`, `Ed25519`, `Ed448`, `XDH`, `X25519`, `X448`), HMAC-based algorithms (`HMACSHA1`, `HMACSHA256`, `HMACSHA384`, `HMACSHA512`), or PBKDF2 key derivation as potentially insecure. These are modern, secure algorithms recommended by NIST and other standards bodies. This will reduce the number of false positives for this query. +* The first argument of the method `getInstance` of `java.security.Signature` is now modeled as a sink for `java/potentially-weak-cryptographic-algorithm`, `java/weak-cryptographic-algorithm` and `java/rsa-without-oaep`. This will increase the number of alerts for these queries. diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index b0a0fc72df77..6af8d29cc4a1 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -259,7 +259,13 @@ string getASecureAlgorithmName() { result = [ "RSA", "SHA-?(256|384|512)", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))", - "Blowfish", "ECIES", "SHA3-(256|384|512)" + "Blowfish", "ECIES", "SHA3-(256|384|512)", + // Elliptic Curve algorithms: EC (key generation), ECDSA (signatures), ECDH (key agreement), + // EdDSA/Ed25519/Ed448 (Edwards-curve signatures), XDH/X25519/X448 (key agreement). + // These are modern, secure algorithms recommended by NIST and other standards bodies. + "EC", "ECDSA", "ECDH", "EdDSA", "Ed25519", "Ed448", "XDH", "X25519", "X448", + // HMAC-based algorithms and key derivation functions. + "HMACSHA(1|256|384|512)", "HmacSHA(1|256|384|512)", "PBKDF2" ] } @@ -366,9 +372,13 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec { exists(Constructor c | c.getAReference() = this | c.getDeclaringType().hasQualifiedName("java.security", "Signature") ) + or + exists(Method m | m.getAReference() = this | + m.hasQualifiedName("java.security", "Signature", "getInstance") + ) } - override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) } + override Expr getAlgoSpec() { result = this.(Call).getArgument(0) } } /** A call to the `getInstance` method declared in `java.security.KeyPairGenerator`. */ diff --git a/java/ql/test/query-tests/security/CWE-327/semmle/tests/Test.java b/java/ql/test/query-tests/security/CWE-327/semmle/tests/Test.java index 2f66d4996393..23aff65161c9 100644 --- a/java/ql/test/query-tests/security/CWE-327/semmle/tests/Test.java +++ b/java/ql/test/query-tests/security/CWE-327/semmle/tests/Test.java @@ -46,6 +46,48 @@ public void test() { cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8")); + + KeyPairGenerator keyPairGenerator; + + // GOOD: EC is a secure algorithm for key pair generation + keyPairGenerator = KeyPairGenerator.getInstance("EC"); + + // GOOD: ECDSA is a secure signature algorithm + Signature ecdsaSig = Signature.getInstance("ECDSA"); + + // GOOD: ECDH is a secure algorithm for key agreement + KeyAgreement ecdhKa = KeyAgreement.getInstance("ECDH"); + + // GOOD: EdDSA is a secure algorithm (Edwards-curve Digital Signature Algorithm) + keyPairGenerator = KeyPairGenerator.getInstance("EdDSA"); + + // GOOD: Ed25519 is a secure algorithm for key pair generation + keyPairGenerator = KeyPairGenerator.getInstance("Ed25519"); + + // GOOD: Ed448 is a secure algorithm for key pair generation + keyPairGenerator = KeyPairGenerator.getInstance("Ed448"); + + // GOOD: XDH is a secure algorithm for key agreement + KeyAgreement xdhKa = KeyAgreement.getInstance("XDH"); + + // GOOD: X25519 is a secure algorithm for key agreement + KeyAgreement x25519Ka = KeyAgreement.getInstance("X25519"); + + // GOOD: X448 is a secure algorithm for key agreement + KeyAgreement x448Ka = KeyAgreement.getInstance("X448"); + + // GOOD: SHA256withECDSA is a secure signature algorithm + Signature sha256Ecdsa = Signature.getInstance("SHA256withECDSA"); + + // GOOD: HMAC-based SecretKeySpec should not be flagged + new SecretKeySpec(null, "HMACSHA1"); + new SecretKeySpec(null, "HMACSHA256"); + new SecretKeySpec(null, "HMACSHA384"); + new SecretKeySpec(null, "SHA384withECDSA"); + + // GOOD: PBKDF2 key derivation is a secure algorithm + SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + } catch (Exception e) { // fail }