Skip to content

Commit f3c436a

Browse files
committed
quantum-c#: Use stream flows for the HashOperationInstance
1 parent e488a74 commit f3c436a

File tree

2 files changed

+74
-41
lines changed

2 files changed

+74
-41
lines changed

csharp/ql/lib/experimental/quantum/dotnet/Cryptography.qll

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,33 @@ class SigningCreateCall extends CryptographyCreateCall {
8282
}
8383
}
8484

85-
class HashAlgorithmCreateCall extends CryptographyCreateCall {
86-
HashAlgorithmCreateCall() { this.getQualifier().getType() instanceof HashAlgorithmType }
85+
/**
86+
* A call to create on an hash algorithm instance.
87+
* The hash algorithm is defined by the qualifier.
88+
*/
89+
class HashAlgorithmCreateCall extends Crypto::AlgorithmValueConsumer instanceof CryptographyCreateCall
90+
{
91+
HashAlgorithmCreateCall() { super.getQualifier().getType() instanceof HashAlgorithmType }
92+
93+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = super.getQualifier() }
94+
95+
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
96+
}
97+
98+
class HashAlgorithmQualifier extends Crypto::HashAlgorithmInstance instanceof Expr {
99+
HashAlgorithmQualifier() {
100+
this = any(HashAlgorithmCreateCall c).(CryptographyCreateCall).getQualifier()
101+
}
102+
103+
override Crypto::THashType getHashFamily() {
104+
result = getHashFamily(this.getRawHashAlgorithmName())
105+
}
106+
107+
override string getRawHashAlgorithmName() { result = super.getType().getName() }
108+
109+
override int getFixedDigestLength() {
110+
hashAlgorithmToFamily(this.getRawHashAlgorithmName(), _, result)
111+
}
87112
}
88113

