Skip to content

Python: cryptography module upgrades #11678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
e3ce715
Create sync_remote_main.yml
bdrodes Nov 23, 2022
a4a3b54
Merge remote-tracking branch 'upstream/main'
your-username Nov 23, 2022
05e8ff1
Merge remote-tracking branch 'upstream/main'
your-username Nov 23, 2022
c204d65
Merge remote-tracking branch 'upstream/main'
your-username Nov 23, 2022
293f07e
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
5eee4ab
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
d98a206
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
b01c6c0
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
d275d6c
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
ad9e4f9
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
63a94d9
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
d241a22
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
9e57f40
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
2da29de
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
46ab801
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
78ef98d
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
95ea865
Merge remote-tracking branch 'upstream/main'
your-username Nov 24, 2022
0fe631f
Merge remote-tracking branch 'upstream/main'
your-username Nov 25, 2022
51c85cc
Merge remote-tracking branch 'upstream/main'
your-username Nov 25, 2022
877dfc2
Merge remote-tracking branch 'upstream/main'
your-username Nov 25, 2022
270516f
Merge remote-tracking branch 'upstream/main'
your-username Nov 26, 2022
ec38da2
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
19403f4
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
575f825
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
afc1652
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
d4a03bb
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
1d9bdda
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
36ce177
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
e568185
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
0072f4d
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
46e1306
Merge remote-tracking branch 'upstream/main'
your-username Nov 28, 2022
ae51a46
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
424b147
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
9a60923
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
9ed360b
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
4535864
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
67f894b
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
5288062
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
c6023ab
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
f380f72
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
fbf0edd
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
543dfd2
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
72a35de
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
b42cc5c
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
1d57f49
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
dc8b13a
Merge remote-tracking branch 'upstream/main'
your-username Nov 29, 2022
2923d0c
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
b6f240e
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
d81e084
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
4b38a00
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
4e1356d
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
8a0463b
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
d8af0bd
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
ffcdef0
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
ddd2101
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
3e6b6ed
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
98082cc
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
2f9a16f
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
6ee7138
Merge remote-tracking branch 'upstream/main'
your-username Nov 30, 2022
28e46df
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
5daaf7f
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
687c0df
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
3c42907
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
b19a5cd
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
3bd4f22
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
02e6724
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
f1e3694
Merge remote-tracking branch 'upstream/main'
your-username Dec 1, 2022
293319c
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
2736364
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
ea8bd55
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
7f49844
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
b7b359f
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
bada2ae
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
39d8277
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
64ac9f7
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
dc4b45a
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
5748496
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
5490fe8
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
390fa06
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
31eda15
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
c173e79
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
96cd88e
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
0c96d41
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
4afd606
Merge remote-tracking branch 'upstream/main'
your-username Dec 2, 2022
92785b1
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
ba04eea
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
732bb00
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
9292471
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
d39b80a
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
bab1523
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
64a3903
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
a80bc3c
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
5e91079
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
86cc483
Merge remote-tracking branch 'upstream/main'
your-username Dec 5, 2022
40abfe3
Adding additional hashing algorithms, and block mode predicates. Also…
bdrodes Dec 7, 2022
2c477c7
Changing BlockMode to use the isKnownCipherBlockModeAlgorithm predica…
bdrodes Dec 7, 2022
a50b01f
Updating cryptodrome and crytopgraphy framework libraries to allow fo…
bdrodes Dec 7, 2022
9bf37b3
Interim partially working refactor of crypto libraries for python.
bdrodes Dec 12, 2022
36fb8f0
Updates for key derivation in stdlib
bdrodes Dec 12, 2022
1ff5cc5
Deleting workflow from branch.
bdrodes Dec 13, 2022
60bff80
Cleanup
bdrodes Dec 13, 2022
05f91f3
More cleanup
bdrodes Dec 13, 2022
a1368a4
More cleanup
bdrodes Dec 13, 2022
8564580
adding a predicate to determine if an encryption algorithm is asymmetric
bdrodes Dec 20, 2022
1be6bc3
updating algorithm names. Removed some entries that are redundant, an…
bdrodes Dec 21, 2022
066270c
Changed mechanics for unknown block mode.
bdrodes Dec 21, 2022
10986e6
Corrected casing on blake sha strings. Added additional sha algorithm…
bdrodes Jan 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ private import internal.CryptoAlgorithmNames
/**
* A cryptographic algorithm.
*/
private newtype TCryptographicAlgorithm =
private newtype TCryptographicAlgorithm =
MkHashingAlgorithm(string name, boolean isWeak) {
isStrongHashingAlgorithm(name) and isWeak = false
or
Expand All @@ -25,6 +25,9 @@ private newtype TCryptographicAlgorithm =
or
isWeakPasswordHashingAlgorithm(name) and isWeak = true
}
or
MkUnknown()


/**
* A cryptographic algorithm.
Expand Down Expand Up @@ -53,6 +56,26 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
* Holds if this algorithm is weak.
*/
abstract predicate isWeak();

