From 4603f90871313f27a6611a8babe39c905dcac3e4 Mon Sep 17 00:00:00 2001 From: Mikunj Varsani Date: Wed, 8 May 2019 10:15:05 +1000 Subject: [PATCH 1/7] Added FallBackSessionCipher decryption --- .../src/Loki/FallbackSessionCipher.swift | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/SignalServiceKit/src/Loki/FallbackSessionCipher.swift b/SignalServiceKit/src/Loki/FallbackSessionCipher.swift index 473874063..78d35553d 100644 --- a/SignalServiceKit/src/Loki/FallbackSessionCipher.swift +++ b/SignalServiceKit/src/Loki/FallbackSessionCipher.swift @@ -49,6 +49,15 @@ private extension String { return identityKeyStore.identityKeyPair() }() + // A symmetric key used for encryption and decryption + private lazy var symmetricKey: Data? = { + guard let myIdentityKeyPair = myIdentityKeyPair else { + return nil + } + + return try? Curve25519.generateSharedSecret(fromPublicKey: recipientPubKey, privateKey: myIdentityKeyPair.privateKey) + }() + /// Creare a FallBackSessionCipher. /// This is a very basic cipher and should only be used in special cases such as Friend Requests. /// @@ -67,22 +76,35 @@ private extension String { /// - Returns: The encypted message or nil if it failed @objc public func encrypt(message: Data) -> Data? { do { - let myIdentityKeyPair = self.myIdentityKeyPair! - let symmetricKey = try Curve25519.generateSharedSecret(fromPublicKey: recipientPubKey, privateKey: myIdentityKeyPair.privateKey) - return try diffieHellmanEncrypt(message: message, symmetricKey: symmetricKey) + let symmetricKey = self.symmetricKey! + return try diffieHellmanEncrypt(plainText: message, symmetricKey: symmetricKey) } catch { Logger.warn("FallBackSessionCipher: Failed to encrypt message") return nil } } + /// Decrypt a message + /// + /// - Parameter message: The message to decrypt + /// - Returns: The decrypted message or nil if it failed + @objc public func decrypt(message: Data) -> Data? { + do { + let symmetricKey = self.symmetricKey! + return try diffieHellmanDecrypt(cipherText: message, symmetricKey: symmetricKey) + } catch { + Logger.warn("FallBackSessionCipher: Failed to decrypt message") + return nil + } + } + // Encypt the message with the symmetric key and a 16 bit iv - private func diffieHellmanEncrypt(message: Data, symmetricKey: Data) throws -> Data { + private func diffieHellmanEncrypt(plainText: Data, symmetricKey: Data) throws -> Data { let iv = Randomness.generateRandomBytes(ivLength)! let ivBytes = [UInt8](iv) let symmetricKeyBytes = [UInt8](symmetricKey) - let messageBytes = [UInt8](message) + let messageBytes = [UInt8](plainText) let blockMode = CBC(iv: ivBytes) let aes = try AES(key: symmetricKeyBytes, blockMode: blockMode) @@ -90,4 +112,17 @@ private extension String { let ivAndCipher = ivBytes + cipherText return Data(bytes: ivAndCipher, count: ivAndCipher.count) } + + // Decrypt the message with the symmetric key + private func diffieHellmanDecrypt(cipherText: Data, symmetricKey: Data) throws -> Data { + let symmetricKeyBytes = [UInt8](symmetricKey) + let ivBytes = [UInt8](cipherText[.. Date: Wed, 8 May 2019 10:18:35 +1000 Subject: [PATCH 2/7] Updated generated proto files. --- SignalServiceKit/protobuf/SignalService.proto | 8 +- .../src/Protos/Generated/SSKProto.swift | 357 +++++++++++++++++- .../Protos/Generated/SignalService.pb.swift | 275 ++++++++++++++ 3 files changed, 633 insertions(+), 7 deletions(-) diff --git a/SignalServiceKit/protobuf/SignalService.proto b/SignalServiceKit/protobuf/SignalService.proto index 4f7ee3fa4..bc17df0dc 100644 --- a/SignalServiceKit/protobuf/SignalService.proto +++ b/SignalServiceKit/protobuf/SignalService.proto @@ -61,7 +61,7 @@ message Content { optional ReceiptMessage receiptMessage = 5; optional TypingMessage typingMessage = 6; optional PrekeyBundleMessage prekeyBundleMessage = 101; // Loki - optional LokiAddressMessage LokiAddressMessage = 102; // Loki + optional LokiAddressMessage lokiAddressMessage = 102; // Loki } message PrekeyBundleMessage { // Loki @@ -75,8 +75,10 @@ message PrekeyBundleMessage { // Loki } message LokiAddressMessage { // Loki - optional string p2pAddress = 1; - optional uint32 p2pPort = 2; + // The naming is a bit different from desktop because of swift auto generation + // It doesn't like p2p much :( + optional string ptpAddress = 1; + optional uint32 ptpPort = 2; } message CallMessage { diff --git a/SignalServiceKit/src/Protos/Generated/SSKProto.swift b/SignalServiceKit/src/Protos/Generated/SSKProto.swift index af4c2e52b..e01692b52 100644 --- a/SignalServiceKit/src/Protos/Generated/SSKProto.swift +++ b/SignalServiceKit/src/Protos/Generated/SSKProto.swift @@ -23,6 +23,7 @@ public enum SSKProtoError: Error { case prekeyBundle = 3 case receipt = 5 case unidentifiedSender = 6 + case friendRequest = 101 } private class func SSKProtoEnvelopeTypeWrap(_ value: SignalServiceProtos_Envelope.TypeEnum) -> SSKProtoEnvelopeType { @@ -33,6 +34,7 @@ public enum SSKProtoError: Error { case .prekeyBundle: return .prekeyBundle case .receipt: return .receipt case .unidentifiedSender: return .unidentifiedSender + case .friendRequest: return .friendRequest } } @@ -44,6 +46,7 @@ public enum SSKProtoError: Error { case .prekeyBundle: return .prekeyBundle case .receipt: return .receipt case .unidentifiedSender: return .unidentifiedSender + case .friendRequest: return .friendRequest } } @@ -449,6 +452,12 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { if let _value = typingMessage { builder.setTypingMessage(_value) } + if let _value = prekeyBundleMessage { + builder.setPrekeyBundleMessage(_value) + } + if let _value = lokiAddressMessage { + builder.setLokiAddressMessage(_value) + } return builder } @@ -482,6 +491,14 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { proto.typingMessage = valueParam.proto } + @objc public func setPrekeyBundleMessage(_ valueParam: SSKProtoPrekeyBundleMessage) { + proto.prekeyBundleMessage = valueParam.proto + } + + @objc public func setLokiAddressMessage(_ valueParam: SSKProtoLokiAddressMessage) { + proto.lokiAddressMessage = valueParam.proto + } + @objc public func build() throws -> SSKProtoContent { return try SSKProtoContent.parseProto(proto) } @@ -505,13 +522,19 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { @objc public let typingMessage: SSKProtoTypingMessage? + @objc public let prekeyBundleMessage: SSKProtoPrekeyBundleMessage? + + @objc public let lokiAddressMessage: SSKProtoLokiAddressMessage? + private init(proto: SignalServiceProtos_Content, dataMessage: SSKProtoDataMessage?, syncMessage: SSKProtoSyncMessage?, callMessage: SSKProtoCallMessage?, nullMessage: SSKProtoNullMessage?, receiptMessage: SSKProtoReceiptMessage?, - typingMessage: SSKProtoTypingMessage?) { + typingMessage: SSKProtoTypingMessage?, + prekeyBundleMessage: SSKProtoPrekeyBundleMessage?, + lokiAddressMessage: SSKProtoLokiAddressMessage?) { self.proto = proto self.dataMessage = dataMessage self.syncMessage = syncMessage @@ -519,6 +542,8 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { self.nullMessage = nullMessage self.receiptMessage = receiptMessage self.typingMessage = typingMessage + self.prekeyBundleMessage = prekeyBundleMessage + self.lokiAddressMessage = lokiAddressMessage } @objc @@ -562,6 +587,16 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { typingMessage = try SSKProtoTypingMessage.parseProto(proto.typingMessage) } + var prekeyBundleMessage: SSKProtoPrekeyBundleMessage? = nil + if proto.hasPrekeyBundleMessage { + prekeyBundleMessage = try SSKProtoPrekeyBundleMessage.parseProto(proto.prekeyBundleMessage) + } + + var lokiAddressMessage: SSKProtoLokiAddressMessage? = nil + if proto.hasLokiAddressMessage { + lokiAddressMessage = try SSKProtoLokiAddressMessage.parseProto(proto.lokiAddressMessage) + } + // MARK: - Begin Validation Logic for SSKProtoContent - // MARK: - End Validation Logic for SSKProtoContent - @@ -572,7 +607,9 @@ extension SSKProtoTypingMessage.SSKProtoTypingMessageBuilder { callMessage: callMessage, nullMessage: nullMessage, receiptMessage: receiptMessage, - typingMessage: typingMessage) + typingMessage: typingMessage, + prekeyBundleMessage: prekeyBundleMessage, + lokiAddressMessage: lokiAddressMessage) return result } @@ -597,6 +634,301 @@ extension SSKProtoContent.SSKProtoContentBuilder { #endif +// MARK: - SSKProtoPrekeyBundleMessage + +@objc public class SSKProtoPrekeyBundleMessage: NSObject { + + // MARK: - SSKProtoPrekeyBundleMessageBuilder + + @objc public class func builder() -> SSKProtoPrekeyBundleMessageBuilder { + return SSKProtoPrekeyBundleMessageBuilder() + } + + // asBuilder() constructs a builder that reflects the proto's contents. + @objc public func asBuilder() -> SSKProtoPrekeyBundleMessageBuilder { + let builder = SSKProtoPrekeyBundleMessageBuilder() + if let _value = identityKey { + builder.setIdentityKey(_value) + } + if hasDeviceID { + builder.setDeviceID(deviceID) + } + if hasPrekeyID { + builder.setPrekeyID(prekeyID) + } + if hasSignedKeyID { + builder.setSignedKeyID(signedKeyID) + } + if let _value = prekey { + builder.setPrekey(_value) + } + if let _value = signedKey { + builder.setSignedKey(_value) + } + if let _value = signature { + builder.setSignature(_value) + } + return builder + } + + @objc public class SSKProtoPrekeyBundleMessageBuilder: NSObject { + + private var proto = SignalServiceProtos_PrekeyBundleMessage() + + @objc fileprivate override init() {} + + @objc public func setIdentityKey(_ valueParam: Data) { + proto.identityKey = valueParam + } + + @objc public func setDeviceID(_ valueParam: UInt32) { + proto.deviceID = valueParam + } + + @objc public func setPrekeyID(_ valueParam: UInt32) { + proto.prekeyID = valueParam + } + + @objc public func setSignedKeyID(_ valueParam: UInt32) { + proto.signedKeyID = valueParam + } + + @objc public func setPrekey(_ valueParam: Data) { + proto.prekey = valueParam + } + + @objc public func setSignedKey(_ valueParam: Data) { + proto.signedKey = valueParam + } + + @objc public func setSignature(_ valueParam: Data) { + proto.signature = valueParam + } + + @objc public func build() throws -> SSKProtoPrekeyBundleMessage { + return try SSKProtoPrekeyBundleMessage.parseProto(proto) + } + + @objc public func buildSerializedData() throws -> Data { + return try SSKProtoPrekeyBundleMessage.parseProto(proto).serializedData() + } + } + + fileprivate let proto: SignalServiceProtos_PrekeyBundleMessage + + @objc public var identityKey: Data? { + guard proto.hasIdentityKey else { + return nil + } + return proto.identityKey + } + @objc public var hasIdentityKey: Bool { + return proto.hasIdentityKey + } + + @objc public var deviceID: UInt32 { + return proto.deviceID + } + @objc public var hasDeviceID: Bool { + return proto.hasDeviceID + } + + @objc public var prekeyID: UInt32 { + return proto.prekeyID + } + @objc public var hasPrekeyID: Bool { + return proto.hasPrekeyID + } + + @objc public var signedKeyID: UInt32 { + return proto.signedKeyID + } + @objc public var hasSignedKeyID: Bool { + return proto.hasSignedKeyID + } + + @objc public var prekey: Data? { + guard proto.hasPrekey else { + return nil + } + return proto.prekey + } + @objc public var hasPrekey: Bool { + return proto.hasPrekey + } + + @objc public var signedKey: Data? { + guard proto.hasSignedKey else { + return nil + } + return proto.signedKey + } + @objc public var hasSignedKey: Bool { + return proto.hasSignedKey + } + + @objc public var signature: Data? { + guard proto.hasSignature else { + return nil + } + return proto.signature + } + @objc public var hasSignature: Bool { + return proto.hasSignature + } + + private init(proto: SignalServiceProtos_PrekeyBundleMessage) { + self.proto = proto + } + + @objc + public func serializedData() throws -> Data { + return try self.proto.serializedData() + } + + @objc public class func parseData(_ serializedData: Data) throws -> SSKProtoPrekeyBundleMessage { + let proto = try SignalServiceProtos_PrekeyBundleMessage(serializedData: serializedData) + return try parseProto(proto) + } + + fileprivate class func parseProto(_ proto: SignalServiceProtos_PrekeyBundleMessage) throws -> SSKProtoPrekeyBundleMessage { + // MARK: - Begin Validation Logic for SSKProtoPrekeyBundleMessage - + + // MARK: - End Validation Logic for SSKProtoPrekeyBundleMessage - + + let result = SSKProtoPrekeyBundleMessage(proto: proto) + return result + } + + @objc public override var debugDescription: String { + return "\(proto)" + } +} + +#if DEBUG + +extension SSKProtoPrekeyBundleMessage { + @objc public func serializedDataIgnoringErrors() -> Data? { + return try! self.serializedData() + } +} + +extension SSKProtoPrekeyBundleMessage.SSKProtoPrekeyBundleMessageBuilder { + @objc public func buildIgnoringErrors() -> SSKProtoPrekeyBundleMessage? { + return try! self.build() + } +} + +#endif + +// MARK: - SSKProtoLokiAddressMessage + +@objc public class SSKProtoLokiAddressMessage: NSObject { + + // MARK: - SSKProtoLokiAddressMessageBuilder + + @objc public class func builder() -> SSKProtoLokiAddressMessageBuilder { + return SSKProtoLokiAddressMessageBuilder() + } + + // asBuilder() constructs a builder that reflects the proto's contents. + @objc public func asBuilder() -> SSKProtoLokiAddressMessageBuilder { + let builder = SSKProtoLokiAddressMessageBuilder() + if let _value = ptpAddress { + builder.setPtpAddress(_value) + } + if hasPtpPort { + builder.setPtpPort(ptpPort) + } + return builder + } + + @objc public class SSKProtoLokiAddressMessageBuilder: NSObject { + + private var proto = SignalServiceProtos_LokiAddressMessage() + + @objc fileprivate override init() {} + + @objc public func setPtpAddress(_ valueParam: String) { + proto.ptpAddress = valueParam + } + + @objc public func setPtpPort(_ valueParam: UInt32) { + proto.ptpPort = valueParam + } + + @objc public func build() throws -> SSKProtoLokiAddressMessage { + return try SSKProtoLokiAddressMessage.parseProto(proto) + } + + @objc public func buildSerializedData() throws -> Data { + return try SSKProtoLokiAddressMessage.parseProto(proto).serializedData() + } + } + + fileprivate let proto: SignalServiceProtos_LokiAddressMessage + + @objc public var ptpAddress: String? { + guard proto.hasPtpAddress else { + return nil + } + return proto.ptpAddress + } + @objc public var hasPtpAddress: Bool { + return proto.hasPtpAddress + } + + @objc public var ptpPort: UInt32 { + return proto.ptpPort + } + @objc public var hasPtpPort: Bool { + return proto.hasPtpPort + } + + private init(proto: SignalServiceProtos_LokiAddressMessage) { + self.proto = proto + } + + @objc + public func serializedData() throws -> Data { + return try self.proto.serializedData() + } + + @objc public class func parseData(_ serializedData: Data) throws -> SSKProtoLokiAddressMessage { + let proto = try SignalServiceProtos_LokiAddressMessage(serializedData: serializedData) + return try parseProto(proto) + } + + fileprivate class func parseProto(_ proto: SignalServiceProtos_LokiAddressMessage) throws -> SSKProtoLokiAddressMessage { + // MARK: - Begin Validation Logic for SSKProtoLokiAddressMessage - + + // MARK: - End Validation Logic for SSKProtoLokiAddressMessage - + + let result = SSKProtoLokiAddressMessage(proto: proto) + return result + } + + @objc public override var debugDescription: String { + return "\(proto)" + } +} + +#if DEBUG + +extension SSKProtoLokiAddressMessage { + @objc public func serializedDataIgnoringErrors() -> Data? { + return try! self.serializedData() + } +} + +extension SSKProtoLokiAddressMessage.SSKProtoLokiAddressMessageBuilder { + @objc public func buildIgnoringErrors() -> SSKProtoLokiAddressMessage? { + return try! self.build() + } +} + +#endif + // MARK: - SSKProtoCallMessageOffer @objc public class SSKProtoCallMessageOffer: NSObject { @@ -2865,6 +3197,9 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { } builder.setContact(contact) builder.setPreview(preview) + if let _value = profile { + builder.setProfile(_value) + } return builder } @@ -2932,6 +3267,10 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { proto.preview = wrappedItems.map { $0.proto } } + @objc public func setProfile(_ valueParam: SSKProtoDataMessageContact) { + proto.profile = valueParam.proto + } + @objc public func build() throws -> SSKProtoDataMessage { return try SSKProtoDataMessage.parseProto(proto) } @@ -2953,6 +3292,8 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { @objc public let preview: [SSKProtoDataMessagePreview] + @objc public let profile: SSKProtoDataMessageContact? + @objc public var body: String? { guard proto.hasBody else { return nil @@ -2999,13 +3340,15 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { group: SSKProtoGroupContext?, quote: SSKProtoDataMessageQuote?, contact: [SSKProtoDataMessageContact], - preview: [SSKProtoDataMessagePreview]) { + preview: [SSKProtoDataMessagePreview], + profile: SSKProtoDataMessageContact?) { self.proto = proto self.attachments = attachments self.group = group self.quote = quote self.contact = contact self.preview = preview + self.profile = profile } @objc @@ -3038,6 +3381,11 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { var preview: [SSKProtoDataMessagePreview] = [] preview = try proto.preview.map { try SSKProtoDataMessagePreview.parseProto($0) } + var profile: SSKProtoDataMessageContact? = nil + if proto.hasProfile { + profile = try SSKProtoDataMessageContact.parseProto(proto.profile) + } + // MARK: - Begin Validation Logic for SSKProtoDataMessage - // MARK: - End Validation Logic for SSKProtoDataMessage - @@ -3047,7 +3395,8 @@ extension SSKProtoDataMessagePreview.SSKProtoDataMessagePreviewBuilder { group: group, quote: quote, contact: contact, - preview: preview) + preview: preview, + profile: profile) return result } diff --git a/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift b/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift index b023dec52..faa449417 100644 --- a/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift +++ b/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift @@ -130,6 +130,9 @@ struct SignalServiceProtos_Envelope { case receipt // = 5 case unidentifiedSender // = 6 + /// Loki: Contains prekeys and a message; uses simple encryption + case friendRequest // = 101 + init() { self = .unknown } @@ -142,6 +145,7 @@ struct SignalServiceProtos_Envelope { case 3: self = .prekeyBundle case 5: self = .receipt case 6: self = .unidentifiedSender + case 101: self = .friendRequest default: return nil } } @@ -154,6 +158,7 @@ struct SignalServiceProtos_Envelope { case .prekeyBundle: return 3 case .receipt: return 5 case .unidentifiedSender: return 6 + case .friendRequest: return 101 } } @@ -316,6 +321,26 @@ struct SignalServiceProtos_Content { /// Clears the value of `typingMessage`. Subsequent reads from it will return its default value. mutating func clearTypingMessage() {_uniqueStorage()._typingMessage = nil} + /// Loki + var prekeyBundleMessage: SignalServiceProtos_PrekeyBundleMessage { + get {return _storage._prekeyBundleMessage ?? SignalServiceProtos_PrekeyBundleMessage()} + set {_uniqueStorage()._prekeyBundleMessage = newValue} + } + /// Returns true if `prekeyBundleMessage` has been explicitly set. + var hasPrekeyBundleMessage: Bool {return _storage._prekeyBundleMessage != nil} + /// Clears the value of `prekeyBundleMessage`. Subsequent reads from it will return its default value. + mutating func clearPrekeyBundleMessage() {_uniqueStorage()._prekeyBundleMessage = nil} + + /// Loki + var lokiAddressMessage: SignalServiceProtos_LokiAddressMessage { + get {return _storage._lokiAddressMessage ?? SignalServiceProtos_LokiAddressMessage()} + set {_uniqueStorage()._lokiAddressMessage = newValue} + } + /// Returns true if `lokiAddressMessage` has been explicitly set. + var hasLokiAddressMessage: Bool {return _storage._lokiAddressMessage != nil} + /// Clears the value of `lokiAddressMessage`. Subsequent reads from it will return its default value. + mutating func clearLokiAddressMessage() {_uniqueStorage()._lokiAddressMessage = nil} + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -323,6 +348,121 @@ struct SignalServiceProtos_Content { fileprivate var _storage = _StorageClass.defaultInstance } +/// Loki +struct SignalServiceProtos_PrekeyBundleMessage { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var identityKey: Data { + get {return _identityKey ?? SwiftProtobuf.Internal.emptyData} + set {_identityKey = newValue} + } + /// Returns true if `identityKey` has been explicitly set. + var hasIdentityKey: Bool {return self._identityKey != nil} + /// Clears the value of `identityKey`. Subsequent reads from it will return its default value. + mutating func clearIdentityKey() {self._identityKey = nil} + + var deviceID: UInt32 { + get {return _deviceID ?? 0} + set {_deviceID = newValue} + } + /// Returns true if `deviceID` has been explicitly set. + var hasDeviceID: Bool {return self._deviceID != nil} + /// Clears the value of `deviceID`. Subsequent reads from it will return its default value. + mutating func clearDeviceID() {self._deviceID = nil} + + var prekeyID: UInt32 { + get {return _prekeyID ?? 0} + set {_prekeyID = newValue} + } + /// Returns true if `prekeyID` has been explicitly set. + var hasPrekeyID: Bool {return self._prekeyID != nil} + /// Clears the value of `prekeyID`. Subsequent reads from it will return its default value. + mutating func clearPrekeyID() {self._prekeyID = nil} + + var signedKeyID: UInt32 { + get {return _signedKeyID ?? 0} + set {_signedKeyID = newValue} + } + /// Returns true if `signedKeyID` has been explicitly set. + var hasSignedKeyID: Bool {return self._signedKeyID != nil} + /// Clears the value of `signedKeyID`. Subsequent reads from it will return its default value. + mutating func clearSignedKeyID() {self._signedKeyID = nil} + + var prekey: Data { + get {return _prekey ?? SwiftProtobuf.Internal.emptyData} + set {_prekey = newValue} + } + /// Returns true if `prekey` has been explicitly set. + var hasPrekey: Bool {return self._prekey != nil} + /// Clears the value of `prekey`. Subsequent reads from it will return its default value. + mutating func clearPrekey() {self._prekey = nil} + + var signedKey: Data { + get {return _signedKey ?? SwiftProtobuf.Internal.emptyData} + set {_signedKey = newValue} + } + /// Returns true if `signedKey` has been explicitly set. + var hasSignedKey: Bool {return self._signedKey != nil} + /// Clears the value of `signedKey`. Subsequent reads from it will return its default value. + mutating func clearSignedKey() {self._signedKey = nil} + + var signature: Data { + get {return _signature ?? SwiftProtobuf.Internal.emptyData} + set {_signature = newValue} + } + /// Returns true if `signature` has been explicitly set. + var hasSignature: Bool {return self._signature != nil} + /// Clears the value of `signature`. Subsequent reads from it will return its default value. + mutating func clearSignature() {self._signature = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _identityKey: Data? = nil + fileprivate var _deviceID: UInt32? = nil + fileprivate var _prekeyID: UInt32? = nil + fileprivate var _signedKeyID: UInt32? = nil + fileprivate var _prekey: Data? = nil + fileprivate var _signedKey: Data? = nil + fileprivate var _signature: Data? = nil +} + +/// Loki +struct SignalServiceProtos_LokiAddressMessage { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// The naming is a bit different from desktop because of swift auto generation + var ptpAddress: String { + get {return _ptpAddress ?? String()} + set {_ptpAddress = newValue} + } + /// Returns true if `ptpAddress` has been explicitly set. + var hasPtpAddress: Bool {return self._ptpAddress != nil} + /// Clears the value of `ptpAddress`. Subsequent reads from it will return its default value. + mutating func clearPtpAddress() {self._ptpAddress = nil} + + var ptpPort: UInt32 { + get {return _ptpPort ?? 0} + set {_ptpPort = newValue} + } + /// Returns true if `ptpPort` has been explicitly set. + var hasPtpPort: Bool {return self._ptpPort != nil} + /// Clears the value of `ptpPort`. Subsequent reads from it will return its default value. + mutating func clearPtpPort() {self._ptpPort = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _ptpAddress: String? = nil + fileprivate var _ptpPort: UInt32? = nil +} + struct SignalServiceProtos_CallMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for @@ -639,6 +779,16 @@ struct SignalServiceProtos_DataMessage { set {_uniqueStorage()._preview = newValue} } + /// Loki: The current user's profile + var profile: SignalServiceProtos_DataMessage.Contact { + get {return _storage._profile ?? SignalServiceProtos_DataMessage.Contact()} + set {_uniqueStorage()._profile = newValue} + } + /// Returns true if `profile` has been explicitly set. + var hasProfile: Bool {return _storage._profile != nil} + /// Clears the value of `profile`. Subsequent reads from it will return its default value. + mutating func clearProfile() {_uniqueStorage()._profile = nil} + var unknownFields = SwiftProtobuf.UnknownStorage() enum Flags: SwiftProtobuf.Enum { @@ -2396,6 +2546,7 @@ extension SignalServiceProtos_Envelope.TypeEnum: SwiftProtobuf._ProtoNameProvidi 3: .same(proto: "PREKEY_BUNDLE"), 5: .same(proto: "RECEIPT"), 6: .same(proto: "UNIDENTIFIED_SENDER"), + 101: .same(proto: "FRIEND_REQUEST"), ] } @@ -2456,6 +2607,8 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes 4: .same(proto: "nullMessage"), 5: .same(proto: "receiptMessage"), 6: .same(proto: "typingMessage"), + 101: .same(proto: "prekeyBundleMessage"), + 102: .same(proto: "lokiAddressMessage"), ] fileprivate class _StorageClass { @@ -2465,6 +2618,8 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes var _nullMessage: SignalServiceProtos_NullMessage? = nil var _receiptMessage: SignalServiceProtos_ReceiptMessage? = nil var _typingMessage: SignalServiceProtos_TypingMessage? = nil + var _prekeyBundleMessage: SignalServiceProtos_PrekeyBundleMessage? = nil + var _lokiAddressMessage: SignalServiceProtos_LokiAddressMessage? = nil static let defaultInstance = _StorageClass() @@ -2477,6 +2632,8 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes _nullMessage = source._nullMessage _receiptMessage = source._receiptMessage _typingMessage = source._typingMessage + _prekeyBundleMessage = source._prekeyBundleMessage + _lokiAddressMessage = source._lokiAddressMessage } } @@ -2498,6 +2655,8 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes case 4: try decoder.decodeSingularMessageField(value: &_storage._nullMessage) case 5: try decoder.decodeSingularMessageField(value: &_storage._receiptMessage) case 6: try decoder.decodeSingularMessageField(value: &_storage._typingMessage) + case 101: try decoder.decodeSingularMessageField(value: &_storage._prekeyBundleMessage) + case 102: try decoder.decodeSingularMessageField(value: &_storage._lokiAddressMessage) default: break } } @@ -2524,6 +2683,12 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes if let v = _storage._typingMessage { try visitor.visitSingularMessageField(value: v, fieldNumber: 6) } + if let v = _storage._prekeyBundleMessage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 101) + } + if let v = _storage._lokiAddressMessage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 102) + } } try unknownFields.traverse(visitor: &visitor) } @@ -2539,6 +2704,8 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes if _storage._nullMessage != rhs_storage._nullMessage {return false} if _storage._receiptMessage != rhs_storage._receiptMessage {return false} if _storage._typingMessage != rhs_storage._typingMessage {return false} + if _storage._prekeyBundleMessage != rhs_storage._prekeyBundleMessage {return false} + if _storage._lokiAddressMessage != rhs_storage._lokiAddressMessage {return false} return true } if !storagesAreEqual {return false} @@ -2548,6 +2715,106 @@ extension SignalServiceProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._Mes } } +extension SignalServiceProtos_PrekeyBundleMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".PrekeyBundleMessage" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "identityKey"), + 2: .same(proto: "deviceID"), + 3: .same(proto: "prekeyID"), + 4: .same(proto: "signedKeyID"), + 5: .same(proto: "prekey"), + 6: .same(proto: "signedKey"), + 7: .same(proto: "signature"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularBytesField(value: &self._identityKey) + case 2: try decoder.decodeSingularUInt32Field(value: &self._deviceID) + case 3: try decoder.decodeSingularUInt32Field(value: &self._prekeyID) + case 4: try decoder.decodeSingularUInt32Field(value: &self._signedKeyID) + case 5: try decoder.decodeSingularBytesField(value: &self._prekey) + case 6: try decoder.decodeSingularBytesField(value: &self._signedKey) + case 7: try decoder.decodeSingularBytesField(value: &self._signature) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._identityKey { + try visitor.visitSingularBytesField(value: v, fieldNumber: 1) + } + if let v = self._deviceID { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2) + } + if let v = self._prekeyID { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 3) + } + if let v = self._signedKeyID { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4) + } + if let v = self._prekey { + try visitor.visitSingularBytesField(value: v, fieldNumber: 5) + } + if let v = self._signedKey { + try visitor.visitSingularBytesField(value: v, fieldNumber: 6) + } + if let v = self._signature { + try visitor.visitSingularBytesField(value: v, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SignalServiceProtos_PrekeyBundleMessage, rhs: SignalServiceProtos_PrekeyBundleMessage) -> Bool { + if lhs._identityKey != rhs._identityKey {return false} + if lhs._deviceID != rhs._deviceID {return false} + if lhs._prekeyID != rhs._prekeyID {return false} + if lhs._signedKeyID != rhs._signedKeyID {return false} + if lhs._prekey != rhs._prekey {return false} + if lhs._signedKey != rhs._signedKey {return false} + if lhs._signature != rhs._signature {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SignalServiceProtos_LokiAddressMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".LokiAddressMessage" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "ptpAddress"), + 2: .same(proto: "ptpPort"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularStringField(value: &self._ptpAddress) + case 2: try decoder.decodeSingularUInt32Field(value: &self._ptpPort) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._ptpAddress { + try visitor.visitSingularStringField(value: v, fieldNumber: 1) + } + if let v = self._ptpPort { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SignalServiceProtos_LokiAddressMessage, rhs: SignalServiceProtos_LokiAddressMessage) -> Bool { + if lhs._ptpAddress != rhs._ptpAddress {return false} + if lhs._ptpPort != rhs._ptpPort {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + extension SignalServiceProtos_CallMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { static let protoMessageName: String = _protobuf_package + ".CallMessage" static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -2837,6 +3104,7 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. 8: .same(proto: "quote"), 9: .same(proto: "contact"), 10: .same(proto: "preview"), + 101: .same(proto: "profile"), ] fileprivate class _StorageClass { @@ -2850,6 +3118,7 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. var _quote: SignalServiceProtos_DataMessage.Quote? = nil var _contact: [SignalServiceProtos_DataMessage.Contact] = [] var _preview: [SignalServiceProtos_DataMessage.Preview] = [] + var _profile: SignalServiceProtos_DataMessage.Contact? = nil static let defaultInstance = _StorageClass() @@ -2866,6 +3135,7 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. _quote = source._quote _contact = source._contact _preview = source._preview + _profile = source._profile } } @@ -2891,6 +3161,7 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. case 8: try decoder.decodeSingularMessageField(value: &_storage._quote) case 9: try decoder.decodeRepeatedMessageField(value: &_storage._contact) case 10: try decoder.decodeRepeatedMessageField(value: &_storage._preview) + case 101: try decoder.decodeSingularMessageField(value: &_storage._profile) default: break } } @@ -2929,6 +3200,9 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. if !_storage._preview.isEmpty { try visitor.visitRepeatedMessageField(value: _storage._preview, fieldNumber: 10) } + if let v = _storage._profile { + try visitor.visitSingularMessageField(value: v, fieldNumber: 101) + } } try unknownFields.traverse(visitor: &visitor) } @@ -2948,6 +3222,7 @@ extension SignalServiceProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf. if _storage._quote != rhs_storage._quote {return false} if _storage._contact != rhs_storage._contact {return false} if _storage._preview != rhs_storage._preview {return false} + if _storage._profile != rhs_storage._profile {return false} return true } if !storagesAreEqual {return false} From f8a7c4091434a87ed946af2f0f7ee26b0f50394c Mon Sep 17 00:00:00 2001 From: Mikunj Varsani Date: Wed, 8 May 2019 11:03:02 +1000 Subject: [PATCH 3/7] Add decryption of friend request message type. --- .../src/Messages/OWSMessageDecrypter.m | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m index d3c6d69da..4ef611f5f 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m @@ -214,6 +214,25 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes } switch (envelope.type) { + case SSKProtoEnvelopeTypeFriendRequest: { + [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self decryptFriendRequestMessage:envelope + envelopeData:envelopeData + successBlock:^(OWSMessageDecryptResult *result) { + OWSLogDebug(@"decrypted friend request message."); + successBlock(result, transaction); + } + failureBlock:^(NSError * _Nullable error) { + OWSLogError(@"decrypting friend request message from address: %@ failed " + @"with error: %@", + envelopeAddress(envelope), + error); + failureBlock(); + }]; + }]; + // Return to avoid double-acknowledging + return; + } case SSKProtoEnvelopeTypeCiphertext: { [self throws_decryptSecureMessage:envelope envelopeData:envelopeData @@ -301,6 +320,43 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes failureBlock(); } +- (void)decryptFriendRequestMessage:(SSKProtoEnvelope *)envelope + envelopeData:(NSData *)envelopeData + successBlock:(void (^)(OWSMessageDecryptResult *result))successBlock + failureBlock:(void (^)(NSError *_Nullable error))failureBlock +{ + OWSAssertDebug(envelope); + OWSAssertDebug(envelopeData); + OWSAssertDebug(successBlock); + OWSAssertDebug(failureBlock); + + NSData *encryptedData = envelope.content; + if (!encryptedData) { + OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]); + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, @"Envelope has no content"); + return failureBlock(error); + } + + NSString *recipientId = envelope.source; + FallBackSessionCipher *ciper = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId + identityKeyStore:self.identityManager]; + + // Decrypt it!! + NSData *_Nullable plaintextData = [ciper decryptWithMessage:encryptedData]; + if (!plaintextData) { + NSString *errorString = [NSString stringWithFormat:@"Failed to decrypt friend request message for %@", recipientId]; + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorString); + return failureBlock(error); + } + + OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData + plaintextData:plaintextData + source:envelope.source + sourceDevice:envelope.sourceDevice + isUDMessage:NO]; + successBlock(result); +} + - (void)throws_decryptSecureMessage:(SSKProtoEnvelope *)envelope envelopeData:(NSData *)envelopeData successBlock:(DecryptSuccessBlock)successBlock From 24aabb36b93dc184ebd95faad7ac271715e07791 Mon Sep 17 00:00:00 2001 From: Mikunj Varsani Date: Wed, 8 May 2019 13:33:47 +1000 Subject: [PATCH 4/7] Forgot to add checking for friend request in OWSMessageManager. --- SignalServiceKit/src/Messages/OWSMessageHandler.m | 2 ++ SignalServiceKit/src/Messages/OWSMessageManager.m | 1 + 2 files changed, 3 insertions(+) diff --git a/SignalServiceKit/src/Messages/OWSMessageHandler.m b/SignalServiceKit/src/Messages/OWSMessageHandler.m index 61e5d7e9e..9a3f8a0f7 100644 --- a/SignalServiceKit/src/Messages/OWSMessageHandler.m +++ b/SignalServiceKit/src/Messages/OWSMessageHandler.m @@ -36,6 +36,8 @@ NSString *envelopeAddress(SSKProtoEnvelope *envelope) return @"PreKeyEncryptedMessage"; case SSKProtoEnvelopeTypeUnidentifiedSender: return @"UnidentifiedSender"; + case SSKProtoEnvelopeTypeCiphertext: + return @"LokiFriendRequest"; default: // Shouldn't happen OWSProdFail([OWSAnalyticsEvents messageManagerErrorEnvelopeTypeOther]); diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 720ab9b68..bf09eafd3 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -262,6 +262,7 @@ NS_ASSUME_NONNULL_BEGIN [self checkForUnknownLinkedDevice:envelope transaction:transaction]; switch (envelope.type) { + case SSKProtoEnvelopeTypeFriendRequest: case SSKProtoEnvelopeTypeCiphertext: case SSKProtoEnvelopeTypePrekeyBundle: case SSKProtoEnvelopeTypeUnidentifiedSender: From 574c72523b51ccc817b246285e1ae88df3214935 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Wed, 8 May 2019 14:17:24 +1000 Subject: [PATCH 5/7] Fix typo --- SignalServiceKit/src/Messages/OWSMessageDecrypter.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m index 4ef611f5f..6d8e09642 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m @@ -223,8 +223,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes successBlock(result, transaction); } failureBlock:^(NSError * _Nullable error) { - OWSLogError(@"decrypting friend request message from address: %@ failed " - @"with error: %@", + OWSLogError(@"decrypting friend request message from address: %@ failed with error: %@", envelopeAddress(envelope), error); failureBlock(); @@ -338,11 +337,10 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes } NSString *recipientId = envelope.source; - FallBackSessionCipher *ciper = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId - identityKeyStore:self.identityManager]; + FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId identityKeyStore:self.identityManager]; // Decrypt it!! - NSData *_Nullable plaintextData = [ciper decryptWithMessage:encryptedData]; + NSData *_Nullable plaintextData = [cipher decryptWithMessage:encryptedData]; if (!plaintextData) { NSString *errorString = [NSString stringWithFormat:@"Failed to decrypt friend request message for %@", recipientId]; NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecryptMessage, errorString); From 142a5e78be4c02447e637070160d1c4c6e463af1 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Wed, 8 May 2019 14:17:57 +1000 Subject: [PATCH 6/7] Update Pods --- Pods | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pods b/Pods index 860a0dd80..bb57d99f1 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 860a0dd80a10bd514e29f07c973bd97f4c68f00e +Subproject commit bb57d99f1ab9cf5a752ccc7ce1b1afa58f79d12f From ab00bd54b90f4ac62f75773c0829067089488513 Mon Sep 17 00:00:00 2001 From: Mikunj Varsani Date: Wed, 8 May 2019 14:23:54 +1000 Subject: [PATCH 7/7] Fixes --- Pods | 2 +- SignalServiceKit/src/Messages/OWSMessageHandler.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Pods b/Pods index bb57d99f1..860a0dd80 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit bb57d99f1ab9cf5a752ccc7ce1b1afa58f79d12f +Subproject commit 860a0dd80a10bd514e29f07c973bd97f4c68f00e diff --git a/SignalServiceKit/src/Messages/OWSMessageHandler.m b/SignalServiceKit/src/Messages/OWSMessageHandler.m index 9a3f8a0f7..e1de268a3 100644 --- a/SignalServiceKit/src/Messages/OWSMessageHandler.m +++ b/SignalServiceKit/src/Messages/OWSMessageHandler.m @@ -36,7 +36,7 @@ NSString *envelopeAddress(SSKProtoEnvelope *envelope) return @"PreKeyEncryptedMessage"; case SSKProtoEnvelopeTypeUnidentifiedSender: return @"UnidentifiedSender"; - case SSKProtoEnvelopeTypeCiphertext: + case SSKProtoEnvelopeTypeFriendRequest: return @"LokiFriendRequest"; default: // Shouldn't happen