Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9f2c59c

Browse files
committed
python: implement getBlockMode for CryptographicOperations
1 parent 03e34e0 commit 9f2c59c

5 files changed

Lines changed: 89 additions & 7 deletions

File tree

python/ql/lib/semmle/python/Concepts.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,13 @@ module Cryptography {
12261226

12271227
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
12281228
DataFlow::Node getAnInput() { result = super.getAnInput() }
1229+
1230+
/**
1231+
* Gets the block mode used to perform this cryptographic operation.
1232+
* This may have no result - for example if the `CryptographicAlgorithm` used
1233+
* is a stream cipher rather than a block cipher.
1234+
*/
1235+
BlockMode getBlockMode() { result = super.getBlockMode() }
12291236
}
12301237

12311238
/** Provides classes for modeling new applications of a cryptographic algorithms. */
@@ -1243,6 +1250,24 @@ module Cryptography {
12431250

12441251
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
12451252
abstract DataFlow::Node getAnInput();
1253+
1254+
/**
1255+
* Gets the block mode used to perform this cryptographic operation.
1256+
* This may have no result - for example if the `CryptographicAlgorithm` used
1257+
* is a stream cipher rather than a block cipher.
1258+
*/
1259+
abstract BlockMode getBlockMode();
12461260
}
12471261
}
1262+
1263+
/**
1264+
* A cryptographic block cipher mode of operation. This can be used to encrypt
1265+
* data of arbitrary length using a block encryption algorithm.
1266+
*/
1267+
class BlockMode extends string {
1268+
BlockMode() { this = ["ECB", "CBC", "GCM", "CCM", "CFB", "OFB", "CTR", "OPENPGP"] }
1269+
1270+
/** Holds if this block mode is considered to be insecure. */
1271+
predicate isWeak() { this = "ECB" }
1272+
}
12481273
}

python/ql/lib/semmle/python/frameworks/Cryptodome.qll

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,20 @@ private module CryptodomeModel {
108108
DataFlow::CallCfgNode {
109109
string methodName;
110110
string cipherName;
111+
API::CallNode newCall;
111112

112113
CryptodomeGenericCipherOperation() {
113114
methodName in [
114115
"encrypt", "decrypt", "verify", "update", "hexverify", "encrypt_and_digest",
115116
"decrypt_and_verify"
116117
] and
117-
this =
118+
newCall =
118119
API::moduleImport(["Crypto", "Cryptodome"])
119120
.getMember("Cipher")
120121
.getMember(cipherName)
121122
.getMember("new")
122-
.getReturn()
123-
.getMember(methodName)
124-
.getACall()
123+
.getACall() and
124+
this = newCall.getReturn().getMember(methodName).getACall()
125125
}
126126

127127
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(cipherName) }
@@ -155,6 +155,20 @@ private module CryptodomeModel {
155155
this.getArgByName("mac_tag")
156156
]
157157
}
158+
159+
override Cryptography::BlockMode getBlockMode() {
160+
// `modeName` is of the form "MODE_<BlockMode>"
161+
exists(string modeName |
162+
newCall.getArg(1) =
163+
API::moduleImport(["Crypto", "Cryptodome"])
164+
.getMember("Cipher")
165+
.getMember(cipherName)
166+
.getMember(modeName)
167+
.getAUse()
168+
|
169+
result = modeName.splitAt("_", 1)
170+
)
171+
}
158172
}
159173

