Skip to content

Commit 804bd89

Browse files
committed
flows for key from contexts
1 parent 310469a commit 804bd89

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

cpp/ql/lib/experimental/quantum/OpenSSL/AlgorithmValueConsumers/PKeyAlgorithmValueConsumer.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ class EVPPKeyAlgorithmConsumer extends PKeyValueConsumer {
1717
// in these cases, the operation will be created separately for the same function.
1818
this.(Call).getTarget().getName() in [
1919
"EVP_PKEY_CTX_new_id", "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key",
20-
"EVP_PKEY_new_mac_key"
20+
"EVP_PKEY_new_mac_key", "EVP_PKEY_CTX_new"
2121
] and
2222
valueArgNode.asExpr() = this.(Call).getArgument(0)
2323
or
2424
this.(Call).getTarget().getName() in [
2525
"EVP_PKEY_CTX_new_from_name", "EVP_PKEY_new_raw_private_key_ex",
26-
"EVP_PKEY_new_raw_public_key_ex", "EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name"
26+
"EVP_PKEY_new_raw_public_key_ex", "EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name",
27+
"EVP_PKEY_CTX_new_from_pkey"
2728
] and
2829
valueArgNode.asExpr() = this.(Call).getArgument(1)
2930
or
@@ -42,6 +43,7 @@ class EVPPKeyAlgorithmConsumer extends PKeyValueConsumer {
4243
// All other cases
4344
valueArgNode.asExpr() = this.(Call).getArgument(2)
4445
)
46+
// TODO: data flow for EVP_PKEY_CTX_dup
4547
)
4648
}
4749

@@ -52,4 +54,8 @@ class EVPPKeyAlgorithmConsumer extends PKeyValueConsumer {
5254
override DataFlow::Node getResultNode() { result = resultNode }
5355

5456
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
57+
58+
// expose the valueArg as an Expr to avoid circular dependency that may arise
59+
// when trying to get the valueArg with getInputNode.
60+
Expr getValueArgExpr() { result = valueArgNode.asExpr() }
5561
}

cpp/ql/lib/experimental/quantum/OpenSSL/CtxFlow.qll

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ private class CtxCopyReturnCall extends Call, CtxPointerExpr {
100100
* Flow from any CtxPointerArgument to any other CtxPointerArgument
101101
*/
102102
module OpenSSLCtxArgumentFlowConfig implements DataFlow::ConfigSig {
103-
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CtxPointerArgument }
103+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CtxPointerExpr }
104104

105105
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CtxPointerArgument }
106106

@@ -128,7 +128,8 @@ module OpenSSLCtxArgumentFlowConfig implements DataFlow::ConfigSig {
128128
module OpenSSLCtxArgumentFlow = DataFlow::Global<OpenSSLCtxArgumentFlowConfig>;
129129

130130
/**
131-
* Holds if there is a context flow from the source to the sink.
131+
* Holds if there is a context flow from the source to the sink,
132+
* where the source and sink are arguments to function calls.
132133
*/
133134
predicate ctxArgFlowsToCtxArg(CtxPointerArgument source, CtxPointerArgument sink) {
134135
exists(DataFlow::Node a, DataFlow::Node b |
@@ -137,3 +138,15 @@ predicate ctxArgFlowsToCtxArg(CtxPointerArgument source, CtxPointerArgument sink
137138
b.asExpr() = sink
138139
)
139140
}
141+
142+
/**
143+
* Holds if there is a context flow from the source to the sink,
144+
* where the source is a variable and the sink is an argument to a function call.
145+
*/
146+
predicate ctxFlowsToCtxArg(CtxPointerExpr source, CtxPointerArgument sink) {
147+
exists(DataFlow::Node a, DataFlow::Node b |
148+
OpenSSLCtxArgumentFlow::flow(a, b) and
149+
a.asExpr() = source and
150+
b.asExpr() = sink
151+
)
152+
}

cpp/ql/lib/experimental/quantum/OpenSSL/Operations/EVPSignatureOperation.qll

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
private import experimental.quantum.Language
66
private import OpenSSLOperationBase
7-
private import experimental.quantum.OpenSSL.CtxFlow as CTXFlow
7+
private import experimental.quantum.OpenSSL.CtxFlow
8+
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.PKeyAlgorithmValueConsumer
89

910
// TODO: verification functions
1011
class EVP_Signature_Initializer extends EVPInitialize {
@@ -44,14 +45,20 @@ class EVP_Signature_Initializer extends EVPInitialize {
4445

4546
/**
4647
* Returns the key argument if there is one.
47-
* They key could be provided in the context or in a later call (final or one-shot).
48+
* If the key was provided via the context, we track it to the context.
4849
*/
4950
override Expr getKeyArg() {
5051
this.(Call).getTarget().getName() = "EVP_DigestSignInit" and
5152
result = this.(Call).getArgument(4)
5253
or
5354
this.(Call).getTarget().getName() = "EVP_DigestSignInit_ex" and
5455
result = this.(Call).getArgument(5)
56+
or
57+
this.(Call).getTarget().getName().matches("EVP_PKEY_%") and
58+
exists(EVPPKeyAlgorithmConsumer source |
59+
result = source.getValueArgExpr() and
60+
ctxFlowsToCtxArg(source.getResultNode().asExpr(), this.getContextArg())
61+
)
5562
}
5663

5764
/**
@@ -123,8 +130,10 @@ abstract class EVP_Signature_Operation extends EVPOperation, Crypto::SignatureOp
123130
}
124131

125132
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
126-
result = DataFlow::exprNode(this.getInitCall().getKeyArg())
127-
// TODO: or track to the EVP_PKEY_CTX_new
133+
// TODO: move to EVPOperation similarly to getAlgorithmArg
134+
if exists(this.getInitCall().getKeyArg())
135+
then result = DataFlow::exprNode(this.getInitCall().getKeyArg())
136+
else none()
128137
}
129138

130139
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
@@ -139,7 +148,6 @@ abstract class EVP_Signature_Operation extends EVPOperation, Crypto::SignatureOp
139148
* TODO: only signing operations for now, change when verificaiton is added
140149
*/
141150
override Crypto::ConsumerInputDataFlowNode getSignatureConsumer() { none() }
142-
143151
}
144152

145153
class EVP_Signature_Call extends EVPOperation, EVP_Signature_Operation {
@@ -163,6 +171,12 @@ class EVP_Signature_Final_Call extends EVPFinal, EVP_Signature_Operation {
163171
]
164172
}
165173

174+
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
175+
if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
176+
then result = DataFlow::exprNode(this.(Call).getArgument(3))
177+
else none()
178+
}
179+
166180
/**
167181
* Output is the signature.
168182
*/

0 commit comments

Comments
 (0)