Skip to content

Commit cbe34f1

Browse files
authored
Merge pull request #19944 from bdrodes/signature_model_refactor
Crypto: Refactor Model and signatures, fix models, add unit tests
2 parents b4c979f + 4901cdf commit cbe34f1

37 files changed

+2106
-972
lines changed

cpp/ql/lib/experimental/quantum/Language.qll

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ module CryptoInput implements InputSig<Language::Location> {
1414
result = node.asExpr() or
1515
result = node.asParameter() or
1616
result = node.asVariable() or
17-
result = node.asDefiningArgument()
18-
// TODO: do we need asIndirectExpr()?
17+
result = node.asDefiningArgument() or
18+
result = node.asIndirectExpr()
1919
}
2020

2121
string locationToFileBaseNameAndLineNumberString(Location location) {
@@ -53,7 +53,7 @@ module ArtifactFlowConfig implements DataFlow::ConfigSig {
5353
}
5454
}
5555

56-
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
56+
module ArtifactFlow = TaintTracking::Global<ArtifactFlowConfig>;
5757

5858
/**
5959
* An artifact output to node input configuration
@@ -93,7 +93,13 @@ module GenericDataSourceFlow = TaintTracking::Global<GenericDataSourceFlowConfig
9393

9494
private class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof OpenSslGenericSourceCandidateLiteral
9595
{
96-
override DataFlow::Node getOutputNode() { result.asExpr() = this }
96+
override DataFlow::Node getOutputNode() {
97+
// OpenSSL algorithms may be referenced either by string name or by numeric ID:
98+
// String names (e.g. "AES-256-CBC") appear in the AST as character pointer
99+
// literals. For these we must use `asIndirectExpr`. Numeric IDs (e.g. NID_aes_256_cbc)
100+
// appear as integer literals. For these, we must use `asExpr` to get the "value" node.
101+
[result.asIndirectExpr(), result.asExpr()] = this
102+
}
97103

98104
override predicate flowsTo(Crypto::FlowAwareElement other) {
99105
// TODO: separate config to avoid blowing up data-flow analysis
@@ -103,28 +109,4 @@ private class ConstantDataSource extends Crypto::GenericConstantSourceInstance i
103109
override string getAdditionalDescription() { result = this.toString() }
104110
}
105111

106-
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
107-
predicate isSource(DataFlow::Node source) {
108-
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
109-
}
110-
111-
predicate isSink(DataFlow::Node sink) {
112-
sink = any(Crypto::FlowAwareElement other).getInputNode()
113-
}
114-
115-
predicate isBarrierOut(DataFlow::Node node) {
116-
node = any(Crypto::FlowAwareElement element).getInputNode()
117-
}
118-
119-
predicate isBarrierIn(DataFlow::Node node) {
120-
node = any(Crypto::FlowAwareElement element).getOutputNode()
121-
}
122-
123-
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
124-
node1.(AdditionalFlowInputStep).getOutput() = node2
125-
}
126-
}
127-
128-
module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;
129-
130112
import OpenSSL.OpenSSL

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/AlgToAVCFlow.qll

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ private import PaddingAlgorithmInstance
1414
*/
1515
module KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
1616
predicate isSource(DataFlow::Node source) {
17-
source.asExpr() instanceof KnownOpenSslAlgorithmExpr and
17+
(
18+
source.asExpr() instanceof KnownOpenSslAlgorithmExpr or
19+
source.asIndirectExpr() instanceof KnownOpenSslAlgorithmExpr
20+
) and
1821
// No need to flow direct operations to AVCs
19-
not source.asExpr() instanceof OpenSslDirectAlgorithmOperationCall
22+
not source.asExpr() instanceof OpenSslDirectAlgorithmOperationCall and
23+
not source.asIndirectExpr() instanceof OpenSslDirectAlgorithmOperationCall
2024
}
2125

2226
predicate isSink(DataFlow::Node sink) {
@@ -46,10 +50,12 @@ module KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::
4650
}
4751

4852
module KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow =
49-
DataFlow::Global<KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig>;
53+
TaintTracking::Global<KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig>;
5054

