Skip to content

Commit 0672027

Browse files
committed
Tracing new notion of known getters, which now includes direct getters for cipher and hash. Removed a redundant hash qll, and fixed misplacement of has type in model.
1 parent 4518086 commit 0672027

7 files changed

Lines changed: 107 additions & 121 deletions

File tree

cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherAlgorithmSource.qll

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import experimental.Quantum.Language
33
import EVPCipherConsumers
44
import OpenSSLAlgorithmGetter
55

6-
predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
6+
/**
7+
* Given a literal `e`, converts this to a cipher family type.
8+
* The literal must be a known literal representing a cipher algorithm.
9+
* If the literal does not represent any known cipher algorithm,
10+
* this predicate will not hold (i.e., it will not bind an unknown to an unknown cipher type)
11+
*/
12+
predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
713
exists(string name, string algType | algType.toLowerCase().matches("%encryption") |
814
resolveAlgorithmFromLiteral(e, name, algType) and
915
(
@@ -52,25 +58,36 @@ predicate literalToCipherFamilyType(Literal e, Crypto::TCipherType type) {
5258
)
5359
}
5460

55-
class CipherKnownAlgorithmLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof Literal
61+
class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant
5662
{
57-
OpenSSLAlgorithmGetterCall cipherGetterCall;
58-
CipherKnownAlgorithmLiteralAlgorithmInstance() {
59-
exists(DataFlow::Node src, DataFlow::Node sink |
60-
sink = cipherGetterCall.getValueArgNode() and
61-
src.asExpr() = this and
62-
KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and
63-
// Not just any known value, but specifically a known cipher operation
64-
exists(string algType |
65-
resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and
66-
algType.toLowerCase().matches("%encryption")
63+
OpenSSLAlgorithmGetterCall getterCall;
64+
65+
KnownOpenSSLCipherConstantAlgorithmInstance() {
66+
// Not just any known value, but specifically a known cipher operation
67+
this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("%encryption") and
68+
(
69+
// Two possibilities:
70+
// 1) The source is a literal and flows to a getter, then we know we have an instance
71+
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
72+
// Possibility 1:
73+
this instanceof Literal and
74+
exists(DataFlow::Node src, DataFlow::Node sink |
75+
// Sink is an argument to a CipherGetterCall
76+
sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and
77+
// Source is `this`
78+
src.asExpr() = this and
79+
// This traces to a getter
80+
KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink)
6781
)
82+
or
83+
// Possibility 2:
84+
this instanceof DirectGetterCall and getterCall = this
6885
)
6986
}
7087

71-
Crypto::AlgorithmConsumer getConsumer() {
72-
AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result))
73-
}
88+
Crypto::AlgorithmConsumer getConsumer() {
89+
AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result))
90+
}
7491

