33 */
44
55import go
6+ import semmle.go.Concepts:: Cryptography
7+ private import codeql.concepts.internal.CryptoAlgorithmNames
68
79/**
8- * Names of cryptographic algorithms, separated into strong and weak variants.
9- *
10- * The names are normalized: upper-case, no spaces, dashes or underscores.
11- *
12- * The names are inspired by the names used in real world crypto libraries.
13- *
14- * The classification into strong and weak are based on OWASP and Wikipedia (2020).
15- *
16- * Sources (more links in qhelp file):
17- * https://en.wikipedia.org/wiki/Strong_cryptography#Cryptographically_strong_algorithms
18- * https://en.wikipedia.org/wiki/Strong_cryptography#Examples
19- * https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html
20- */
21- private module AlgorithmNames {
22- predicate isStrongHashingAlgorithm ( string name ) {
23- name =
24- [
25- "DSA" , "ED25519" , "SHA256" , "SHA384" , "SHA512" , "SHA3" , "ES256" , "ECDSA256" , "ES384" ,
26- "ECDSA384" , "ES512" , "ECDSA512" , "SHA2" , "SHA224"
27- ]
28- }
29-
30- predicate isWeakHashingAlgorithm ( string name ) {
31- name =
32- [
33- "HAVEL128" , "MD2" , "SHA1" , "MD4" , "MD5" , "PANAMA" , "RIPEMD" , "RIPEMD128" , "RIPEMD256" ,
34- "RIPEMD320" , "SHA0"
35- ]
36- }
37-
38- predicate isStrongEncryptionAlgorithm ( string name ) {
39- name = [ "AES" , "AES128" , "AES192" , "AES256" , "AES512" , "RSA" , "RABBIT" , "BLOWFISH" ]
40- }
41-
42- predicate isWeakEncryptionAlgorithm ( string name ) {
43- name =
44- [
45- "DES" , "3DES" , "ARC5" , "RC5" , "TRIPLEDES" , "TDEA" , "TRIPLEDEA" , "ARC2" , "RC2" , "ARC4" ,
46- "RC4" , "ARCFOUR"
47- ]
48- }
49-
50- predicate isStrongPasswordHashingAlgorithm ( string name ) {
51- name = [ "ARGON2" , "PBKDF2" , "BCRYPT" , "SCRYPT" ]
52- }
53-
54- predicate isWeakPasswordHashingAlgorithm ( string name ) { none ( ) }
55- }
56-
57- private import AlgorithmNames
58-
59- /**
60- * A cryptographic algorithm.
61- */
62- private newtype TCryptographicAlgorithm =
63- MkHashingAlgorithm ( string name , boolean isWeak ) {
64- isStrongHashingAlgorithm ( name ) and isWeak = false
65- or
66- isWeakHashingAlgorithm ( name ) and isWeak = true
67- } or
68- MkEncryptionAlgorithm ( string name , boolean isWeak ) {
69- isStrongEncryptionAlgorithm ( name ) and isWeak = false
70- or
71- isWeakEncryptionAlgorithm ( name ) and isWeak = true
72- } or
73- MkPasswordHashingAlgorithm ( string name , boolean isWeak ) {
74- isStrongPasswordHashingAlgorithm ( name ) and isWeak = false
75- or
76- isWeakPasswordHashingAlgorithm ( name ) and isWeak = true
77- }
78-
79- /**
80- * A cryptographic algorithm.
81- */
82- abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
83- /** Gets a textual representation of this element. */
84- string toString ( ) { result = this .getName ( ) }
85-
86- /**
87- * Gets the name of this algorithm.
88- */
89- abstract string getName ( ) ;
90-
91- /**
92- * Holds if the name of this algorithm matches `name` modulo case,
93- * white space, dashes and underscores.
94- */
95- bindingset [ name]
96- predicate matchesName ( string name ) {
97- exists ( name .regexpReplaceAll ( "[-_]" , "" ) .regexpFind ( "(?i)\\Q" + this .getName ( ) + "\\E" , _, _) )
98- }
99-
100- /**
101- * Holds if this algorithm is weak.
102- */
103- abstract predicate isWeak ( ) ;
104- }
105-
106- /**
107- * A hashing algorithm such as `MD5` or `SHA512`.
108- */
109- class HashingAlgorithm extends MkHashingAlgorithm , CryptographicAlgorithm {
110- string name ;
111- boolean isWeak ;
112-
113- HashingAlgorithm ( ) { this = MkHashingAlgorithm ( name , isWeak ) }
114-
115- override string getName ( ) { result = name }
116-
117- override predicate isWeak ( ) { isWeak = true }
118- }
119-
120- /**
121- * An encryption algorithm such as `DES` or `AES512`.
122- */
123- class EncryptionAlgorithm extends MkEncryptionAlgorithm , CryptographicAlgorithm {
124- string name ;
125- boolean isWeak ;
126-
127- EncryptionAlgorithm ( ) { this = MkEncryptionAlgorithm ( name , isWeak ) }
128-
129- override string getName ( ) { result = name }
130-
131- override predicate isWeak ( ) { isWeak = true }
132- }
133-
134- /**
135- * A password hashing algorithm such as `PBKDF2` or `SCRYPT`.
136- */
137- class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm , CryptographicAlgorithm {
138- string name ;
139- boolean isWeak ;
140-
141- PasswordHashingAlgorithm ( ) { this = MkPasswordHashingAlgorithm ( name , isWeak ) }
142-
143- override string getName ( ) { result = name }
144-
145- override predicate isWeak ( ) { isWeak = true }
146- }
147-
148- /**
149- * An application of a cryptographic algorithm.
10+ * A cryptographic operation from the `crypto/md5` package.
15011 */
151- abstract class CryptographicOperation extends DataFlow:: Node {
152- /**
153- * Gets the input the algorithm is used on, e.g. the plain text input to be encrypted.
154- */
155- abstract Expr getInput ( ) ;
12+ private module CryptoMd5 {
13+ private class Md5 extends CryptographicOperation:: Range instanceof DataFlow:: CallNode {
14+ Md5 ( ) { this .getTarget ( ) .hasQualifiedName ( "crypto/md5" , [ "New" , "Sum" ] ) }
15615
157- /**
158- * Gets the applied algorithm.
159- */
160- abstract CryptographicAlgorithm getAlgorithm ( ) ;
161- }
16+ override DataFlow:: Node getInitialization ( ) { result = this }
16217
163- /**
164- * A cryptographic operation from the `crypto/md5` package.
165- */
166- class Md5 extends CryptographicOperation , DataFlow:: CallNode {
167- Md5 ( ) { this .getTarget ( ) .hasQualifiedName ( "crypto/md5" , [ "New" , "Sum" ] ) }
18+ override CryptographicAlgorithm getAlgorithm ( ) { result .matchesName ( "MD5" ) }
16819
169- override Expr getInput ( ) { result = this .getArgument ( 0 ) . asExpr ( ) }
20+ override DataFlow :: Node getAnInput ( ) { result = super .getArgument ( 0 ) }
17021
171- override CryptographicAlgorithm getAlgorithm ( ) {
172- result . matchesName ( this . getTarget ( ) . getPackage ( ) . getName ( ) )
22+ // not relevant for md5
23+ override BlockMode getBlockMode ( ) { none ( ) }
17324 }
17425}
17526
17627/**
17728 * A cryptographic operation from the `crypto/sha1` package.
17829 */
179- class Sha1 extends CryptographicOperation , DataFlow:: CallNode {
30+ class Sha1 extends CryptographicOperation:: Range instanceof DataFlow:: CallNode {
18031 Sha1 ( ) { this .getTarget ( ) .hasQualifiedName ( "crypto/sha1" , [ "New" , "Sum" ] ) }
18132
18233 override Expr getInput ( ) { result = this .getArgument ( 0 ) .asExpr ( ) }
@@ -189,7 +40,7 @@ class Sha1 extends CryptographicOperation, DataFlow::CallNode {
18940/**
19041 * A cryptographic operation from the `crypto/des` package.
19142 */
192- class Des extends CryptographicOperation , DataFlow:: CallNode {
43+ class Des extends CryptographicOperation:: Range instanceof DataFlow:: CallNode {
19344 Des ( ) { this .getTarget ( ) .hasQualifiedName ( "crypto/des" , [ "NewCipher" , "NewTripleDESCipher" ] ) }
19445
19546 override Expr getInput ( ) { result = this .getArgument ( 0 ) .asExpr ( ) }
@@ -202,7 +53,7 @@ class Des extends CryptographicOperation, DataFlow::CallNode {
20253/**
20354 * A cryptographic operation from the `crypto/rc4` package.
20455 */
205- class Rc4 extends CryptographicOperation , DataFlow:: CallNode {
56+ class Rc4 extends CryptographicOperation:: Range instanceof DataFlow:: CallNode {
20657 Rc4 ( ) { this .getTarget ( ) .hasQualifiedName ( "crypto/rc4" , "NewCipher" ) }
20758
20859 override Expr getInput ( ) { result = this .getArgument ( 0 ) .asExpr ( ) }
0 commit comments