Skip to content

Commit 49335e5

Browse files
authored
Merge pull request #17126 from geoffw0/swiftcleartext
Swift: Improve documentation and examples that use encryption
2 parents 927c65e + 5a5fdb2 commit 49335e5

12 files changed

+167
-128
lines changed

swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.qhelp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</recommendation>
1313
<example>
1414

15-
<p>The following example shows three cases of storing information using the Core Data library. In the 'BAD' case, the data that is stored is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption.</p>
15+
<p>The following example shows three cases of storing information using the Core Data library. In the 'BAD' case, the data that is stored is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption. When encryption is used, take care to select a secure modern encryption algorithm, and put suitable key management practices into place.</p>
1616

1717
<sample src="CleartextStorageDatabase.swift" />
1818

@@ -23,6 +23,10 @@
2323
OWASP Top 10:2021:
2424
<a href="https://owasp.org/Top10/A02_2021-Cryptographic_Failures/">A02:2021 � Cryptographic Failures</a>.
2525
</li>
26+
<li>
27+
OWASP:
28+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html">Key Management Cheat Sheet</a>.
29+
</li>
2630

2731
</references>
2832
</qhelp>
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import CryptoKit
12

2-
func storeMyData(databaseObject : NSManagedObject, faveSong : String, creditCardNo : String) {
3+
private func encrypt(_ text: String, _ encryptionKey: SymmetricKey) -> String {
4+
let sealedBox = try! AES.GCM.seal(Data(text.utf8), using: encryptionKey)
5+
return sealedBox.combined!.base64EncodedString()
6+
}
7+
8+
func storeMyData(databaseObject : NSManagedObject, faveSong : String, creditCardNo : String, encryptionKey: SymmetricKey) {
39
// ...
410

511
// GOOD: not sensitive information
@@ -9,7 +15,7 @@ func storeMyData(databaseObject : NSManagedObject, faveSong : String, creditCard
915
databaseObject.setValue(creditCardNo, forKey: "myCreditCardNo")
1016

1117
// GOOD: encrypted sensitive information saved
12-
databaseObject.setValue(encrypt(creditCardNo), forKey: "myCreditCardNo")
18+
databaseObject.setValue(encrypt(creditCardNo, encryptionKey), forKey: "myCreditCardNo")
1319

1420
// ...
1521
}

swift/ql/src/queries/Security/CWE-311/CleartextTransmission.qhelp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</recommendation>
1313
<example>
1414

15-
<p>The following example shows three cases of transmitting information. In the 'BAD' case, the data transmitted is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption.</p>
15+
<p>The following example shows three cases of transmitting information. In the 'BAD' case, the data transmitted is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption. When encryption is used, take care to select a secure modern encryption algorithm, and put suitable key management practices into place.</p>
1616

1717
<sample src="CleartextTransmission.swift" />
1818

@@ -23,6 +23,10 @@
2323
OWASP Top 10:2021:
2424
<a href="https://owasp.org/Top10/A02_2021-Cryptographic_Failures/">A02:2021 � Cryptographic Failures</a>.
2525
</li>
26+
<li>
27+
OWASP:
28+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html">Key Management Cheat Sheet</a>.
29+
</li>
2630

2731
</references>
2832
</qhelp>
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import CryptoKit
12

2-
func transmitMyData(connection : NWConnection, faveSong : String, creditCardNo : String) {
3+
private func encrypt(_ text: String, _ encryptionKey: SymmetricKey) -> String {
4+
let sealedBox = try! AES.GCM.seal(Data(text.utf8), using: encryptionKey)
5+
return sealedBox.combined!.base64EncodedString()
6+
}
7+
8+
func transmitMyData(connection : NWConnection, faveSong : String, creditCardNo : String, encryptionKey: SymmetricKey) {
39
// ...
410

511
// GOOD: not sensitive information
@@ -9,7 +15,7 @@ func transmitMyData(connection : NWConnection, faveSong : String, creditCardNo :
915
connection.send(content: creditCardNo, completion: .idempotent)
1016

1117
// GOOD: encrypted sensitive information saved
12-
connection.send(content: encrypt(creditCardNo), completion: .idempotent)
18+
connection.send(content: encrypt(creditCardNo, encryptionKey), completion: .idempotent)
1319

1420
// ...
1521
}

swift/ql/src/queries/Security/CWE-312/CleartextStoragePreferences.qhelp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</recommendation>
1313
<example>
1414

15-
<p>The following example shows three cases of storing information using UserDefaults. In the 'BAD' case, the data that is stored is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption.</p>
15+
<p>The following example shows three cases of storing information using UserDefaults. In the 'BAD' case, the data that is stored is sensitive (a credit card number) and is not encrypted. In the 'GOOD' cases, the data is either not sensitive, or is protected with encryption. When encryption is used, take care to select a secure modern encryption algorithm, and put suitable key management practices into place.</p>
1616

1717
<sample src="CleartextStoragePreferences.swift" />
1818

@@ -26,6 +26,10 @@
2626
<li>
2727
Apple Developer Documentation: <a href="https://developer.apple.com/documentation/foundation/userdefaults">UserDefaults</a>, <a href="https://developer.apple.com/documentation/foundation/nsubiquitouskeyvaluestore">NSUbiquitousKeyValueStore</a>
2828
</li>
29+
<li>
30+
OWASP:
31+
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Key_Management_Cheat_Sheet.html">Key Management Cheat Sheet</a>.
32+
</li>
2933

3034
</references>
3135
</qhelp>
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import CryptoKit
12

2-
func storeMyData(faveSong : String, creditCardNo : String) {
3+
private func encrypt(_ text: String, _ encryptionKey: SymmetricKey) -> String {
4+
let sealedBox = try! AES.GCM.seal(Data(text.utf8), using: encryptionKey)
5+
return sealedBox.combined!.base64EncodedString()
6+
}
7+
8+
func storeMyData(faveSong : String, creditCardNo : String, encryptionKey: SymmetricKey) {
39
// ...
410

511
// GOOD: not sensitive information
@@ -9,7 +15,7 @@ func storeMyData(faveSong : String, creditCardNo : String) {
915
UserDefaults.standard.set(creditCardNo, forKey: "myCreditCardNo")
1016

1117
// GOOD: encrypted sensitive information saved
12-
UserDefaults.standard.set(encrypt(creditCardNo), forKey: "myCreditCardNo")
18+
UserDefaults.standard.set(encrypt(creditCardNo, encryptionKey), forKey: "myCreditCardNo")
1319

1420
// ...
1521
}

swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ func encrypt(padding : Padding) {
66
let key: Array<UInt8> = [0x2a, 0x3a, 0x80, 0x05]
77
let keyString = "this is a constant string"
88
let ivString = getRandomIV()
9-
_ = try AES(key: key, blockMode: CBC(), padding: padding)
9+
_ = try AES(key: key, blockMode: CBC(AES.randomIV(AES.blockSize)), padding: padding)
1010
_ = try AES(key: keyString, iv: ivString)
11-
_ = try Blowfish(key: key, blockMode: CBC(), padding: padding)
11+
_ = try Blowfish(key: key, blockMode: CBC(Blowfish.randomIV(Blowfish.blockSize)), padding: padding)
1212
_ = try Blowfish(key: keyString, iv: ivString)
1313

1414

@@ -18,9 +18,9 @@ func encrypt(padding : Padding) {
1818
if status == errSecSuccess {
1919
let keyString = String(cString: key)
2020
let ivString = getRandomIV()
21-
_ = try AES(key: key, blockMode: CBC(), padding: padding)
21+
_ = try AES(key: key, blockMode: CBC(AES.randomIV(AES.blockSize)), padding: padding)
2222
_ = try AES(key: keyString, iv: ivString)
23-
_ = try Blowfish(key: key, blockMode: CBC(), padding: padding)
23+
_ = try Blowfish(key: key, blockMode: CBC(Blowfish.randomIV(Blowfish.blockSize)), padding: padding)
2424
_ = try Blowfish(key: keyString, iv: ivString)
2525
}
2626

swift/ql/src/queries/Security/CWE-327/ECBEncryption.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ func encrypt(key : Key, padding : Padding) {
99
_ = try Blowfish(key: key, blockMode: blockMode, padding: padding)
1010

1111
// GOOD: ECB is not used for block mode
12-
let blockMode = CBC()
13-
_ = try AES(key: key, blockMode: blockMode, padding: padding)
14-
_ = try AES(key: key, blockMode: blockMode)
15-
_ = try Blowfish(key: key, blockMode: blockMode, padding: padding)
12+
let aesBlockMode = CBC(iv: AES.randomIV(AES.blockSize))
13+
let blowfishBlockMode = CBC(iv: Blowfish.randomIV(Blowfish.blockSize))
14+
_ = try AES(key: key, blockMode: aesBlockMode, padding: padding)
15+
_ = try AES(key: key, blockMode: aesBlockMode)
16+
_ = try Blowfish(key: key, blockMode: blowfishBlockMode, padding: padding)
1617

1718
// ...
1819
}

0 commit comments

Comments
 (0)