Skip to content

Commit 8412b35

Browse files
committed
Fixed crash when encrypting/decrypting invalid filenames, see cryptomator/ios#167
1 parent 26b3861 commit 8412b35

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

Sources/CryptomatorCryptoLib/AesSiv.swift

+8-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ class AesSiv {
1919

2020
- Parameter aesKey: SIV mode requires two separate keys. You can use one long key, which is splitted in half. See [RFC 5297 Section 2.2](https://tools.ietf.org/html/rfc5297#section-2.2).
2121
- Parameter macKey: SIV mode requires two separate keys. You can use one long key, which is splitted in half. See [RFC 5297 Section 2.2](https://tools.ietf.org/html/rfc5297#section-2.2).
22-
- Parameter plaintext: Your plaintext, which shall be encrypted.
22+
- Parameter plaintext: Your plaintext, which shall be encrypted. It must not be longer than 2^32 - 16 bytes.
2323
- Parameter ad: Associated data, which gets authenticated but not encrypted.
2424
- Returns: IV + Ciphertext as a concatenated byte array.
2525
*/
2626
static func encrypt(aesKey: [UInt8], macKey: [UInt8], plaintext: [UInt8], ad: [UInt8]...) throws -> [UInt8] {
27-
assert(plaintext.count <= UInt32.max - 16, "plaintext must not be longer than 2^32 - 16 bytes")
27+
guard plaintext.count <= UInt32.max - 16 else {
28+
throw CryptoError.invalidParameter("plaintext must not be longer than 2^32 - 16 bytes")
29+
}
2830
let iv = try s2v(macKey: macKey, plaintext: plaintext, ad: ad)
2931
let ciphertext = try ctr(aesKey: aesKey, iv: iv, plaintext: plaintext)
3032
return iv + ciphertext
@@ -35,12 +37,14 @@ class AesSiv {
3537

3638
- Parameter aesKey: SIV mode requires two separate keys. You can use one long key, which is splitted in half. See [RFC 5297 Section 2.2](https://tools.ietf.org/html/rfc5297#section-2.2).
3739
- Parameter macKey: SIV mode requires two separate keys. You can use one long key, which is splitted in half. See [RFC 5297 Section 2.2](https://tools.ietf.org/html/rfc5297#section-2.2).
38-
- Parameter ciphertext: Your ciphertext, which shall be decrypted.
40+
- Parameter ciphertext: Your ciphertext, which shall be decrypted. It must be at least 16 bytes.
3941
- Parameter ad: Associated data, which needs to be authenticated during decryption.
4042
- Returns: Plaintext byte array.
4143
*/
4244
static func decrypt(aesKey: [UInt8], macKey: [UInt8], ciphertext: [UInt8], ad: [UInt8]...) throws -> [UInt8] {
43-
assert(ciphertext.count >= 16, "ciphertext must be at least 16 bytes")
45+
guard ciphertext.count >= 16 else {
46+
throw CryptoError.invalidParameter("ciphertext must be at least 16 bytes")
47+
}
4448
let iv = Array(ciphertext[..<16])
4549
let actualCiphertext = Array(ciphertext[16...])
4650
let plaintext = try ctr(aesKey: aesKey, iv: iv, plaintext: actualCiphertext)

Tests/CryptomatorCryptoLibTests/CryptorTests.swift

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ class CryptorTests: XCTestCase {
4949
XCTAssertEqual(originalName, cleartextName)
5050
}
5151

52+
func testDecryptInvalidName() throws {
53+
let dirId = "foo".data(using: .utf8)!
54+
XCTAssertThrowsError(try cryptor.decryptFileName("****", dirId: dirId), "invalid ciphertext name encoding") { error in
55+
XCTAssertEqual(.invalidParameter("Can't base64url-decode ciphertext name: ****"), error as? CryptoError)
56+
}
57+
XCTAssertThrowsError(try cryptor.decryptFileName("test", dirId: dirId), "invalid ciphertext name count") { error in
58+
XCTAssertEqual(.invalidParameter("ciphertext must be at least 16 bytes"), error as? CryptoError)
59+
}
60+
}
61+
5262
func testCreateHeader() throws {
5363
let header = try cryptor.createHeader()
5464
XCTAssertEqual([UInt8](repeating: 0xF0, count: 16), header.nonce)

0 commit comments

Comments
 (0)