Skip to content

Commit 8a7671d

Browse files
committed
Adding block mode models to openssl.
1 parent 71eae39 commit 8a7671d

File tree

1 file changed

+85
-9
lines changed

1 file changed

+85
-9
lines changed

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

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import EVPCipherConsumers
44
import OpenSSLAlgorithmGetter
55

66
/**
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)
7+
* Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type.
8+
* Does not bind if there is know mapping (no mapping to 'unknown' or 'other').
119
*/
12-
predicate knownOpenSSLConstantToCipherFamilyType(KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type) {
10+
predicate knownOpenSSLConstantToCipherFamilyType(
11+
KnownOpenSSLAlgorithmConstant e, Crypto::TCipherType type
12+
) {
1313
exists(string name | e.getAlgType().toLowerCase().matches("%encryption") |
1414
name = e.getNormalizedName() and
1515
(
@@ -90,16 +90,92 @@ class KnownOpenSSLCipherConstantAlgorithmInstance extends Crypto::CipherAlgorith
9090
}
9191

9292
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() {
93-
none() // TODO: provider defaults
93+
// if there is a block mode associated with the same element, then that's the block mode
94+
// note, if none are associated, we may need to parse if the cipher is a block cipher
95+
// to determine if this is an unknown vs not relevant.
96+
result = this
9497
}
9598

9699
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
97100

98101
override string getRawAlgorithmName() { result = this.(Literal).getValue().toString() }
99102

100-
override Crypto::TCipherType getCipherFamily() {
101-
knownOpenSSLConstantToCipherFamilyType(this, result)
103+
override Crypto::TCipherType getCipherFamily() {
104+
knownOpenSSLConstantToCipherFamilyType(this, result)
102105
or
103106
not knownOpenSSLConstantToCipherFamilyType(this, _) and result = Crypto::OtherCipherType()
104107
}
105-
}
108+
}
109+
110+
/**
111+
* Given a `KnownOpenSSLAlgorithmConstant`, converts this to a cipher family type.
112+
* Does not bind if there is know mapping (no mapping to 'unknown' or 'other').
113+
*/
114+
predicate knownOpenSSLConstantToBlockModeFamilyType(
115+
KnownOpenSSLAlgorithmConstant e, Crypto::TBlockCipherModeOperationType type
116+
) {
117+
exists(string name | e.getAlgType().toLowerCase().matches("block_mode") |
118+
name = e.getNormalizedName() and
119+
(
120+
name.matches("CBC") and type instanceof Crypto::CBC
121+
or
122+
name.matches("CFB%") and type instanceof Crypto::CFB
123+
or
124+
name.matches("CTR") and type instanceof Crypto::CTR
125+
or
126+
name.matches("GCM") and type instanceof Crypto::GCM
127+
or
128+
name.matches("OFB") and type instanceof Crypto::OFB
129+
or
130+
name.matches("XTS") and type instanceof Crypto::XTS
131+
or
132+
name.matches("CCM") and type instanceof Crypto::CCM
133+
or
134+
name.matches("GCM") and type instanceof Crypto::GCM
135+
or
136+
name.matches("CCM") and type instanceof Crypto::CCM
137+
or
138+
name.matches("ECB") and type instanceof Crypto::ECB
139+
)
140+
)
141+
}
142+
143+
class KnownOpenSSLBlockModeConstantAlgorithmInstance extends Crypto::ModeOfOperationAlgorithmInstance instanceof KnownOpenSSLAlgorithmConstant
144+
{
145+
OpenSSLAlgorithmGetterCall getterCall;
146+
147+
KnownOpenSSLBlockModeConstantAlgorithmInstance() {
148+
// Not just any known value, but specifically a known cipher operation
149+
this.(KnownOpenSSLAlgorithmConstant).getAlgType().toLowerCase().matches("block_mode") and
150+
(
151+
// Two possibilities:
152+
// 1) The source is a literal and flows to a getter, then we know we have an instance
153+
// 2) The source is a KnownOpenSSLAlgorithm is call, and we know we have an instance immediately from that
154+
// Possibility 1:
155+
this instanceof Literal and
156+
exists(DataFlow::Node src, DataFlow::Node sink |
157+
// Sink is an argument to a CipherGetterCall
158+
sink = getterCall.(OpenSSLAlgorithmGetterCall).getValueArgNode() and
159+
// Source is `this`
160+
src.asExpr() = this and
161+
// This traces to a getter
162+
KnownOpenSSLAlgorithmToAlgorithmGetterFlow::flow(src, sink)
163+
)
164+
or
165+
// Possibility 2:
166+
this instanceof DirectGetterCall and getterCall = this
167+
)
168+
}
169+
170+
override Crypto::TBlockCipherModeOperationType getModeType() {
171+
knownOpenSSLConstantToBlockModeFamilyType(this, result)
172+
or
173+
not knownOpenSSLConstantToBlockModeFamilyType(this, _) and result = Crypto::OtherMode()
174+
}
175+
176+
// NOTE: I'm not going to attempt to parse out the mode specific part, so returning
177+
// the same as the raw name for now.
178+
override string getRawModeAlgorithmName() { result = this.(Literal).getValue().toString() }
179+
180+
override string getRawAlgorithmName() { result = this.getRawModeAlgorithmName() }
181+
}

0 commit comments

Comments
 (0)