mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
Merge pull request #10785 from jcogs33/insuff-key-size-globalflow-keysize
Java: Promote insufficient key size query from experimental
This commit is contained in:
@@ -88,6 +88,22 @@ class KeyPairGenerator extends RefType {
|
||||
KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") }
|
||||
}
|
||||
|
||||
/** The `init` method declared in `javax.crypto.KeyGenerator`. */
|
||||
class KeyGeneratorInitMethod extends Method {
|
||||
KeyGeneratorInitMethod() {
|
||||
this.getDeclaringType() instanceof KeyGenerator and
|
||||
this.hasName("init")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `initialize` method declared in `java.security.KeyPairGenerator`. */
|
||||
class KeyPairGeneratorInitMethod extends Method {
|
||||
KeyPairGeneratorInitMethod() {
|
||||
this.getDeclaringType() instanceof KeyPairGenerator and
|
||||
this.hasName("initialize")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */
|
||||
class HostnameVerifierVerify extends Method {
|
||||
HostnameVerifierVerify() {
|
||||
@@ -367,8 +383,8 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec {
|
||||
override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) }
|
||||
}
|
||||
|
||||
/** A method call to the Java class `java.security.KeyPairGenerator`. */
|
||||
class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec {
|
||||
/** A call to the `getInstance` method declared in `java.security.KeyPairGenerator`. */
|
||||
class JavaSecurityKeyPairGenerator extends JavaSecurityAlgoSpec {
|
||||
JavaSecurityKeyPairGenerator() {
|
||||
exists(Method m | m.getAReference() = this |
|
||||
m.getDeclaringType() instanceof KeyPairGenerator and
|
||||
@@ -378,3 +394,53 @@ class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec {
|
||||
|
||||
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
|
||||
}
|
||||
|
||||
/** The Java class `java.security.AlgorithmParameterGenerator`. */
|
||||
class AlgorithmParameterGenerator extends RefType {
|
||||
AlgorithmParameterGenerator() {
|
||||
this.hasQualifiedName("java.security", "AlgorithmParameterGenerator")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `init` method declared in `java.security.AlgorithmParameterGenerator`. */
|
||||
class AlgoParamGeneratorInitMethod extends Method {
|
||||
AlgoParamGeneratorInitMethod() {
|
||||
this.getDeclaringType() instanceof AlgorithmParameterGenerator and
|
||||
this.hasName("init")
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to the `getInstance` method declared in `java.security.AlgorithmParameterGenerator`. */
|
||||
class JavaSecurityAlgoParamGenerator extends JavaSecurityAlgoSpec {
|
||||
JavaSecurityAlgoParamGenerator() {
|
||||
exists(Method m | m.getAReference() = this |
|
||||
m.getDeclaringType() instanceof AlgorithmParameterGenerator and
|
||||
m.getName() = "getInstance"
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
|
||||
}
|
||||
|
||||
/** An implementation of the `java.security.spec.AlgorithmParameterSpec` interface. */
|
||||
abstract class AlgorithmParameterSpec extends RefType { }
|
||||
|
||||
/** The Java class `java.security.spec.ECGenParameterSpec`. */
|
||||
class EcGenParameterSpec extends AlgorithmParameterSpec {
|
||||
EcGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") }
|
||||
}
|
||||
|
||||
/** The Java class `java.security.spec.RSAKeyGenParameterSpec`. */
|
||||
class RsaKeyGenParameterSpec extends AlgorithmParameterSpec {
|
||||
RsaKeyGenParameterSpec() { this.hasQualifiedName("java.security.spec", "RSAKeyGenParameterSpec") }
|
||||
}
|
||||
|
||||
/** The Java class `java.security.spec.DSAGenParameterSpec`. */
|
||||
class DsaGenParameterSpec extends AlgorithmParameterSpec {
|
||||
DsaGenParameterSpec() { this.hasQualifiedName("java.security.spec", "DSAGenParameterSpec") }
|
||||
}
|
||||
|
||||
/** The Java class `javax.crypto.spec.DHGenParameterSpec`. */
|
||||
class DhGenParameterSpec extends AlgorithmParameterSpec {
|
||||
DhGenParameterSpec() { this.hasQualifiedName("javax.crypto.spec", "DHGenParameterSpec") }
|
||||
}
|
||||
|
||||
193
java/ql/lib/semmle/code/java/security/InsufficientKeySize.qll
Normal file
193
java/ql/lib/semmle/code/java/security/InsufficientKeySize.qll
Normal file
@@ -0,0 +1,193 @@
|
||||
/** Provides classes and predicates related to insufficient key sizes in Java. */
|
||||
|
||||
private import semmle.code.java.security.Encryption
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
|
||||
/** A source for an insufficient key size. */
|
||||
abstract class InsufficientKeySizeSource extends DataFlow::Node {
|
||||
/** Holds if this source has the specified `state`. */
|
||||
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
|
||||
}
|
||||
|
||||
/** A sink for an insufficient key size. */
|
||||
abstract class InsufficientKeySizeSink extends DataFlow::Node {
|
||||
/** Holds if this sink has the specified `state`. */
|
||||
predicate hasState(DataFlow::FlowState state) { state instanceof DataFlow::FlowStateEmpty }
|
||||
}
|
||||
|
||||
/** Provides models for asymmetric cryptography. */
|
||||
private module Asymmetric {
|
||||
/** Provides models for non-elliptic-curve asymmetric cryptography. */
|
||||
private module NonEllipticCurve {
|
||||
/** A source for an insufficient key size used in RSA, DSA, and DH algorithms. */
|
||||
private class Source extends InsufficientKeySizeSource {
|
||||
Source() { this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize() }
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** A sink for an insufficient key size used in RSA, DSA, and DH algorithms. */
|
||||
private class Sink extends InsufficientKeySizeSink {
|
||||
Sink() {
|
||||
exists(KeyPairGenInit kpgInit, KeyPairGen kpg |
|
||||
kpg.getAlgoName().matches(["RSA", "DSA", "DH"]) and
|
||||
DataFlow::localExprFlow(kpg, kpgInit.getQualifier()) and
|
||||
this.asExpr() = kpgInit.getKeySizeArg()
|
||||
)
|
||||
or
|
||||
exists(Spec spec | this.asExpr() = spec.getKeySizeArg())
|
||||
}
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** Returns the minimum recommended key size for RSA, DSA, and DH algorithms. */
|
||||
private int getMinKeySize() { result = 2048 }
|
||||
|
||||
/** An instance of an RSA, DSA, or DH algorithm specification. */
|
||||
private class Spec extends ClassInstanceExpr {
|
||||
Spec() {
|
||||
this.getConstructedType() instanceof RsaKeyGenParameterSpec or
|
||||
this.getConstructedType() instanceof DsaGenParameterSpec or
|
||||
this.getConstructedType() instanceof DhGenParameterSpec
|
||||
}
|
||||
|
||||
/** Gets the `keysize` argument of this instance. */
|
||||
Argument getKeySizeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides models for elliptic-curve asymmetric cryptography. */
|
||||
private module EllipticCurve {
|
||||
/** A source for an insufficient key size used in elliptic curve (EC) algorithms. */
|
||||
private class Source extends InsufficientKeySizeSource {
|
||||
Source() {
|
||||
this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize()
|
||||
or
|
||||
// the below is needed for cases when the key size is embedded in the curve name
|
||||
getKeySize(this.asExpr().(StringLiteral).getValue()) < getMinKeySize()
|
||||
}
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** A sink for an insufficient key size used in elliptic curve (EC) algorithms. */
|
||||
private class Sink extends InsufficientKeySizeSink {
|
||||
Sink() {
|
||||
exists(KeyPairGenInit kpgInit, KeyPairGen kpg |
|
||||
kpg.getAlgoName().matches("EC%") and
|
||||
DataFlow::localExprFlow(kpg, kpgInit.getQualifier()) and
|
||||
this.asExpr() = kpgInit.getKeySizeArg()
|
||||
)
|
||||
or
|
||||
exists(Spec s | this.asExpr() = s.getKeySizeArg())
|
||||
}
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** Returns the minimum recommended key size for elliptic curve (EC) algorithms. */
|
||||
private int getMinKeySize() { result = 256 }
|
||||
|
||||
/** Returns the key size from an EC algorithm's curve name string */
|
||||
bindingset[algorithm]
|
||||
private int getKeySize(string algorithm) {
|
||||
algorithm.matches("sec%") and // specification such as "secp256r1"
|
||||
result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt()
|
||||
or
|
||||
algorithm.matches("X9.62%") and // specification such as "X9.62 prime192v2"
|
||||
result = algorithm.regexpCapture("X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
|
||||
or
|
||||
algorithm.matches(["prime%", "c2tnb%"]) and // specification such as "prime192v2"
|
||||
result = algorithm.regexpCapture(".*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
|
||||
}
|
||||
|
||||
/** An instance of an elliptic curve (EC) algorithm specification. */
|
||||
private class Spec extends ClassInstanceExpr {
|
||||
Spec() { this.getConstructedType() instanceof EcGenParameterSpec }
|
||||
|
||||
/** Gets the `keysize` argument of this instance. */
|
||||
Argument getKeySizeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `initialize` method declared in `java.security.KeyPairGenerator`
|
||||
* or to the `init` method declared in `java.security.AlgorithmParameterGenerator`.
|
||||
*/
|
||||
private class KeyPairGenInit extends MethodAccess {
|
||||
KeyPairGenInit() {
|
||||
this.getMethod() instanceof KeyPairGeneratorInitMethod or
|
||||
this.getMethod() instanceof AlgoParamGeneratorInitMethod
|
||||
}
|
||||
|
||||
/** Gets the `keysize` argument of this call. */
|
||||
Argument getKeySizeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of a `java.security.KeyPairGenerator`
|
||||
* or of a `java.security.AlgorithmParameterGenerator`.
|
||||
*/
|
||||
private class KeyPairGen extends GeneratorAlgoSpec {
|
||||
KeyPairGen() {
|
||||
this instanceof JavaSecurityKeyPairGenerator or
|
||||
this instanceof JavaSecurityAlgoParamGenerator
|
||||
}
|
||||
|
||||
override Expr getAlgoSpec() {
|
||||
result =
|
||||
[
|
||||
this.(JavaSecurityKeyPairGenerator).getAlgoSpec(),
|
||||
this.(JavaSecurityAlgoParamGenerator).getAlgoSpec()
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides models for symmetric cryptography. */
|
||||
private module Symmetric {
|
||||
/** A source for an insufficient key size used in AES algorithms. */
|
||||
private class Source extends InsufficientKeySizeSource {
|
||||
Source() { this.asExpr().(IntegerLiteral).getIntValue() < getMinKeySize() }
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** A sink for an insufficient key size used in AES algorithms. */
|
||||
private class Sink extends InsufficientKeySizeSink {
|
||||
Sink() {
|
||||
exists(KeyGenInit kgInit, KeyGen kg |
|
||||
kg.getAlgoName() = "AES" and
|
||||
DataFlow::localExprFlow(kg, kgInit.getQualifier()) and
|
||||
this.asExpr() = kgInit.getKeySizeArg()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasState(DataFlow::FlowState state) { state = getMinKeySize().toString() }
|
||||
}
|
||||
|
||||
/** Returns the minimum recommended key size for AES algorithms. */
|
||||
private int getMinKeySize() { result = 128 }
|
||||
|
||||
/** A call to the `init` method declared in `javax.crypto.KeyGenerator`. */
|
||||
private class KeyGenInit extends MethodAccess {
|
||||
KeyGenInit() { this.getMethod() instanceof KeyGeneratorInitMethod }
|
||||
|
||||
/** Gets the `keysize` argument of this call. */
|
||||
Argument getKeySizeArg() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** An instance of a `javax.crypto.KeyGenerator`. */
|
||||
private class KeyGen extends GeneratorAlgoSpec instanceof JavaxCryptoKeyGenerator {
|
||||
override Expr getAlgoSpec() { result = JavaxCryptoKeyGenerator.super.getAlgoSpec() }
|
||||
}
|
||||
}
|
||||
|
||||
/** An instance of a generator that specifies an encryption algorithm. */
|
||||
abstract private class GeneratorAlgoSpec extends CryptoAlgoSpec {
|
||||
/** Returns an uppercase string representing the algorithm name specified by this generator object. */
|
||||
string getAlgoName() {
|
||||
result = this.getAlgoSpec().(CompileTimeConstantExpr).getStringValue().toUpperCase()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/** Provides data flow configurations to be used in queries related to insufficient key sizes. */
|
||||
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.security.InsufficientKeySize
|
||||
|
||||
/** A data flow configuration for tracking key sizes used in cryptographic algorithms. */
|
||||
class KeySizeConfiguration extends DataFlow::Configuration {
|
||||
KeySizeConfiguration() { this = "KeySizeConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
source.(InsufficientKeySizeSource).hasState(state)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
sink.(InsufficientKeySizeSink).hasState(state)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user