From b323637f7a7497ad743f0d84b860991439edbb3a Mon Sep 17 00:00:00 2001 From: gmbnt Date: Wed, 1 Apr 2020 11:33:38 +1100 Subject: [PATCH] Fix missing IV & improve error handling --- .../OnionRequestAPI+Encryption.swift | 4 ++-- .../API/Onion Requests/OnionRequestAPI.swift | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift index 34dbbbc10..736854253 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift @@ -20,14 +20,14 @@ extension OnionRequestAPI { /// - Note: Sync. Don't call from the main thread. private static func encrypt(_ plaintext: Data, usingAESGCMWithSymmetricKey symmetricKey: Data) throws -> Data { - guard !Thread.isMainThread else { preconditionFailure("It's illegal to call encryptUsingAESGCM(symmetricKey:plainText:) from the main thread.") } + guard !Thread.isMainThread else { preconditionFailure("It's illegal to call encrypt(_:usingAESGCMWithSymmetricKey:) from the main thread.") } let ivSize: UInt = 12 let iv = try getRandomData(ofSize: ivSize) let gcmTagLength: UInt = 128 let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagLength), mode: .combined) let aes = try AES(key: symmetricKey.bytes, blockMode: gcm, padding: .noPadding) let ciphertext = try aes.encrypt(plaintext.bytes) - return Data(bytes: ciphertext) + return iv + Data(bytes: ciphertext) } /// - Note: Sync. Don't call from the main thread. diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift index 5621ef3ec..6305cb484 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift @@ -18,7 +18,7 @@ internal enum OnionRequestAPI { private static let pathSize: UInt = 3 private static let timeout: TimeInterval = 20 - private static var guardSnodeCount: UInt { return pathCount } + private static var guardSnodeCount: UInt { return pathCount } // One per path // MARK: HTTP Verb private enum HTTPVerb : String { @@ -94,8 +94,14 @@ internal enum OnionRequestAPI { } let statusCode = UInt(response.statusCode) guard 200...299 ~= statusCode else { - print("[Loki] [Onion Request API] \(verb.rawValue) request to \(url) failed with status code: \(statusCode).") - let json = try? JSONSerialization.jsonObject(with: data, options: []) as? JSON + var json: JSON? = nil + if let j = try? JSONSerialization.jsonObject(with: data, options: []) as? JSON { + json = j + } else if let message = String(data: data, encoding: .utf8) { + json = [ "message" : message ] + } + let jsonDescription = json?.prettifiedDescription ?? "no debugging info provided" + print("[Loki] [Onion Request API] \(verb.rawValue) request to \(url) failed with status code: \(statusCode) (\(jsonDescription).") return seal.reject(Error.httpRequestFailed(statusCode: statusCode, json: json)) } do { @@ -121,7 +127,7 @@ internal enum OnionRequestAPI { execute(.get, url, timeout: timeout).done(on: queue) { rawResponse in guard let json = rawResponse as? JSON, let version = json["version"] as? String else { return seal.reject(Error.missingSnodeVersion) } // TODO: Caching - if version >= "2.0.3" { + if version >= "2.0.0" { seal.fulfill(()) } else { print("[Loki] [Onion Request API] Unsupported snode version: \(version).") @@ -210,11 +216,12 @@ internal enum OnionRequestAPI { /// Builds an onion around `payload` and returns the result. private static func buildOnion(around payload: Data, targetedAt snode: LokiAPITarget) -> Promise { var guardSnode: LokiAPITarget! + var encryptionResult: EncryptionResult! return getPath().then(on: workQueue) { path -> Promise in guardSnode = path.first! return encrypt(payload, forTargetSnode: snode).then(on: workQueue) { r -> Promise in + encryptionResult = r var path = path - var encryptionResult = r var rhs = snode func addLayer() -> Promise { if path.isEmpty { @@ -230,7 +237,7 @@ internal enum OnionRequestAPI { } return addLayer() } - }.map(on: workQueue) { (guardSnode: guardSnode, encryptionResult: $0) } + }.map(on: workQueue) { _ in (guardSnode: guardSnode, encryptionResult: encryptionResult) } } // MARK: Internal API