89114
class NamedCurvePropertyAccess extends PropertyAccess {
@@ -111,15 +136,18 @@ class HashAlgorithmName extends PropertyAccess {
111136

112137
string getAlgorithmName() { result = algorithmName }
113138

114-
Crypto::THashType getHashFamily() {
115-
if hashAlgorithmToFamily(this.getAlgorithmName(), _, _)
116-
then hashAlgorithmToFamily(this.getAlgorithmName(), result, _)
117-
else result = Crypto::OtherHashType()
118-
}
139+
Crypto::THashType getHashFamily() { result = getHashFamily(this.getAlgorithmName()) }
119140

120141
int getFixedDigestLength() { hashAlgorithmToFamily(this.getAlgorithmName(), _, result) }
121142
}
122143

144+
bindingset[name]
145+
Crypto::THashType getHashFamily(string name) {
146+
if hashAlgorithmToFamily(name, _, _)
147+
then hashAlgorithmToFamily(name, result, _)
148+
else result = Crypto::OtherHashType()
149+
}
150+
123151
private predicate hashAlgorithmToFamily(
124152
string hashName, Crypto::THashType hashFamily, int digestLength
125153
) {
@@ -198,40 +226,44 @@ class ByteArrayOrReadOnlyByteSpanType extends Type {
198226
}
199227
}
200228

201-
class HashUse extends MethodCall {
229+
class HashUse extends Crypto::AlgorithmValueConsumer instanceof MethodCall {
202230
HashUse() {
203231
this.getQualifier().getType() instanceof HashAlgorithmType and
204232
this.getTarget()
205-
.getName()
206-
.matches([
233+
.hasName([
207234
"ComputeHash", "ComputeHashAsync", "HashCore", "HashData", "HashDataAsync",
208235
"TransformBlock", "TransformFinalBlock", "TryComputeHash", "TryHashData",
209236
"TryHashFinal", "HashFinal"
210237
])
211238
}
212239

213-
predicate isIntermediate() { this.getTarget().hasName("HashCore") }
240+
predicate isIntermediate() { super.getTarget().hasName("HashCore") }
214241

215-
Expr getOutputArtifact() {
242+
Expr getOutput() {
216243
not this.isIntermediate() and
217244
// some functions receive the destination as a parameter
218245
if
219-
this.getTarget().getName() = ["TryComputeHash", "TryHashFinal", "TryHashData"]
246+
super.getTarget().getName() = ["TryComputeHash", "TryHashFinal", "TryHashData"]
220247
or
221-
this.getTarget().getName() = ["HashData"] and this.getNumberOfArguments() = 2
248+
super.getTarget().getName() = ["HashData"] and super.getNumberOfArguments() = 2
222249
or
223-
this.getTarget().getName() = ["HashDataAsync"] and this.getNumberOfArguments() = 3
224-
then result = this.getArgument(1)
250+
super.getTarget().getName() = ["HashDataAsync"] and super.getNumberOfArguments() = 3
251+
then result = super.getArgument(1)
225252
else result = this
226253
}
227254

228255
Expr getInputArg() {
229-
result = this.getAnArgument() and result.getType() instanceof ByteArrayOrReadOnlyByteSpanType
256+
result = super.getArgument(0) and result.getType() instanceof ByteArrayOrReadOnlyByteSpanType
230257
}
231-
// Expr getStreamArg() {
232-
// result = this.getAnArgument() and
233-
// result.getType() instanceof Stream
234-
// }
258+
259+
Expr getStreamArg() {
260+
result = super.getAnArgument() and
261+
result.getType() instanceof Stream
262+
}
263+
264+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = super.getQualifier() }
265+
266+
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
235267
}
236268

237269
class SignerUse extends MethodCall {

csharp/ql/lib/experimental/quantum/dotnet/OperationInstances.qll

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,8 @@ private import Cryptography
77

88
class ECDsaORRSASigningOperationInstance extends Crypto::SignatureOperationInstance instanceof SignerUse
99
{
10-
SigningCreateCall creator;
11-
12-
ECDsaORRSASigningOperationInstance() {
13-
creator = SigningCreateToUseFlow::getCreationFromUse(this, _, _)
14-
}
15-
1610
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
17-
result = creator.getAlgorithmArg()
11+
result = SigningCreateToUseFlow::getCreationFromUse(this, _, _).getAlgorithmArg()
1812
}
1913

2014
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
@@ -27,7 +21,7 @@ class ECDsaORRSASigningOperationInstance extends Crypto::SignatureOperationInsta
2721
}
2822

2923
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
30-
result.asExpr() = creator.getKeyConsumer()
24+
result.asExpr() = SigningCreateToUseFlow::getCreationFromUse(this, _, _).getKeyConsumer()
3125
}
3226

3327
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() { none() }
@@ -45,18 +39,25 @@ class ECDsaORRSASigningOperationInstance extends Crypto::SignatureOperationInsta
4539
}
4640
}
4741

48-
// class HashOperationInstance extends Crypto::HashOperationInstance instanceof HashUse {
49-
// HashOperationInstance() {
50-
// not super.isIntermediate()
51-
// }
52-
// override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
53-
// result.asExpr() = super.getOutputArtifact()
54-
// }
55-
// override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
56-
// result.asExpr() = super.getInputArg() or result = StreamFlow::getIntermediateUse(this.getStreamArg(), _, _).getInputArg()
57-
// }
58-
// override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { result = HashCreateToUseFlow::getCreationFromUse(this, _, _) }
59-
// }
42+
class HashOperationInstance extends Crypto::HashOperationInstance instanceof HashUse {
43+
HashOperationInstance() { not super.isIntermediate() }
44+
45+
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
46+
result.asExpr() = super.getOutput()
47+
}
48+
49+
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
50+
result.asExpr() = super.getInputArg() or
51+
result.asExpr() = StreamFlow::getEarlierUse(super.getStreamArg(), _, _).getInputArg()
52+
}
53+
54+
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
55+
if exists(HashCreateToUseFlow::getCreationFromUse(this, _, _))
56+
then result = HashCreateToUseFlow::getCreationFromUse(this, _, _)
57+
else result = this
58+
}
59+
}
60+
6061
/**
6162
* A symmetric algorithm class, such as AES or DES.
6263
*/

0 commit comments

Comments
 (0)