Skip to content

Commit 48439bc

Browse files
authored
Merge pull request #11905 from geoffw0/rncrypt
Swift: Add RNCryptor sinks to swift/constant-password
2 parents c8bcfb7 + 71c1ca5 commit 48439bc

File tree

3 files changed

+180
-1
lines changed

3 files changed

+180
-1
lines changed

swift/ql/src/queries/Security/CWE-259/ConstantPassword.ql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ class ConstantPasswordSink extends Expr {
3838
call.getStaticTarget() = f and
3939
call.getArgumentWithLabel("password").getExpr() = this
4040
)
41+
or
42+
// RNCryptor (labelled arguments)
43+
exists(ClassOrStructDecl c, MethodDecl f, CallExpr call |
44+
c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and
45+
c.getAMember() = f and
46+
call.getStaticTarget() = f and
47+
call.getArgumentWithLabel(["password", "withPassword", "forPassword"]).getExpr() = this
48+
)
49+
or
50+
// RNCryptor (unlabelled arguments)
51+
exists(MethodDecl f, CallExpr call |
52+
f.hasQualifiedName("RNCryptor", "keyForPassword(_:salt:settings:)") and
53+
call.getStaticTarget() = f and
54+
call.getArgument(0).getExpr() = this
55+
)
4156
}
4257
}
4358

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,72 @@
11
edges
2+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:77:89:77:89 | myConstPassword |
3+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:78:56:78:56 | myConstPassword |
4+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:80:89:80:89 | myMaybePassword |
5+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:81:56:81:56 | myMaybePassword |
6+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:91:39:91:39 | myConstPassword |
7+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:92:37:92:37 | myConstPassword |
8+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:93:39:93:39 | myConstPassword |
9+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:94:37:94:37 | myConstPassword |
10+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:96:68:96:68 | myConstPassword |
11+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:97:68:97:68 | myConstPassword |
12+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:98:68:98:68 | myConstPassword |
13+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:100:89:100:89 | myConstPassword |
14+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:101:97:101:97 | myConstPassword |
15+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:102:89:102:89 | myConstPassword |
16+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:103:97:103:97 | myConstPassword |
17+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:105:32:105:32 | myConstPassword |
18+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:107:61:107:61 | myConstPassword |
19+
| rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:108:97:108:97 | myConstPassword |
220
| test.swift:43:39:43:134 | [...] : | test.swift:51:30:51:30 | constantPassword |
321
| test.swift:43:39:43:134 | [...] : | test.swift:56:40:56:40 | constantPassword |
422
| test.swift:43:39:43:134 | [...] : | test.swift:62:40:62:40 | constantPassword |
523
| test.swift:43:39:43:134 | [...] : | test.swift:67:34:67:34 | constantPassword |
624
nodes
25+
| rncryptor.swift:69:24:69:24 | abc123 : | semmle.label | abc123 : |
26+
| rncryptor.swift:77:89:77:89 | myConstPassword | semmle.label | myConstPassword |
27+
| rncryptor.swift:78:56:78:56 | myConstPassword | semmle.label | myConstPassword |
28+
| rncryptor.swift:80:89:80:89 | myMaybePassword | semmle.label | myMaybePassword |
29+
| rncryptor.swift:81:56:81:56 | myMaybePassword | semmle.label | myMaybePassword |
30+
| rncryptor.swift:91:39:91:39 | myConstPassword | semmle.label | myConstPassword |
31+
| rncryptor.swift:92:37:92:37 | myConstPassword | semmle.label | myConstPassword |
32+
| rncryptor.swift:93:39:93:39 | myConstPassword | semmle.label | myConstPassword |
33+
| rncryptor.swift:94:37:94:37 | myConstPassword | semmle.label | myConstPassword |
34+
| rncryptor.swift:96:68:96:68 | myConstPassword | semmle.label | myConstPassword |
35+
| rncryptor.swift:97:68:97:68 | myConstPassword | semmle.label | myConstPassword |
36+
| rncryptor.swift:98:68:98:68 | myConstPassword | semmle.label | myConstPassword |
37+
| rncryptor.swift:100:89:100:89 | myConstPassword | semmle.label | myConstPassword |
38+
| rncryptor.swift:101:97:101:97 | myConstPassword | semmle.label | myConstPassword |
39+
| rncryptor.swift:102:89:102:89 | myConstPassword | semmle.label | myConstPassword |
40+
| rncryptor.swift:103:97:103:97 | myConstPassword | semmle.label | myConstPassword |
41+
| rncryptor.swift:105:32:105:32 | myConstPassword | semmle.label | myConstPassword |
42+
| rncryptor.swift:107:61:107:61 | myConstPassword | semmle.label | myConstPassword |
43+
| rncryptor.swift:108:97:108:97 | myConstPassword | semmle.label | myConstPassword |
744
| test.swift:43:39:43:134 | [...] : | semmle.label | [...] : |
845
| test.swift:51:30:51:30 | constantPassword | semmle.label | constantPassword |
946
| test.swift:56:40:56:40 | constantPassword | semmle.label | constantPassword |
1047
| test.swift:62:40:62:40 | constantPassword | semmle.label | constantPassword |
1148
| test.swift:67:34:67:34 | constantPassword | semmle.label | constantPassword |
1249
subpaths
1350
#select
51+
| rncryptor.swift:77:89:77:89 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:77:89:77:89 | myConstPassword | The value 'abc123' is used as a constant password. |
52+
| rncryptor.swift:78:56:78:56 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:78:56:78:56 | myConstPassword | The value 'abc123' is used as a constant password. |
53+
| rncryptor.swift:80:89:80:89 | myMaybePassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:80:89:80:89 | myMaybePassword | The value 'abc123' is used as a constant password. |
54+
| rncryptor.swift:81:56:81:56 | myMaybePassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:81:56:81:56 | myMaybePassword | The value 'abc123' is used as a constant password. |
55+
| rncryptor.swift:91:39:91:39 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:91:39:91:39 | myConstPassword | The value 'abc123' is used as a constant password. |
56+
| rncryptor.swift:92:37:92:37 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:92:37:92:37 | myConstPassword | The value 'abc123' is used as a constant password. |
57+
| rncryptor.swift:93:39:93:39 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:93:39:93:39 | myConstPassword | The value 'abc123' is used as a constant password. |
58+
| rncryptor.swift:94:37:94:37 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:94:37:94:37 | myConstPassword | The value 'abc123' is used as a constant password. |
59+
| rncryptor.swift:96:68:96:68 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:96:68:96:68 | myConstPassword | The value 'abc123' is used as a constant password. |
60+
| rncryptor.swift:97:68:97:68 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:97:68:97:68 | myConstPassword | The value 'abc123' is used as a constant password. |
61+
| rncryptor.swift:98:68:98:68 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:98:68:98:68 | myConstPassword | The value 'abc123' is used as a constant password. |
62+
| rncryptor.swift:100:89:100:89 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:100:89:100:89 | myConstPassword | The value 'abc123' is used as a constant password. |
63+
| rncryptor.swift:101:97:101:97 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:101:97:101:97 | myConstPassword | The value 'abc123' is used as a constant password. |
64+
| rncryptor.swift:102:89:102:89 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:102:89:102:89 | myConstPassword | The value 'abc123' is used as a constant password. |
65+
| rncryptor.swift:103:97:103:97 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:103:97:103:97 | myConstPassword | The value 'abc123' is used as a constant password. |
66+
| rncryptor.swift:105:32:105:32 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:105:32:105:32 | myConstPassword | The value 'abc123' is used as a constant password. |
67+
| rncryptor.swift:107:61:107:61 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:107:61:107:61 | myConstPassword | The value 'abc123' is used as a constant password. |
68+
| rncryptor.swift:108:97:108:97 | myConstPassword | rncryptor.swift:69:24:69:24 | abc123 : | rncryptor.swift:108:97:108:97 | myConstPassword | The value 'abc123' is used as a constant password. |
1469
| test.swift:51:30:51:30 | constantPassword | test.swift:43:39:43:134 | [...] : | test.swift:51:30:51:30 | constantPassword | The value '[...]' is used as a constant password. |
1570
| test.swift:56:40:56:40 | constantPassword | test.swift:43:39:43:134 | [...] : | test.swift:56:40:56:40 | constantPassword | The value '[...]' is used as a constant password. |
1671
| test.swift:62:40:62:40 | constantPassword | test.swift:43:39:43:134 | [...] : | test.swift:62:40:62:40 | constantPassword | The value '[...]' is used as a constant password. |
17-
| test.swift:67:34:67:34 | constantPassword | test.swift:43:39:43:134 | [...] : | test.swift:67:34:67:34 | constantPassword | The value '[...]' is used as a constant password. |
72+
| test.swift:67:34:67:34 | constantPassword | test.swift:43:39:43:134 | [...] : | test.swift:67:34:67:34 | constantPassword | The value '[...]' is used as a constant password. |
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
// --- stubs ---
3+
4+
class Data {
5+
init<S>(_ elements: S) {}
6+
}
7+
8+
class NSObject
9+
{
10+
}
11+
12+
struct _RNCryptorSettings {
13+
// ...
14+
}
15+
typealias RNCryptorSettings = _RNCryptorSettings
16+
17+
let kRNCryptorAES256Settings = RNCryptorSettings()
18+
19+
struct _RNCryptorKeyDerivationSettings {
20+
// ...
21+
}
22+
typealias RNCryptorKeyDerivationSettings = _RNCryptorKeyDerivationSettings
23+
24+
typealias RNCryptorHandler = () -> Void // simplified
25+
26+
class RNCryptor : NSObject
27+
{
28+
func key(forPassword password: String?, salt: Data?, settings keySettings: RNCryptorKeyDerivationSettings) -> Data? { return nil }
29+
func keyForPassword(_ password: String?, salt: Data?, settings keySettings: RNCryptorKeyDerivationSettings) -> Data? { return nil }
30+
}
31+
32+
class RNEncryptor : RNCryptor
33+
{
34+
override init() {}
35+
36+
init(settings: RNCryptorSettings, password: String?, handler: RNCryptorHandler?) {}
37+
init(settings: RNCryptorSettings, password: String, iv anIV: Data?, encryptionSalt anEncryptionSalt: Data?, hmacSalt anHMACSalt: Data?, handler: RNCryptorHandler?) {}
38+
init(settings: RNCryptorSettings, password: String, IV anIV: Data?, encryptionSalt anEncryptionSalt: Data?, HMACSalt anHMACSalt: Data?, handler: RNCryptorHandler?) {}
39+
40+
func encryptData(_ data: Data?, with settings: RNCryptorSettings, password: String?) throws -> Data { return Data(0) }
41+
func encryptData(_ data: Data?, withSettings settings: RNCryptorSettings, password: String?) throws -> Data { return Data(0) }
42+
func encryptData(_ data: Data?, with settings: RNCryptorSettings, password: String?, iv anIV: Data?, encryptionSalt anEncryptionSalt: Data?, hmacSalt anHMACSalt: Data?) throws -> Data { return Data(0) }
43+
func encryptData(_ data: Data?, withSettings settings: RNCryptorSettings, password: String?, IV anIV: Data?, encryptionSalt anEncryptionSalt: Data?, HMACSalt anHMACSalt: Data?) throws -> Data { return Data(0) }
44+
}
45+
46+
class RNDecryptor : RNCryptor
47+
{
48+
override init() {}
49+
50+
init(password: String?, handler: RNCryptorHandler?) {}
51+
52+
func decryptData(_ data: Data?, withPassword password: String?) throws -> Data { return Data(0) }
53+
func decryptData(_ theCipherText: Data?, withSettings settings: RNCryptorSettings, password aPassword: String?) throws -> Data { return Data(0) }
54+
}
55+
56+
// --- tests ---
57+
58+
func getARandomPassword() -> String {
59+
let charset = "abcdefghijklmnopqrstuvwxyz1234567890"
60+
return String("............".map{_ in charset.randomElement()!})
61+
}
62+
63+
func test(cond: Bool) {
64+
let myEncryptor = RNEncryptor()
65+
let myDecryptor = RNDecryptor()
66+
let myData = Data(0)
67+
68+
let myRandomPassword = getARandomPassword()
69+
let myConstPassword = "abc123"
70+
let myMaybePassword = cond ? myRandomPassword : myConstPassword
71+
72+
// reasonable usage
73+
74+
let a = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myRandomPassword) // GOOD
75+
let _ = try? myDecryptor.decryptData(a, withPassword: myRandomPassword) // GOOD
76+
77+
let b = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // BAD
78+
let _ = try? myDecryptor.decryptData(b, withPassword: myConstPassword) // BAD
79+
80+
let c = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myMaybePassword) // BAD
81+
let _ = try? myDecryptor.decryptData(c, withPassword: myMaybePassword) // BAD
82+
83+
// all methods
84+
85+
let myKeyDerivationSettings = RNCryptorKeyDerivationSettings()
86+
let myHandler = {}
87+
let myIV = Data(0)
88+
let mySalt = Data(0)
89+
let mySalt2 = Data(0)
90+
91+
let _ = myEncryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
92+
let _ = myEncryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
93+
let _ = myDecryptor.key(forPassword: myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
94+
let _ = myDecryptor.keyForPassword(myConstPassword, salt: mySalt, settings: myKeyDerivationSettings) // BAD
95+
96+
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, handler: myHandler) // BAD
97+
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2, handler: myHandler) // BAD
98+
let _ = RNEncryptor(settings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2, handler: myHandler) // BAD
99+
100+
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword) // BAD
101+
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // BAD
102+
let _ = try? myEncryptor.encryptData(myData, with: kRNCryptorAES256Settings, password: myConstPassword, iv: myIV, encryptionSalt: mySalt, hmacSalt: mySalt2) // BAD
103+
let _ = try? myEncryptor.encryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword, IV: myIV, encryptionSalt: mySalt, HMACSalt: mySalt2) // BAD
104+
105+
let _ = RNDecryptor(password: myConstPassword, handler: myHandler) // BAD
106+
107+
let _ = try? myDecryptor.decryptData(myData, withPassword: myConstPassword) // BAD
108+
let _ = try? myDecryptor.decryptData(myData, withSettings: kRNCryptorAES256Settings, password: myConstPassword) // BAD
109+
}

0 commit comments

Comments
 (0)