7592
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() {
7693
none() // TODO: provider defaults

cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@ import EVPCipherInitializer
22
import EVPCipherOperation
33
import EVPCipherAlgorithmSource
44

5-
65
class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument
7-
{
8-
override DataFlow::Node getInputNode() { result.asExpr() = this }
6+
{
7+
override DataFlow::Node getInputNode() { result.asExpr() = this }
98

10-
override Crypto::AlgorithmElement getAKnownAlgorithmSource() {
11-
result.(CipherKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this
12-
}
9+
override Crypto::AlgorithmElement getAKnownAlgorithmSource() {
10+
result.(KnownOpenSSLCipherConstantAlgorithmInstance).getConsumer() = this
11+
}
1312
}
13+
1414
// //TODO: need a key consumer
1515
// class EVP_Initializer_Key_Consumer extends Crypto::KeyConsumer instanceof EVP_Cipher_Inititalizer isntanceof InitializerKeyArgument{
1616
// }
17-
class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument{
18-
override DataFlow::Node getInputNode() { result.asExpr() = this }
17+
class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument
18+
{
19+
override DataFlow::Node getInputNode() { result.asExpr() = this }
1920
}
2021

21-
class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument{
22-
23-
override DataFlow::Node getInputNode() { result.asExpr() = this }
22+
class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument
23+
{
24+
override DataFlow::Node getInputNode() { result.asExpr() = this }
2425
}
25-

cpp/ql/lib/experimental/Quantum/OpenSSL/EVPDigestAlgorithmSource.qll

Lines changed: 0 additions & 67 deletions
This file was deleted.
Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import cpp
22
import experimental.Quantum.Language
3-
import EVPHashConsumers
43
import OpenSSLAlgorithmGetter
54

65
predicate literalToHashFamilyType(Literal e, Crypto::THashType type) {
@@ -11,12 +10,16 @@ predicate literalToHashFamilyType(Literal e, Crypto::THashType type) {
1110
or
1211
name.matches("BLAKE2S") and type instanceof Crypto::BLAKE2S
1312
or
13+
name.matches("GOST%") and type instanceof Crypto::GOSTHash
14+
or
1415
name.matches("MD2") and type instanceof Crypto::MD2
1516
or
1617
name.matches("MD4") and type instanceof Crypto::MD4
1718
or
1819
name.matches("MD5") and type instanceof Crypto::MD5
1920
or
21+
name.matches("MDC2") and type instanceof Crypto::MDC2
22+
or
2023
name.matches("POLY1305") and type instanceof Crypto::POLY1305
2124
or
2225
name.matches(["SHA", "SHA1"]) and type instanceof Crypto::SHA1
@@ -31,40 +34,45 @@ predicate literalToHashFamilyType(Literal e, Crypto::THashType type) {
3134
or
3235
name.matches("RIPEMD160") and type instanceof Crypto::RIPEMD160
3336
or
34-
//or
35-
//TODO: need to handle MACs differently, including md_GOST94
36-
// name.matches("%GOST%") and type instanceof Crypto::GOST
3737
name.matches("WHIRLPOOL") and type instanceof Crypto::WHIRLPOOL
3838
)
3939
)
4040
}
4141

42-
class HashKnownAlgorithmLiteralAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof Literal
42+
class KnownOpenSSLHashConstantAlgorithmInstance extends Crypto::HashAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant
4343
{
44-
OpenSSLAlgorithmGetterCall cipherGetterCall;
44+
OpenSSLAlgorithmGetterCall getterCall;
4545

46-
HashKnownAlgorithmLiteralAlgorithmInstance() {
47-
exists(DataFlow::Node src, DataFlow::Node sink |
48-
sink = cipherGetterCall.getValueArgNode() and
49-
src.asExpr() = this and
50-
KnownAlgorithmLiteralToAlgorithmGetterFlow::flow(src, sink) and
51-
// Not just any known value, but specifically a known cipher operation
52-
exists(string algType |
53-
resolveAlgorithmFromLiteral(src.asExpr(), _, algType) and
54-
algType.toLowerCase().matches("hash")
46+
KnownOpenSSLHashConstantAlgorithmInstance() {
47+
// Not just any known value, but specifically a known hash
48+
this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("hash") and
49+
(
50+
// Two possibilities:
51+
// 1) The source is a literal and flows to a getter, then we know we have an instance
52+
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
53+
// Possibility 1:
54+
this instanceof Literal and
55+
exists(DataFlow::Node src, DataFlow::Node sink |
56+
// Sink is an argument to a CipherGetterCall
57+
sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and
58+
// Source is `this`
59+
src.asExpr() = this and
60+
// This traces to a getter
61+
KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink)
5562
)
63+
or
64+
// Possibility 2:
65+
this instanceof DirectGetterCall and getterCall = this
5666
)
5767
}
5868

5969
Crypto::AlgorithmConsumer getConsumer() {
60-
AlgGetterToAlgConsumerFlow::flow(cipherGetterCall.getResultNode(), DataFlow::exprNode(result))
70+
AlgGetterToAlgConsumerFlow::flow(getterCall.getResultNode(), DataFlow::exprNode(result))
6171
}
6272

63-
override Crypto::THashType getHashFamily() {
64-
literalToHashFamilyType(this, result)
65-
}
73+
override Crypto::THashType getHashFamily() { literalToHashFamilyType(this, result) }
6674

6775
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
6876

69-
override int getHashSize() {none() }//TODO
77+
override int getHashSize() { none() } //TODO
7078
}

cpp/ql/lib/experimental/Quantum/OpenSSL/EVPHashConsumers.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ class EVP_Digest_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsume
66
override DataFlow::Node getInputNode() { result.asExpr() = this }
77

88
override Crypto::AlgorithmElement getAKnownAlgorithmSource() {
9-
result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this
9+
result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this
1010
}
1111
}
1212

1313
class EVP_Q_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Q_Digest_Algorithm_Argument{
1414
override DataFlow::Node getInputNode() { result.asExpr() = this }
1515

1616
override Crypto::AlgorithmElement getAKnownAlgorithmSource() {
17-
result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this
17+
result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this
1818
}
1919
}
2020

2121
class EVP_Digest_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVP_Digest_Algorithm_Argument{
2222
override DataFlow::Node getInputNode() { result.asExpr() = this }
2323

2424
override Crypto::AlgorithmElement getAKnownAlgorithmSource() {
25-
result.(HashKnownAlgorithmLiteralAlgorithmInstance).getConsumer() = this
25+
result.(KnownOpenSSLHashConstantAlgorithmInstance).getConsumer() = this
2626
}
2727
}

cpp/ql/lib/experimental/Quantum/OpenSSL/OpenSSLAlgorithmGetter.qll

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,10 @@ abstract class OpenSSLAlgorithmGetterCall extends Call {
128128
abstract Expr getResultExpr();
129129
}
130130

131-
module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigSig {
132-
predicate isSource(DataFlow::Node source) { resolveAlgorithmFromLiteral(source.asExpr(), _, _) }
131+
module KnownOpenSSLAlgorithmToAlgorithmGetterConfig implements DataFlow::ConfigSig {
132+
predicate isSource(DataFlow::Node source) {
133+
source.asExpr() instanceof KnownOpenSSLAlgorithmConstant
134+
}
133135

134136
predicate isSink(DataFlow::Node sink) {
135137
exists(OpenSSLAlgorithmGetterCall c | c.getValueArgNode() = sink)
@@ -151,8 +153,33 @@ module KnownAlgorithmLiteralToAlgorithmGetterConfig implements DataFlow::ConfigS
151153
}
152154
}
153155

154-
module KnownAlgorithmLiteralToAlgorithmGetterFlow =
155-
DataFlow::Global<KnownAlgorithmLiteralToAlgorithmGetterConfig>;
156+
module KnownOpenSSLAlgorithmToAlgorithmGetterFlow =
157+
DataFlow::Global<KnownOpenSSLAlgorithmToAlgorithmGetterConfig>;
158+
159+
/**
160+
* Cases like EVP_MD5(),
161+
* there is no input, rather it directly gets an algorithm
162+
* and returns it.
163+
*/
164+
class DirectGetterCall extends OpenSSLAlgorithmGetterCall {
165+
DataFlow::Node resultNode;
166+
Expr resultExpr;
167+
168+
DirectGetterCall() {
169+
this instanceof KnownOpenSSLAlgorithmConstant and
170+
this instanceof Call and
171+
resultExpr = this and
172+
resultNode.asExpr() = resultExpr
173+
}
174+
175+
override DataFlow::Node getValueArgNode() { none() }
176+
177+
override DataFlow::Node getResultNode() { result = resultNode }
178+
179+
override Expr getValueArgExpr() { none() }
180+
181+
override Expr getResultExpr() { result = resultExpr }
182+
}
156183

157184
// https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
158185
class EVPCipherGetterCall extends OpenSSLAlgorithmGetterCall {

shared/cryptography/codeql/cryptography/Model.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ module CryptographyBase<LocationSig Location, InputSig<Location> Input> {
10421042
MD2() or
10431043
MD4() or
10441044
MD5() or
1045+
MDC2() or
10451046
POLY1305() or
10461047
SHA1() or
10471048
SHA2() or

0 commit comments

Comments
 (0)