Skip to content

Commit 9c87ad8

Browse files
committed
Merge branch 'brodes/key_agreement' of https://github.com/nicolaswill/codeql into brodes/key_agreement
2 parents 7f24a25 + ac798f2 commit 9c87ad8

20 files changed

+305
-37
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
import experimental.Quantum.Language
4+
5+
/**
6+
* Flow from any function that appears to return a value
7+
* to an artifact node.
8+
* NOTE: TODO: need to handle call by refernece for now. Need to re-evaluate (see notes below)
9+
* Such functions may be 'wrappers' for some derived value.
10+
*/
11+
private module WrapperConfig implements DataFlow::ConfigSig {
12+
predicate isSource(DataFlow::Node source) {
13+
exists(Call c |
14+
c = source.asExpr()
15+
// not handling references yet, I think we want to flat say references are only ok
16+
// if I know the source, otherwise, it has to be through an additional flow step, which
17+
// we filter as a source, i.e., references are only allowed as sources only,
18+
// no inferrece? Not sure if that would work
19+
//or
20+
// source.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = c.getAnArgument()
21+
) and
22+
// Filter out sources that are known additional flow steps, as these are likely not the
23+
// kind of wrapper source we are looking for.
24+
not exists(AdditionalFlowInputStep s | s.getOutput() = source)
25+
}
26+
27+
// Flow through additional flow steps
28+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
29+
node1.(AdditionalFlowInputStep).getOutput() = node2
30+
}
31+
32+
predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(Crypto::ArtifactNode i).asElement() }
33+
}
34+
35+
module WrapperFlow = DataFlow::Global<WrapperConfig>;
36+
37+
/**
38+
* Using a set approach to determine if reuse of an artifact exists.
39+
* This predicate produces a set of 'wrappers' that flow to the artifact node.
40+
* This set can be compared with the set to another artifact node to determine if they are the same.
41+
*/
42+
private DataFlow::Node getWrapperSet(Crypto::NonceArtifactNode a) {
43+
WrapperFlow::flow(result, DataFlow::exprNode(a.asElement()))
44+
or
45+
result.asExpr() = a.getSourceElement()
46+
}
47+
48+
/**
49+
* Two different artifact nodes are considered reuse if any of the following conditions are met:
50+
* 1. The source for artifact `a` and artifact `b` are the same and the source is a literal.
51+
* 2. The source for artifact `a` and artifact `b` are not the same and the source is a literal of the same value.
52+
* 3. For all 'wrappers' that return the source of artifact `a`, and that wrapper also exists for artifact `b`.
53+
* 4. For all 'wrappers' that return the source of artifact `b`, and that wrapper also exists for artifact `a`.
54+
*/
55+
predicate isArtifactReuse(Crypto::ArtifactNode a, Crypto::ArtifactNode b) {
56+
a != b and
57+
(
58+
a.getSourceElement() = b.getSourceElement() and a.getSourceElement() instanceof Literal
59+
or
60+
a.getSourceElement().(Literal).getValue() = b.getSourceElement().(Literal).getValue()
61+
or
62+
forex(DataFlow::Node e | e = getWrapperSet(a) |
63+
exists(DataFlow::Node e2 | e2 = getWrapperSet(b) | e = e2)
64+
)
65+
or
66+
forex(DataFlow::Node e | e = getWrapperSet(b) |
67+
exists(DataFlow::Node e2 | e2 = getWrapperSet(a) | e = e2)
68+
)
69+
)
70+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* @name Detects known weak KDf iteration counts (less than 100k and the count is statically known)
3+
* @id java/crypto_inventory_filters/known_weak_kdf_iteration_count
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::KeyDerivationOperationNode op, Literal l
11+
where
12+
op.getIterationCount().asElement() = l and
13+
l.getValue().toInt() < 100000
14+
select op, "Key derivation operation configures iteration count below 100k: $@", l,
15+
l.getValue().toString()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Detects reuse of the same nonce in multiple operations
3+
* @id java/crypto_inventory_filter/nonce_reuse
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import ArtifactReuse
9+
10+
from Crypto::NonceArtifactNode nonce1, Crypto::NonceArtifactNode nonce2
11+
where isArtifactReuse(nonce1, nonce2)
12+
select nonce1, "Reuse with nonce $@", nonce2, nonce2.toString()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name Detects unknown KDf iteration counts
3+
* @id java/crypto_inventory_filters/unknown_kdf_iteration_count
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::KeyDerivationOperationNode op, Element e, string msg
11+
where
12+
e = op.getIterationCount().asElement() and
13+
not e instanceof Literal and
14+
msg = "Key derivation operation with unknown iteration: $@"
15+
or
16+
not exists(op.getIterationCount()) and
17+
e = op.asElement() and
18+
msg = "Key derivation operation with no iteration configuration."
19+
select op, msg, e, e.toString()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Detects known asymmetric algorithms
3+
* @id java/crypto_inventory_slices/known_asymmetric_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::AlgorithmNode a
11+
where Crypto::isKnownAsymmetricAlgorithm(a)
12+
select a, "Instance of asymmetric algorithm " + a.getAlgorithmName()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Detects known asymmetric cipher algorithms
3+
* @id java/crypto_inventory_slices/known_symmetric_cipher_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::KeyOperationAlgorithmNode a
11+
where a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm
12+
select a, "Instance of asymmetric cipher algorithm " + a.getAlgorithmName()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @name Detects operations where the algorithm applied is a known asymmetric algorithms
3+
* @id java/crypto_inventory_slices/known_asymmetric_operation_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::OperationNode op, Crypto::AlgorithmNode a
11+
where a = op.getAKnownAlgorithm() and Crypto::isKnownAsymmetricAlgorithm(a)
12+
select op, "Operation using asymmetric algorithm $@", a, a.getAlgorithmName()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* @name Detects known cipher algorithms
3+
* @id java/crypto_inventory_slices/known_cipher_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
// TODO: should there be a cipher algorithm node?
11+
from Crypto::KeyOperationAlgorithmNode a
12+
where
13+
a.getAlgorithmType() instanceof Crypto::KeyOpAlg::AsymmetricCipherAlgorithm or
14+
a.getAlgorithmType() instanceof Crypto::KeyOpAlg::SymmetricCipherAlgorithm
15+
select a, "Instance of cipher algorithm " + a.getAlgorithmName()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @name Detects known elliptic curve algorithms
3+
* @id java/crypto_inventory_slices/known_elliptic_curve_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::EllipticCurveNode a
11+
select a, "Instance of elliptic curve algorithm " + a.getAlgorithmName()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @name Detects algorithms that are known hashing algorithms
3+
* @id java/crypto_inventory_slices/known_hashing_algorithm
4+
* @kind problem
5+
*/
6+
7+
import java
8+
import experimental.Quantum.Language
9+
10+
from Crypto::HashAlgorithmNode a
11+
select a, "Instance of hashing algorithm " + a.getAlgorithmName()

0 commit comments

Comments
 (0)