Skip to content

Commit bf9a249

Browse files
committed
Crypto: Experimental queries for mac ordering
1 parent ee08385 commit bf9a249

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @name Bad MAC order: decrypt to mac
3+
* @description MAC should be on a cipher, not a raw message
4+
* @id java/quantum/bad-mac-order-decrypt-to-mac
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @precision high
8+
* @tags quantum
9+
* experimental
10+
*/
11+
12+
import java
13+
import experimental.quantum.Language
14+
import ArtifactFlow::PathGraph
15+
16+
from ArtifactFlow::PathNode src, ArtifactFlow::PathNode sink
17+
where
18+
ArtifactFlow::flowPath(src, sink) and
19+
exists(Crypto::CipherOperationNode cipherOp |
20+
cipherOp.getKeyOperationSubtype() = Crypto::TDecryptMode() and
21+
cipherOp.getAnOutputArtifact().asElement() = src.getNode().asExpr()
22+
) and
23+
exists(Crypto::MacOperationNode macOp |
24+
macOp.getAnInputArtifact().asElement() = sink.getNode().asExpr()
25+
)
26+
select sink, src, sink,
27+
"MAC order potentially wrong: observed decrypt output to MAC implying the MAC is on plaintext, and not a cipher."
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @name Bad MAC order: MAC on an encrypt plaintext
3+
* @description MAC should be on a cipher, not a raw message
4+
* @id java/quantum/bad-mac-order-encrypt-plaintext-also-in-mac
5+
* @kind problem
6+
* @problem.severity error
7+
* @precision high
8+
* @tags quantum
9+
* experimental
10+
*/
11+
12+
import java
13+
import experimental.quantum.Language
14+
15+
// NOTE: I must look for a common data flow node rather than
16+
// starting from a message source, since the message source
17+
// might not be known.
18+
// TODO: can we approximate a message source better?
19+
module CommonDataFlowNodeConfig implements DataFlow::ConfigSig {
20+
predicate isSource(DataFlow::Node source) { exists(source.asParameter()) }
21+
22+
predicate isSink(DataFlow::Node sink) {
23+
sink = any(Crypto::FlowAwareElement other).getInputNode()
24+
}
25+
26+
predicate isBarrierOut(DataFlow::Node node) {
27+
node = any(Crypto::FlowAwareElement element).getInputNode()
28+
}
29+
30+
predicate isBarrierIn(DataFlow::Node node) {
31+
node = any(Crypto::FlowAwareElement element).getOutputNode()
32+
}
33+
34+
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
35+
node1.(AdditionalFlowInputStep).getOutput() = node2
36+
or
37+
exists(MethodCall m |
38+
m.getMethod().hasQualifiedName("java.lang", "String", "getBytes") and
39+
node1.asExpr() = m.getQualifier() and
40+
node2.asExpr() = m
41+
)
42+
}
43+
}
44+
45+
module CommonDataFlowNodeFlow = DataFlow::Global<CommonDataFlowNodeConfig>;
46+
47+
from DataFlow::Node src, DataFlow::Node sink1, DataFlow::Node sink2
48+
where
49+
CommonDataFlowNodeFlow::flow(src, sink1) and
50+
CommonDataFlowNodeFlow::flow(src, sink2) and
51+
exists(Crypto::CipherOperationNode cipherOp |
52+
cipherOp.getKeyOperationSubtype() = Crypto::TEncryptMode() and
53+
cipherOp.getAnInputArtifact().asElement() = sink1.asExpr()
54+
) and
55+
exists(Crypto::MacOperationNode macOp | macOp.getAnInputArtifact().asElement() = sink2.asExpr())
56+
select src, "Message used for encryption operation at $@, also used for MAC at $@.", sink1,
57+
sink1.toString(), sink2, sink2.toString()

0 commit comments

Comments
 (0)