/**
* Holds if this algorithm is not known.
*/
predicate isUnknown() { this instanceof UnknownAlgorithm }
}

/**
* An 'Unknown' cryptographic algorithm, typically encountered when extracting as yet unmodelled API algorithms.
*/
class UnknownAlgorithm extends MkUnknown, CryptographicAlgorithm {
override predicate isUnknown() { any() }

override string getName() { result = unknownAlgorithm() }

override predicate isWeak() { any() }

bindingset[name]
override predicate matchesName(string name) { none()}

}

/**
Expand Down Expand Up @@ -82,6 +105,8 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm

override predicate isWeak() { isWeak = true }

predicate isAsymmetricEncryption() { isAsymmetricEncryption(name) }

/** Holds if this algorithm is a stream cipher. */
predicate isStreamCipher() { isStreamCipher(name) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,34 @@
* The classification into strong and weak are based on Wikipedia, OWASP and Google (2021).
*/

/**
* Returns a string to represent generally unknown algorithms.
* Predicate is to be used to get a consistent string representation
* for unknown algorithms.
*/
string unknownAlgorithm()
{
result = "UNKNOWN"
}


/**
* Holds if `name` is a known hashing algorithm in the model/library.
*/
predicate isKnownHashingAlgorithm(string name)
{
isStrongHashingAlgorithm(name) or isWeakHashingAlgorithm(name)
}

/**
* Holds if `name` corresponds to a strong hashing algorithm.
*/
predicate isStrongHashingAlgorithm(string name) {
name =
[
"DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2",
"SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512"
"BLAKE2", "BLAKE2B", "BLAKE2S", "DSA", "ED25519", "ES256", "ECDSA256", "ES384", "ECDSA384", "ES512", "ECDSA512", "SHA2",
"SHA224", "SHA256", "SHA384", "SHA512", "SHA512224", "SHA512256", "SHA3", "SHA3224", "SHA3256", "SHA3384", "SHA3512",
"SHAKE128", "SHAKE256", "SM3", "WHIRLPOOL"
]
}

Expand All @@ -30,16 +50,25 @@ predicate isWeakHashingAlgorithm(string name) {
]
}

/**
* Holds if `name` is a known encryption algorithm in the model/library.
*/
predicate isKnownEncryptionAlgorithm(string name)
{
isStrongEncryptionAlgorithm(name) or isWeakEncryptionAlgorithm(name)
}


/**
* Holds if `name` corresponds to a strong encryption algorithm.
*/
predicate isStrongEncryptionAlgorithm(string name) {
name =
[
"AES", "AES128", "AES192", "AES256", "AES512", "AES-128", "AES-192", "AES-256", "AES-512",
"AES", "AES128", "AES192", "AES256", "AES512",
"ARIA", "BLOWFISH", "BF", "ECIES", "CAST", "CAST5", "CAMELLIA", "CAMELLIA128", "CAMELLIA192",
"CAMELLIA256", "CAMELLIA-128", "CAMELLIA-192", "CAMELLIA-256", "CHACHA", "GOST", "GOST89",
"IDEA", "RABBIT", "RSA", "SEED", "SM4"
"CAMELLIA256", "CHACHA", "GOST", "GOST89",
"IDEA", "RABBIT", "RSA", "SEED", "SM3", "SM4"
]
}

Expand All @@ -54,6 +83,15 @@ predicate isWeakEncryptionAlgorithm(string name) {
]
}

/**
* Holds if `name` is a known password hashing algorithm in the model/library.
*/
predicate isKnownPasswordHashingAlgorithm(string name)
{
isStrongPasswordHashingAlgorithm(name) or isWeakPasswordHashingAlgorithm(name)
}


