Skip to content

Commit ec7e41c

Browse files
committed
Crypto: Fixed issues in CBOM representations (gaps in the underlying model) and simplified unit tests in terms of the graph complexity to aid visual assessments of model correctness.
1 parent 65ff727 commit ec7e41c

File tree

12 files changed

+795
-393
lines changed

12 files changed

+795
-393
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,10 @@ 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+
"EVP_PKEY_get1_RSA"
177+
] and
175178
normalized = "RSA" and
176179
algType = "ASYMMETRIC_ENCRYPTION"
177180
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,20 @@ class EvpDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
8787
exists(OpenSslAlgorithmInstance i | i.getAvc() = this and result = i)
8888
}
8989
}
90+
91+
class RsaSignOrVerifyHashAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
92+
DataFlow::Node valueArgNode;
93+
94+
RsaSignOrVerifyHashAlgorithmValueConsumer() {
95+
this.(Call).getTarget().getName() in ["RSA_sign", "RSA_verify"] and
96+
valueArgNode.asExpr() = this.(Call).getArgument(0)
97+
}
98+
99+
override DataFlow::Node getResultNode() { none() }
100+
101+
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
102+
103+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
104+
exists(OpenSslAlgorithmInstance i | i.getAvc() = this and result = i)
105+
}
106+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer extends PaddingAlgorit
1414
DataFlow::Node resultNode;
1515