5155
module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
52-
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof OpenSslPaddingLiteral }
56+
predicate isSource(DataFlow::Node source) {
57+
source.asExpr() instanceof OpenSslSpecialPaddingLiteral
58+
}
5359

5460
predicate isSink(DataFlow::Node sink) {
5561
exists(PaddingAlgorithmValueConsumer c | c.getInputNode() = sink)
@@ -61,7 +67,7 @@ module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataF
6167
}
6268

6369
module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow =
64-
DataFlow::Global<RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig>;
70+
TaintTracking::Global<RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig>;
6571

6672
class OpenSslAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep {
6773
OpenSslAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) }

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/BlockAlgorithmInstance.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class KnownOpenSslBlockModeConstantAlgorithmInstance extends OpenSslAlgorithmIns
5353
// Sink is an argument to a CipherGetterCall
5454
sink = getterCall.getInputNode() and
5555
// Source is `this`
56-
src.asExpr() = this and
56+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
57+
this = [src.asExpr(), src.asIndirectExpr()] and
5758
// This traces to a getter
5859
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
5960
)

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/CipherAlgorithmInstance.qll

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ import cpp
22
private import experimental.quantum.Language
33
private import KnownAlgorithmConstants
44
private import Crypto::KeyOpAlg as KeyOpAlg
5-
private import OpenSSLAlgorithmInstanceBase
6-
private import PaddingAlgorithmInstance
7-
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
8-
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
5+
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperationBase
6+
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
7+
private import OpenSSLAlgorithmInstances
98
private import AlgToAVCFlow
10-
private import BlockAlgorithmInstance
119