/**
* Holds if `name` corresponds to a strong password hashing algorithm.
*/
Expand All @@ -64,9 +102,46 @@ predicate isStrongPasswordHashingAlgorithm(string name) {
/**
* Holds if `name` corresponds to a weak password hashing algorithm.
*/
predicate isWeakPasswordHashingAlgorithm(string name) { name = "EVPKDF" }
predicate isWeakPasswordHashingAlgorithm(string name) {
name = "EVPKDF"
}

/**
* Holds if `name` is a known cipher block mode algorithm in the model/library.
*/
predicate isKnownCipherBlockModeAlgorithm(string name)
{
isStrongCipherBlockModeAlgorithm(name) or isWeakCipherBlockModeAlgorithm(name)
}


/**
* Holds if `name` corresponds to a strong cipher block mode
*/
predicate isStrongCipherBlockModeAlgorithm(string name)
{
name = ["CBC", "GCM", "CCM", "CFB", "OFB", "CFB8", "CTR", "OPENPGP", "XTS", "EAX"]
}

/**
* Holds if `name` corresponds to a weak cipher block mode
*/
predicate isWeakCipherBlockModeAlgorithm(string name)
{
name = ["ECB"]

Check warning

Code scanning / CodeQL

Singleton set literal

Singleton set literal can be replaced by its member.
}


/**
* Holds if `name` corresponds to a stream cipher.
*/
predicate isStreamCipher(string name) { name = ["CHACHA", "RC4", "ARC4", "ARCFOUR", "RABBIT"] }


/**
* Holds if `name` corresponds to an asymmetric encryption.
*/
bindingset[name]
predicate isAsymmetricEncryption(string name){
name.regexpMatch("(?i)^rsa.*")
}
46 changes: 28 additions & 18 deletions python/ql/lib/semmle/python/frameworks/Cryptodome.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import semmle.python.concepts.internal.CryptoAlgorithmNames

/**
* Provides models for
Expand Down Expand Up @@ -124,7 +125,9 @@ private module CryptodomeModel {
this = newCall.getReturn().getMember(methodName).getACall()
}

override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(cipherName) }
override string getAlgorithmRaw() {
result = cipherName
}

override DataFlow::Node getAnInput() {
methodName = "encrypt" and
Expand Down Expand Up @@ -156,18 +159,23 @@ private module CryptodomeModel {
]
}

override Cryptography::BlockMode getBlockMode() {
// `modeName` is of the form "MODE_<BlockMode>"
exists(string modeName |
newCall.getArg(1) =
API::moduleImport(["Crypto", "Cryptodome"])
.getMember("Cipher")
.getMember(cipherName)
.getMember(modeName)
.getAValueReachableFromSource()
|
result = modeName.splitAt("_", 1)
)
private predicate resolveModeName(string modeName)
{
newCall.getArg(1) =
API::moduleImport(["Crypto", "Cryptodome"])
.getMember("Cipher")
.getMember(cipherName)
.getMember(modeName)
.getAValueReachableFromSource()
}

override Cryptography::BlockMode getBlockModeRaw() {
// `modeName` is of the form "MODE_<BlockMode>"
exists(string modeName |
if resolveModeName(modeName)

Check warning

Code scanning / CodeQL

Using implicit `this`

Use of implicit `this`.
then result = modeName.splitAt("_", 1)
else modeName = unknownAlgorithm() and
result = unknownAlgorithm())
}
}

Expand All @@ -191,8 +199,8 @@ private module CryptodomeModel {
.getACall()
}

override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(signatureName)
override string getAlgorithmRaw() {
result = signatureName
}

override DataFlow::Node getAnInput() {
Expand All @@ -207,7 +215,7 @@ private module CryptodomeModel {
)
}

override Cryptography::BlockMode getBlockMode() { none() }
override string getBlockModeRaw() { none() }
}

/**
Expand All @@ -228,10 +236,12 @@ private module CryptodomeModel {
)
}

override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
override string getAlgorithmRaw() {
result = hashName
}

override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }

override Cryptography::BlockMode getBlockMode() { none() }
override string getBlockModeRaw() { none() }
}
}
21 changes: 12 additions & 9 deletions python/ql/lib/semmle/python/frameworks/Cryptography.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
import semmle.python.concepts.internal.CryptoAlgorithmNames

/**
* Provides models for the `cryptography` PyPI package.
Expand Down Expand Up @@ -180,7 +181,7 @@ private module CryptographyModel {
}

/** Gets a reference to a Cipher instance using algorithm with `algorithmName`. */
API::Node cipherInstance(string algorithmName, string modeName) {
API::Node symmetricCipherInstance(string algorithmName, string modeName) {
exists(API::CallNode call | result = call.getReturn() |
call =
API::moduleImport("cryptography")
Expand All @@ -193,10 +194,12 @@ private module CryptographyModel {
call.getArg(0), call.getArgByName("algorithm")
] and
exists(DataFlow::Node modeArg | modeArg in [call.getArg(1), call.getArgByName("mode")] |
// Find the used mode name
if modeArg = modeClassRef(_).getReturn().getAValueReachableFromSource()
then modeArg = modeClassRef(modeName).getReturn().getAValueReachableFromSource()
else modeName = "<None or unknown>"
else modeName = unknownAlgorithm()
)

)
}

Expand All @@ -210,20 +213,20 @@ private module CryptographyModel {

CryptographyGenericCipherOperation() {
this =
cipherInstance(algorithmName, modeName)
symmetricCipherInstance(algorithmName, modeName)
.getMember(["decryptor", "encryptor"])
.getReturn()
.getMember(["update", "update_into"])
.getACall()
}

override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(algorithmName)
override string getAlgorithmRaw() {
result = algorithmName
}

override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }

override Cryptography::BlockMode getBlockMode() { result = modeName }
override string getBlockModeRaw() { result = modeName }
}
}

Expand Down Expand Up @@ -269,13 +272,13 @@ private module CryptographyModel {
this = hashInstance(algorithmName).getMember("update").getACall()
}

override Cryptography::CryptographicAlgorithm getAlgorithm() {
result.matchesName(algorithmName)
override string getAlgorithmRaw() {
result = algorithmName
}

override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }

override Cryptography::BlockMode getBlockMode() { none() }
override string getBlockModeRaw() { none() }
}
}
}
Loading