Skip to content

Commit 791c260

Browse files
committed
quantum-c#: Add HashAlgorithmInstance
1 parent 3913f44 commit 791c260

5 files changed

Lines changed: 94 additions & 25 deletions

File tree

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ private import AlgorithmValueConsumers
44
private import Cryptography
55
private import FlowAnalysis
66

7-
class SigningNamedCurveAlgorithmInstance extends Crypto::EllipticCurveInstance instanceof SigningNamedCurvePropertyAccess
7+
class NamedCurveAlgorithmInstance extends Crypto::EllipticCurveInstance instanceof SigningNamedCurvePropertyAccess
88
{
99
ECDsaAlgorithmValueConsumer consumer;
1010

11-
SigningNamedCurveAlgorithmInstance() {
11+
NamedCurveAlgorithmInstance() {
1212
SigningNamedCurveToSignatureCreateFlow::flow(DataFlow::exprNode(this), consumer.getInputNode())
1313
}
1414

@@ -25,6 +25,30 @@ class SigningNamedCurveAlgorithmInstance extends Crypto::EllipticCurveInstance i
2525
}
2626
}
2727

28+
class EcdsaAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance instanceof ECDsaCreateCall
29+
{
30+
EcdsaAlgorithmInstance() {
31+
// SigningNamedCurveToSignatureCreateFlow::flow(DataFlow::exprNode(this), consumer.getInputNode())
32+
this instanceof ECDsaCreateCall
33+
}
34+
35+
ECDsaAlgorithmValueConsumer getConsumer() { result = super.getQualifier() }
36+
37+
override string getRawAlgorithmName() { result = "ECDsa" }
38+
39+
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
40+
41+
// TODO: PaddingAlgorithmInstance errors with "call to empty relation: class test for Model::CryptographyBase::PaddingAlgorithmInstance"
42+
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
43+
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() }
44+
45+
override int getKeySizeFixed() { none() }
46+
47+
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
48+
result = Crypto::KeyOpAlg::TSignature(Crypto::KeyOpAlg::ECDSA())
49+
}
50+
}
51+
2852
class HashAlgorithmNameInstance extends Crypto::HashAlgorithmInstance instanceof HashAlgorithmName {
2953
HashAlgorithmNameConsumer consumer;
3054

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class ECDsaAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer {
1111
override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this }
1212

1313
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
14-
exists(SigningNamedCurveAlgorithmInstance l | l.getConsumer() = this and result = l)
14+
exists(NamedCurveAlgorithmInstance l | l.getConsumer() = this and result = l)
1515
}
1616
}
1717

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

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,25 @@ class ECCurve extends CryptographyType {
1717
ECCurve() { this.hasName("ECCurve") }
1818
}
1919