160174
/**
@@ -192,6 +206,8 @@ private module CryptodomeModel {
192206
result in [this.getArg(1), this.getArgByName("signature")]
193207
)
194208
}
209+
210+
override Cryptography::BlockMode getBlockMode() { none() }
195211
}
196212

197213
/**
@@ -215,5 +231,7 @@ private module CryptodomeModel {
215231
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
216232

217233
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }
234+
235+
override Cryptography::BlockMode getBlockMode() { none() }
218236
}
219237
}

python/ql/lib/semmle/python/frameworks/Cryptography.qll

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,19 @@ private module CryptographyModel {
170170
.getMember(algorithmName)
171171
}
172172

173+
/** Gets a reference to a `cryptography.hazmat.primitives.ciphers.modes` Class */
174+
API::Node modeClassRef(string modeName) {
175+
result =
176+
API::moduleImport("cryptography")
177+
.getMember("hazmat")
178+
.getMember("primitives")
179+
.getMember("ciphers")
180+
.getMember("modes")
181+
.getMember(modeName)
182+
}
183+
173184
/** Gets a reference to a Cipher instance using algorithm with `algorithmName`. */
174-
API::Node cipherInstance(string algorithmName) {
185+
API::Node cipherInstance(string algorithmName, string modeName) {
175186
exists(API::CallNode call | result = call.getReturn() |
176187
call =
177188
API::moduleImport("cryptography")
@@ -182,7 +193,12 @@ private module CryptographyModel {
182193
.getACall() and
183194
algorithmClassRef(algorithmName).getReturn().getAUse() in [
184195
call.getArg(0), call.getArgByName("algorithm")
185-
]
196+
] and
197+
exists(DataFlow::Node modeArg | modeArg in [call.getArg(1), call.getArgByName("mode")] |
198+
modeArg = modeClassRef(modeName).getReturn().getAUse()
199+
or
200+
modeArg.asExpr() instanceof None and modeName = "<none>"
201+
)
186202
)
187203
}
188204

@@ -192,10 +208,11 @@ private module CryptographyModel {
192208
class CryptographyGenericCipherOperation extends Cryptography::CryptographicOperation::Range,
193209
DataFlow::MethodCallNode {
194210
string algorithmName;
211+
string modeName;
195212

196213
CryptographyGenericCipherOperation() {
197214
this =
198-
cipherInstance(algorithmName)
215+
cipherInstance(algorithmName, modeName)
199216
.getMember(["decryptor", "encryptor"])
200217
.getReturn()
201218
.getMember(["update", "update_into"])
@@ -207,6 +224,8 @@ private module CryptographyModel {
207224
}
208225

209226
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }
227+
228+
override Cryptography::BlockMode getBlockMode() { result = modeName }
210229
}
211230
}
212231

@@ -257,6 +276,8 @@ private module CryptographyModel {
257276
}
258277

259278
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }
279+
280+
override Cryptography::BlockMode getBlockMode() { none() }
260281
}
261282
}
262283
}

python/ql/lib/semmle/python/frameworks/Rsa.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ private module Rsa {
4141
override DataFlow::Node getAnInput() {
4242
result in [this.getArg(0), this.getArgByName("message")]
4343
}
44+
45+
override Cryptography::BlockMode getBlockMode() { none() }
4446
}
4547

4648
/**
@@ -54,6 +56,8 @@ private module Rsa {
5456
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
5557

5658
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("crypto")] }
59+
60+
override Cryptography::BlockMode getBlockMode() { none() }
5761
}
5862

5963
/**
@@ -79,6 +83,8 @@ private module Rsa {
7983
override DataFlow::Node getAnInput() {
8084
result in [this.getArg(0), this.getArgByName("message")]
8185
}
86+
87+
override Cryptography::BlockMode getBlockMode() { none() }
8288
}
8389

8490
/**
@@ -100,6 +106,8 @@ private module Rsa {
100106
or
101107
result in [this.getArg(1), this.getArgByName("signature")]
102108
}
109+
110+
override Cryptography::BlockMode getBlockMode() { none() }
103111
}
104112

105113
/**
@@ -122,6 +130,8 @@ private module Rsa {
122130
override DataFlow::Node getAnInput() {
123131
result in [this.getArg(0), this.getArgByName("message")]
124132
}
133+
134+
override Cryptography::BlockMode getBlockMode() { none() }
125135
}
126136

127137
/**
@@ -137,5 +147,7 @@ private module Rsa {
137147
override DataFlow::Node getAnInput() {
138148
result in [this.getArg(0), this.getArgByName("hash_value")]
139149
}
150+
151+
override Cryptography::BlockMode getBlockMode() { none() }
140152
}
141153
}

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,6 +2671,8 @@ private module StdlibPrivate {
26712671
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
26722672

26732673
override DataFlow::Node getAnInput() { result = this.getParameter(1, "data").getARhs() }
2674+
2675+
override Cryptography::BlockMode getBlockMode() { none() }
26742676
}
26752677

26762678
/**
@@ -2686,6 +2688,8 @@ private module StdlibPrivate {
26862688
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
26872689

26882690
override DataFlow::Node getAnInput() { result = this.getArg(0) }
2691+
2692+
override Cryptography::BlockMode getBlockMode() { none() }
26892693
}
26902694

26912695
/** Helper predicate for the `HashLibGenericHashOperation` charpred, to prevent a bad join order. */
@@ -2709,6 +2713,8 @@ private module StdlibPrivate {
27092713
HashlibGenericHashOperation() { hashClass = hashlibMember(hashName) }
27102714

27112715
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
2716+
2717+
override Cryptography::BlockMode getBlockMode() { none() }
27122718
}
27132719

27142720
/**

0 commit comments

Comments
 (0)