1616
Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer() {
17-
resultNode.asExpr() = this and
17+
resultNode.asExpr() = this.(Call).getArgument(0) and
1818
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_padding" and
1919
valueArgNode.asExpr() = this.(Call).getArgument(1)
2020
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class EvpSignatureAlgorithmValueConsumer extends SignatureAlgorithmValueConsumer
1818
this.(Call).getTarget().getName() = "EVP_SIGNATURE_fetch" and
1919
valueArgNode.asExpr() = this.(Call).getArgument(1)
2020
// EVP_PKEY_get1_DSA, EVP_PKEY_get1_RSA
21-
// DSA_SIG_new, DSA_SIG_get0, RSA_sign ?
21+
// DSA_SIG_new, DSA_SIG_get0 ?
2222
)
2323
}
2424

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
/**
22
* Initializers for EVP PKey
3+
* These are used to create a Pkey context or set properties on a Pkey context
4+
* e.g., key size, hash algorithms, curves, padding schemes, etc.
5+
* Meant to capture more general purpose initializers that aren't necessarily
6+
* tied to a specific operation. If tied to an operation (i.e., in the docs)
7+
* we recommend defining defining all together in the same operation definition qll.
38
* including:
49
* https://docs.openssl.org/3.0/man3/EVP_PKEY_CTX_ctrl/
510
* https://docs.openssl.org/3.0/man3/EVP_EncryptInit/#synopsis
@@ -195,3 +200,26 @@ class EvpCtxSetSaltLengthInitializer extends OperationStep {
195200

196201
override OperationStepType getStepType() { result = InitializerStep() }
197202
}
203+
204+
/**
205+
* A call to `EVP_PKEY_get1_RSA` or `EVP_PKEY_get1_DSA`
206+
* - RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
207+
* - DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
208+
*/
209+
class EvpPkeyGet1RsaOrDsa extends OperationStep {
210+
EvpPkeyGet1RsaOrDsa() { this.getTarget().getName() = ["EVP_PKEY_get1_RSA", "EVP_PKEY_get1_DSA"] }
211+
212+
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
213+
214+
override DataFlow::Node getInput(IOType type) {
215+
// Key being loaded or created from another location
216+
result.asExpr() = this.getArgument(0) and type = KeyIO()
217+
}
218+
219+
/**
220+
* Consider this to be an intialization step. A key is accepted and a different key is produced.
221+
* It doesn't create a new context or new key. It isn't quite an initialiation for an operaiton
222+
* either.
223+
*/
224+
override OperationStepType getStepType() { result = InitializerStep() }
225+
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,21 +149,16 @@ class EvpNewMacKey extends KeyGenFinalOperationStep {
149149
EvpNewMacKey() { this.getTarget().getName() = "EVP_PKEY_new_mac_key" }
150150

151151
override DataFlow::Node getInput(IOType type) {
152-
result.asExpr() = this.getArgument(0) and type = ContextIO()
153-
or
154152
// the raw key that is configured into the output key
155153
result.asExpr() = this.getArgument(2) and type = KeyIO()
156154
or
157155
result.asExpr() = this.getArgument(3) and type = KeySizeIO()
158156
}
159157

160-
override DataFlow::Node getOutput(IOType type) {
161-
result.asExpr() = this and type = KeyIO()
162-
or
163-
result.asExpr() = this.getArgument(0) and type = ContextIO()
164-
}
158+
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
165159
}
166160

161+
167162
/// TODO: https://docs.openssl.org/3.0/man3/EVP_PKEY_new/#synopsis
168163
/**
169164
* An `KeyGenerationOperationInstance` for the for all key gen final operation steps.

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ newtype TIOType =
7575
PaddingAlgorithmIO() or
7676
// Plaintext also includes a message for digest, signature, verification, and mac generation
7777
PlaintextIO() or
78+
PlaintextSizeIO() or
7879
PrimaryAlgorithmIO() or
7980
RandomSourceIO() or
8081
SaltLengthIO() or
8182
SeedIO() or
82-
SignatureIO()
83+
SignatureIO() or
84+
SignatureSizeIO()
8385

8486
private string ioTypeToString(TIOType t) {
8587
t = CiphertextIO() and result = "CiphertextIO"
@@ -108,6 +110,8 @@ private string ioTypeToString(TIOType t) {
108110
or
109111
t = PlaintextIO() and result = "PlaintextIO"
110112
or
113+
t = PlaintextSizeIO() and result = "PlaintextSizeIO"
114+
or
111115
t = PrimaryAlgorithmIO() and result = "PrimaryAlgorithmIO"
112116
or
113117
t = RandomSourceIO() and result = "RandomSourceIO"
@@ -117,6 +121,8 @@ private string ioTypeToString(TIOType t) {
117121
t = SeedIO() and result = "SeedIO"
118122
or
119123
t = SignatureIO() and result = "SignatureIO"
124+
or
125+
t = SignatureSizeIO() and result = "SignatureSizeIO"
120126
}
121127

122128
class IOType extends TIOType {
@@ -131,8 +137,9 @@ class IOType extends TIOType {
131137
* The type of step in an `OperationStep`.
132138
* - `ContextCreationStep`: the creation of a context from an algorithm or key.
133139
* for example `EVP_MD_CTX_create(EVP_sha256())` or `EVP_PKEY_CTX_new(pkey, NULL)`
134-
* - `InitializerStep`: the initialization of an operation through some sort of shared/accumulated context
135-
* for example `EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)`
140+
* - `InitializerStep`: the initialization of an operation or state through some sort of shared/accumulated context
141+
* for example `EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)`, may also be used for pass through
142+
* configuration, for example `EVP_PKEY_get1_RSA(key)` where a pkey is input into an RSA key return.
136143
* - `UpdateStep`: any operation that has and update/final paradigm, the update represents an intermediate step in an operation,
137144
* such as `EVP_DigestUpdate(ctx, data, len)`
138145
* - `FinalStep`: an ultimate operation step. This may be an explicit 'final' in an update/final paradigm, but not necessarily.
@@ -249,8 +256,9 @@ abstract class OperationStep extends Call {
249256
/**
250257
* Gets an AVC for the primary algorithm for this operation.
251258
* A primary algorithm is an AVC that either:
259+
* 0) `this` is an AVC (consider direct algorithm consumers like RSA_sign (algorithm is implicit) or EVP_PKEY_new_mac_key (NID is first arg) )
252260
* 1) flows to a ctx input directly or
253-
* 2) flows to a primary algorithm input directly
261+
* 2) flows to a primary algorithm input directly or
254262
* 3) flows to a key input directly (algorithm held in a key will be considered primary)
255263
* See `AvcContextCreationStep` for details about resetting scenarios.
256264
* Gets the first OperationStep an AVC flows to. If a context input,
@@ -259,6 +267,8 @@ abstract class OperationStep extends Call {
259267
* operation step (dominating operation step, see `getDominatingInitializersToStep`).
260268
*/
261269
Crypto::AlgorithmValueConsumer getPrimaryAlgorithmValueConsumer() {
270+
this instanceof Crypto::AlgorithmValueConsumer and result = this
271+
or
262272
exists(DataFlow::Node src, DataFlow::Node sink, IOType t, OperationStep avcConsumingPred |
263273
(t = PrimaryAlgorithmIO() or t = ContextIO() or t = KeyIO()) and
264274
avcConsumingPred.flowsToOperationStep(this) and

0 commit comments

Comments
 (0)