20+
class HashAlgorithmType extends CryptographyType {
21+
HashAlgorithmType() {
22+
this.hasName([
23+
"MD5",
24+
"RIPEMD160",
25+
"SHA1",
26+
"SHA256",
27+
"SHA384",
28+
"SHA512",
29+
"SHA3_256",
30+
"SHA3_384",
31+
"SHA3_512"
32+
])
33+
}
34+
}
35+
2036
// This class models Create calls for the ECDsa and RSA classes in .NET.
21-
class SigningCreateCall extends MethodCall {
22-
SigningCreateCall() {
37+
class CryptographyCreateCall extends MethodCall {
38+
CryptographyCreateCall() {
2339
this.getTarget().getName() = "Create" and
2440
this.getQualifier().getType() instanceof CryptographyType
2541
}
@@ -41,7 +57,7 @@ class SigningCreateCall extends MethodCall {
4157
}
4258
}
4359

44-
class ECDsaCreateCall extends SigningCreateCall {
60+
class ECDsaCreateCall extends CryptographyCreateCall {
4561
ECDsaCreateCall() { this.getQualifier().getType().hasName("ECDsa") }
4662
}
4763

@@ -54,28 +70,21 @@ class ECDsaCreateCallWithECCurve extends ECDsaCreateCall {
5470
ECDsaCreateCallWithECCurve() { this.getArgument(0).getType() instanceof ECCurve }
5571
}
5672

57-
class RSACreateCall extends SigningCreateCall {
73+
class RSACreateCall extends CryptographyCreateCall {
5874
RSACreateCall() { this.getQualifier().getType().hasName("RSA") }
5975
}
6076

61-
class HashAlgorithmCreateCall extends SigningCreateCall {
62-
HashAlgorithmCreateCall() {
63-
this.getQualifier()
64-
.getType()
65-
.hasName([
66-
"MD5",
67-
"RIPEMD160",
68-
"SHA1",
69-
"SHA256",
70-
"SHA384",
71-
"SHA512",
72-
"SHA3_256",
73-
"SHA3_384",
74-
"SHA3_512"
75-
])
77+
class SigningCreateCall extends CryptographyCreateCall {
78+
SigningCreateCall() {
79+
this instanceof ECDsaCreateCall or
80+
this instanceof RSACreateCall
7681
}
7782
}
7883

84+
class HashAlgorithmCreateCall extends CryptographyCreateCall {
85+
HashAlgorithmCreateCall() { this.getQualifier().getType() instanceof HashAlgorithmType }
86+
}
87+
7988
class SigningNamedCurvePropertyAccess extends PropertyAccess {
8089
string curveName;
8190

@@ -166,6 +175,13 @@ private class RSAClass extends CryptographyType {
166175
RSAClass() { this.hasName("RSA") }
167176
}
168177

178+
private class SignerType extends Type {
179+
SignerType() {
180+
this instanceof ECDsaClass or
181+
this instanceof RSAClass
182+
}
183+
}
184+
169185
class ByteArrayType extends Type {
170186
ByteArrayType() { this.getName() = "Byte[]" }
171187
}
@@ -174,8 +190,25 @@ class ReadOnlyByteSpanType extends Type {
174190
ReadOnlyByteSpanType() { this.getName() = "ReadOnlySpan<Byte>" }
175191
}
176192

193+
class HashUse extends MethodCall {
194+
HashUse() {
195+
this.getQualifier().getType() instanceof HashAlgorithmType and
196+
this.getTarget()
197+
.getName()
198+
.matches([
199+
"ComputeHash", "ComputeHashAsync", "HashCore", "HashData", "HashDataAsync",
200+
"TransformBlock", "TransformFinalBlock", "TryComputeHash", "TryHashData", "TryHashFinal"
201+
])
202+
}
203+
204+
predicate isIntermediate() { this.getTarget().hasName("HashCore") }
205+
}
206+
177207
class SignerUse extends MethodCall {
178-
SignerUse() { this.getTarget().getName().matches(["Verify%", "Sign%"]) }
208+
SignerUse() {
209+
this.getTarget().getName().matches(["Verify%", "Sign%"]) and
210+
this.getQualifier().getType() instanceof SignerType
211+
}
179212

180213
Expr getMessageArg() {
181214
// Both Sign and Verify methods take the message as the first argument.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ signature class UseCallSig instanceof QualifiableExpr {
3434

3535
module SigningCreateToUseFlow = CreationToUseFlow<SigningCreateCall, SignerUse>;
3636

37+
module HashCreateToUseFlow = CreationToUseFlow<HashAlgorithmCreateCall, HashUse>;
38+
3739
module CreationToUseFlow<CreationCallSig Creation, UseCallSig Use> {
3840
private module CreationToUseConfig implements DataFlow::ConfigSig {
3941
predicate isSource(DataFlow::Node source) {

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ class ECDsaORRSASigningOperationInstance extends Crypto::SignatureOperationInsta
1414

1515
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
1616
result = creator.getAlgorithmArg()
17-
or
18-
result = super.getHashAlgorithmArg()
1917
}
2018

2119
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
@@ -45,3 +43,15 @@ class ECDsaORRSASigningOperationInstance extends Crypto::SignatureOperationInsta
4543
result.asExpr() = super.getSignatureOutput()
4644
}
4745
}
46+
47+
class HashOperationInstance extends Crypto::HashOperationInstance instanceof HashUse {
48+
HashAlgorithmCreateCall creator;
49+
50+
HashOperationInstance() { creator = HashCreateToUseFlow::getCreationFromUse(this, _, _) }
51+
52+
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() { none() }
53+
54+
override Crypto::ConsumerInputDataFlowNode getInputConsumer() { none() }
55+
56+
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { none() }
57+
}

0 commit comments

Comments
 (0)