1210
/**
1311
* Given a `KnownOpenSslCipherAlgorithmExpr`, converts this to a cipher family type.
@@ -79,7 +77,8 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
7977
// Sink is an argument to a CipherGetterCall
8078
sink = getterCall.getInputNode() and
8179
// Source is `this`
82-
src.asExpr() = this and
80+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
81+
this = [src.asExpr(), src.asIndirectExpr()] and
8382
// This traces to a getter
8483
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
8584
)
@@ -97,10 +96,13 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
9796
}
9897

9998
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() {
100-
//TODO: the padding is either self, or it flows through getter ctx to a set padding call
101-
// like EVP_PKEY_CTX_set_rsa_padding
10299
result = this
103-
// TODO or trace through getter ctx to set padding
100+
or
101+
exists(OperationStep s |
102+
this.getAvc().(AvcContextCreationStep).flowsToOperationStep(s) and
103+
s.getAlgorithmValueConsumerForInput(PaddingAlgorithmIO()) =
104+
result.(OpenSslAlgorithmInstance).getAvc()
105+
)
104106
}
105107

106108
override string getRawAlgorithmName() {

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/EllipticCurveAlgorithmInstance.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class KnownOpenSslEllipticCurveConstantAlgorithmInstance extends OpenSslAlgorith
2121
// Sink is an argument to a CipherGetterCall
2222
sink = getterCall.getInputNode() and
2323
// Source is `this`
24-
src.asExpr() = this and
24+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
25+
this = [src.asExpr(), src.asIndirectExpr()] and
2526
// This traces to a getter
2627
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
2728
)

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/HashAlgorithmInstance.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class KnownOpenSslHashConstantAlgorithmInstance extends OpenSslAlgorithmInstance
5959
// Sink is an argument to a CipherGetterCall
6060
sink = getterCall.getInputNode() and
6161
// Source is `this`
62-
src.asExpr() = this and
62+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
63+
this = [src.asExpr(), src.asIndirectExpr()] and
6364
// This traces to a getter
6465
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
6566
)

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/KeyAgreementAlgorithmInstance.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class KnownOpenSslKeyAgreementConstantAlgorithmInstance extends OpenSslAlgorithm
3737
// Sink is an argument to a CipherGetterCall
3838
sink = getterCall.getInputNode() and
3939
// Source is `this`
40-
src.asExpr() = this and
40+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
41+
this = [src.asExpr(), src.asIndirectExpr()] and
4142
// This traces to a getter
4243
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
4344
)

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/KnownAlgorithmConstants.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,15 @@ class KnownOpenSslKeyAgreementAlgorithmExpr extends Expr instanceof KnownOpenSsl
171171
}
172172

173173
predicate knownOpenSslAlgorithmOperationCall(Call c, string normalized, string algType) {
174-
c.getTarget().getName() in ["EVP_RSA_gen", "RSA_generate_key_ex", "RSA_generate_key", "RSA_new"] and
174+
c.getTarget().getName() in [
175+
"EVP_RSA_gen", "RSA_generate_key_ex", "RSA_generate_key", "RSA_new", "RSA_sign", "RSA_verify"
176+
] and
175177
normalized = "RSA" and
176178
algType = "ASYMMETRIC_ENCRYPTION"
179+
or
180+
c.getTarget().getName() in ["DSA_do_sign", "DSA_do_verify"] and
181+
normalized = "DSA" and
182+
algType = "SIGNATURE"
177183
}
178184

179185
/**

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmInstances/MACAlgorithmInstance.qll

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import cpp
22
private import experimental.quantum.Language
33
private import KnownAlgorithmConstants
44
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
5-
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
5+
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
66
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
7+
private import Crypto::KeyOpAlg as KeyOpAlg
78
private import AlgToAVCFlow
89

910
class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
10-
Crypto::MacAlgorithmInstance instanceof KnownOpenSslMacAlgorithmExpr
11+
Crypto::KeyOperationAlgorithmInstance instanceof KnownOpenSslMacAlgorithmExpr
1112
{
1213
OpenSslAlgorithmValueConsumer getterCall;
1314

@@ -21,7 +22,8 @@ class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
2122
// Sink is an argument to a CipherGetterCall
2223
sink = getterCall.getInputNode() and
2324
// Source is `this`
24-
src.asExpr() = this and
25+
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
26+
this = [src.asExpr(), src.asIndirectExpr()] and
2527
// This traces to a getter
2628
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
2729
)
@@ -33,17 +35,34 @@ class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
3335

3436
override OpenSslAlgorithmValueConsumer getAvc() { result = getterCall }
3537

36-
override string getRawMacAlgorithmName() {
38+
override string getRawAlgorithmName() {
3739
result = this.(Literal).getValue().toString()
3840
or
3941
result = this.(Call).getTarget().getName()
4042
}
4143

42-
override Crypto::MacType getMacType() {
43-
this instanceof KnownOpenSslHMacAlgorithmExpr and result = Crypto::HMAC()
44-
or
45-
this instanceof KnownOpenSslCMacAlgorithmExpr and result = Crypto::CMAC()
44+
override Crypto::KeyOpAlg::AlgorithmType getAlgorithmType() {
45+
if this instanceof KnownOpenSslHMacAlgorithmExpr
46+
then result = KeyOpAlg::TMac(KeyOpAlg::HMAC())
47+
else
48+
if this instanceof KnownOpenSslCMacAlgorithmExpr
49+
then result = KeyOpAlg::TMac(KeyOpAlg::CMAC())
50+
else result = KeyOpAlg::TMac(KeyOpAlg::OtherMacAlgorithmType())
51+
}
52+
53+
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
54+
// TODO: trace to any key size initializer?
55+
none()
56+
}
57+
58+
override int getKeySizeFixed() {
59+
// TODO: are there known fixed key sizes to consider?
60+
none()
4661
}
62+
63+
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
64+
65+
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
4766
}
4867

4968
class KnownOpenSslHMacConstantAlgorithmInstance extends Crypto::HmacAlgorithmInstance,
@@ -60,9 +79,13 @@ class KnownOpenSslHMacConstantAlgorithmInstance extends Crypto::HmacAlgorithmIns
6079
// where the current AVC traces to a HashAlgorithmIO consuming operation step.
6180
// TODO: need to consider getting reset values, tracing down to the first set for now
6281
exists(OperationStep s, AvcContextCreationStep avc |
63-
avc = this.getAvc() and
82+
avc = super.getAvc() and
6483
avc.flowsToOperationStep(s) and
6584
s.getAlgorithmValueConsumerForInput(HashAlgorithmIO()) = result
6685
)
6786
}
87+
88+
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
89+
90+
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
6891
}

0 commit comments

Comments
 (0)