Remove CDSH
This commit is contained in:
parent
62fd09cd38
commit
cc4af7b88e
@ -1526,10 +1526,8 @@
|
||||
F9C5CC96289453B300548EEE /* SessionRecord.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9AB289453B100548EEE /* SessionRecord.pb.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC97289453B300548EEE /* WebSocketProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9AC289453B100548EEE /* WebSocketProto.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC98289453B300548EEE /* GroupsProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9AD289453B100548EEE /* GroupsProto.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC99289453B300548EEE /* ContactDiscovery.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9AE289453B100548EEE /* ContactDiscovery.pb.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9A289453B300548EEE /* SignalService.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9AF289453B100548EEE /* SignalService.pb.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9B289453B300548EEE /* KeyBackupProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B0289453B100548EEE /* KeyBackupProto.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9C289453B300548EEE /* ContactDiscoveryMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B1289453B100548EEE /* ContactDiscoveryMessage.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9D289453B300548EEE /* Provisioning.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B2289453B100548EEE /* Provisioning.pb.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9E289453B300548EEE /* SignalIOSProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B3289453B100548EEE /* SignalIOSProto.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CC9F289453B300548EEE /* FingerprintProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9B4289453B100548EEE /* FingerprintProto.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
@ -1564,9 +1562,7 @@
|
||||
F9C5CCBC289453B300548EEE /* PhoneNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D4289453B100548EEE /* PhoneNumber.m */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCBD289453B300548EEE /* UUIDBackfillTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D6289453B100548EEE /* UUIDBackfillTask.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCBE289453B300548EEE /* SGXContactDiscoveryOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D7289453B100548EEE /* SGXContactDiscoveryOperation.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCBF289453B300548EEE /* HSMContactDiscoveryOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D8289453B100548EEE /* HSMContactDiscoveryOperation.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCC0289453B300548EEE /* ContactDiscoveryTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9D9289453B100548EEE /* ContactDiscoveryTask.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCC1289453B300548EEE /* CDSHWebsocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DA289453B100548EEE /* CDSHWebsocket.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCC2289453B300548EEE /* BulkUUIDLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DB289453B100548EEE /* BulkUUIDLookup.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCC3289453B300548EEE /* ContactDiscoveryOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DC289453B100548EEE /* ContactDiscoveryOperation.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
F9C5CCC4289453B300548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C5C9DD289453B100548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift */; settings = {COMPILER_FLAGS = "-fcxx-modules"; }; };
|
||||
@ -3864,10 +3860,8 @@
|
||||
F9C5C9AB289453B100548EEE /* SessionRecord.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionRecord.pb.swift; sourceTree = "<group>"; };
|
||||
F9C5C9AC289453B100548EEE /* WebSocketProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebSocketProto.swift; sourceTree = "<group>"; };
|
||||
F9C5C9AD289453B100548EEE /* GroupsProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupsProto.swift; sourceTree = "<group>"; };
|
||||
F9C5C9AE289453B100548EEE /* ContactDiscovery.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscovery.pb.swift; sourceTree = "<group>"; };
|
||||
F9C5C9AF289453B100548EEE /* SignalService.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalService.pb.swift; sourceTree = "<group>"; };
|
||||
F9C5C9B0289453B100548EEE /* KeyBackupProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupProto.swift; sourceTree = "<group>"; };
|
||||
F9C5C9B1289453B100548EEE /* ContactDiscoveryMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscoveryMessage.swift; sourceTree = "<group>"; };
|
||||
F9C5C9B2289453B100548EEE /* Provisioning.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Provisioning.pb.swift; sourceTree = "<group>"; };
|
||||
F9C5C9B3289453B100548EEE /* SignalIOSProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalIOSProto.swift; sourceTree = "<group>"; };
|
||||
F9C5C9B4289453B100548EEE /* FingerprintProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FingerprintProto.swift; sourceTree = "<group>"; };
|
||||
@ -3902,9 +3896,7 @@
|
||||
F9C5C9D4289453B100548EEE /* PhoneNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumber.m; sourceTree = "<group>"; };
|
||||
F9C5C9D6289453B100548EEE /* UUIDBackfillTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUIDBackfillTask.swift; sourceTree = "<group>"; };
|
||||
F9C5C9D7289453B100548EEE /* SGXContactDiscoveryOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SGXContactDiscoveryOperation.swift; sourceTree = "<group>"; };
|
||||
F9C5C9D8289453B100548EEE /* HSMContactDiscoveryOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HSMContactDiscoveryOperation.swift; sourceTree = "<group>"; };
|
||||
F9C5C9D9289453B100548EEE /* ContactDiscoveryTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscoveryTask.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DA289453B100548EEE /* CDSHWebsocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CDSHWebsocket.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DB289453B100548EEE /* BulkUUIDLookup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BulkUUIDLookup.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DC289453B100548EEE /* ContactDiscoveryOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactDiscoveryOperation.swift; sourceTree = "<group>"; };
|
||||
F9C5C9DD289453B100548EEE /* OWSDisappearingMessagesConfiguration+SDS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSDisappearingMessagesConfiguration+SDS.swift"; sourceTree = "<group>"; };
|
||||
@ -7545,8 +7537,6 @@
|
||||
F9C5C9A2289453B100548EEE /* Generated */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9C5C9AE289453B100548EEE /* ContactDiscovery.pb.swift */,
|
||||
F9C5C9B1289453B100548EEE /* ContactDiscoveryMessage.swift */,
|
||||
F9C5C9A9289453B100548EEE /* DeviceTransfer.pb.swift */,
|
||||
F9C5C9B5289453B100548EEE /* DeviceTransferProto.swift */,
|
||||
F9C5C9A6289453B100548EEE /* Fingerprint.pb.swift */,
|
||||
@ -7647,10 +7637,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9C5C9DB289453B100548EEE /* BulkUUIDLookup.swift */,
|
||||
F9C5C9DA289453B100548EEE /* CDSHWebsocket.swift */,
|
||||
F9C5C9DC289453B100548EEE /* ContactDiscoveryOperation.swift */,
|
||||
F9C5C9D9289453B100548EEE /* ContactDiscoveryTask.swift */,
|
||||
F9C5C9D8289453B100548EEE /* HSMContactDiscoveryOperation.swift */,
|
||||
F9C5C9D7289453B100548EEE /* SGXContactDiscoveryOperation.swift */,
|
||||
F9C5C9D6289453B100548EEE /* UUIDBackfillTask.swift */,
|
||||
);
|
||||
@ -10586,7 +10574,6 @@
|
||||
F9C5CD8D289453B300548EEE /* CaptchaChallenge.swift in Sources */,
|
||||
76387BF028F4ED73002C7BA5 /* CaseIterable.swift in Sources */,
|
||||
F9C5CC0C289453B300548EEE /* CDNDownloadOperation.swift in Sources */,
|
||||
F9C5CCC1289453B300548EEE /* CDSHWebsocket.swift in Sources */,
|
||||
661396AD28BE74DC00E0C4DF /* ChainedPromise.swift in Sources */,
|
||||
F9C5CE0E289453B400548EEE /* ChangePhoneNumber.swift in Sources */,
|
||||
F9C5CCF2289453B300548EEE /* ChunkedInputStream.swift in Sources */,
|
||||
@ -10594,8 +10581,6 @@
|
||||
F9C5CCE5289453B300548EEE /* Contact+Swift.swift in Sources */,
|
||||
F9C5CCB5289453B300548EEE /* Contact.m in Sources */,
|
||||
F9C5CCE4289453B300548EEE /* Contact.swift in Sources */,
|
||||
F9C5CC99289453B300548EEE /* ContactDiscovery.pb.swift in Sources */,
|
||||
F9C5CC9C289453B300548EEE /* ContactDiscoveryMessage.swift in Sources */,
|
||||
F9C5CCC3289453B300548EEE /* ContactDiscoveryOperation.swift in Sources */,
|
||||
F9C5CDC1289453B400548EEE /* ContactDiscoveryService.swift in Sources */,
|
||||
F9C5CCC0289453B300548EEE /* ContactDiscoveryTask.swift in Sources */,
|
||||
@ -10667,7 +10652,6 @@
|
||||
F9C5CE78289453B400548EEE /* GroupsV2.swift in Sources */,
|
||||
F9C5CDA1289453B400548EEE /* GroupsV2MessageJobFinder.swift in Sources */,
|
||||
F9C5CDA2289453B400548EEE /* GroupsV2MessageProcessor.swift in Sources */,
|
||||
F9C5CCBF289453B300548EEE /* HSMContactDiscoveryOperation.swift in Sources */,
|
||||
F9C5CD94289453B300548EEE /* HTMLMetadata.swift in Sources */,
|
||||
F9C5CDC2289453B400548EEE /* HTTPEntities.swift in Sources */,
|
||||
F9C5CDBC289453B400548EEE /* HTTPUtils.m in Sources */,
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
// iOS - package name determines class prefix
|
||||
package ContactDiscoveryMessages;
|
||||
|
||||
message ClientRequest {
|
||||
// Each ACI/UAK pair is a 32-byte buffer, containing the 16-byte ACI followed
|
||||
// by its 16-byte UAK.
|
||||
bytes aciUakPairs = 1;
|
||||
|
||||
// Each E164 is an 8-byte big-endian number, as 8 bytes.
|
||||
bytes prevE164List = 2;
|
||||
bytes newE164List = 3;
|
||||
bytes discardE164List = 4;
|
||||
|
||||
// If true, the client has more pairs or e164s to send. If false or unset,
|
||||
// this is the client's last request, and processing should commence.
|
||||
bool moreComing = 5;
|
||||
|
||||
// If set, a token which allows rate limiting to discount the e164s in
|
||||
// the request's prev_e164s, only counting new_e164s. If not set, then
|
||||
// rate limiting considers both prev_e164s' and new_e164s' size.
|
||||
bytes token = 6;
|
||||
}
|
||||
|
||||
message ClientResponse {
|
||||
// Each triple is an 8-byte e164, a 16-byte PNI, and a 16-byte ACI.
|
||||
// If the e164 was not found, PNI and ACI are all zeros. If the PNI
|
||||
// was found but the ACI was not, the PNI will be non-zero and the ACI
|
||||
// will be all zeros. ACI will be returned if one of the returned
|
||||
// PNIs has an ACI/UAK pair that matches.
|
||||
//
|
||||
// Should the request be successful (IE: a successful status returned),
|
||||
// |e164_pni_aci_triple| will always equal |e164| of the request,
|
||||
// so the entire marshalled size of the response will be (2+32)*|e164|,
|
||||
// where the additional 2 bytes are the id/type/length additions of the
|
||||
// protobuf marshaling added to each byte array. This avoids any data
|
||||
// leakage based on the size of the encrypted output.
|
||||
bytes e164PniAciTriples = 1;
|
||||
|
||||
// If the user has run out of quota for lookups, they will receive
|
||||
// a response with just the following field set, followed by a websocket
|
||||
// closure of type 4008 (RESOURCE_EXHAUSTED). Should they retry exactly
|
||||
// the same request after the provided number of seconds has passed,
|
||||
// we expect it should work.
|
||||
int32 retryAfterSecs = 2;
|
||||
|
||||
// A token which allows subsequent calls' rate limiting to discount the
|
||||
// e164s sent up in this request, only counting those in the next
|
||||
// request's new_e164s.
|
||||
bytes token = 3;
|
||||
}
|
||||
@ -5,7 +5,7 @@ PROTOC=protoc \
|
||||
WRAPPER_SCRIPT=../../Scripts/ProtoWrappers.py \
|
||||
--proto-dir='./' --verbose
|
||||
|
||||
all: signal_service_protos provisioning_protos fingerprint_protos websocket_protos signal_ios_protos key_backup_protos storage_service_protos groups_protos device_transfer_protos session_record_protos contact_discovery_protos
|
||||
all: signal_service_protos provisioning_protos fingerprint_protos websocket_protos signal_ios_protos key_backup_protos storage_service_protos groups_protos device_transfer_protos session_record_protos
|
||||
|
||||
signal_service_protos: SignalService.proto
|
||||
$(PROTOC) --swift_out=../src/Protos/Generated \
|
||||
@ -69,9 +69,3 @@ device_transfer_protos: DeviceTransfer.proto
|
||||
|
||||
session_record_protos: SessionRecord.proto
|
||||
$(PROTOC) --swift_out=../src/Protos/Generated SessionRecord.proto
|
||||
|
||||
contact_discovery_protos: ContactDiscovery.proto
|
||||
$(PROTOC) --swift_out=../src/Protos/Generated \
|
||||
ContactDiscovery.proto
|
||||
$(WRAPPER_SCRIPT) --dst-dir=../src/Protos/Generated \
|
||||
--wrapper-prefix=ContactDiscoveryMessage --proto-prefix=ContactDiscoveryMessages --proto-file=ContactDiscovery.proto
|
||||
|
||||
@ -1,218 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import LibSignalClient
|
||||
|
||||
public enum CDSHResult {
|
||||
case completed
|
||||
|
||||
case unauthenticated
|
||||
case rateLimited
|
||||
case invalidArgument
|
||||
case serverError
|
||||
case unknown(Error?)
|
||||
}
|
||||
|
||||
public protocol CDSHWebSocketDelegate: AnyObject {
|
||||
func socketDidReceiveData(_ socket: CDSHWebSocket, data: Data)
|
||||
func socketDidClose(_ socket: CDSHWebSocket, result: CDSHResult)
|
||||
}
|
||||
|
||||
public class CDSHWebSocket: Dependencies, SSKWebSocketDelegate {
|
||||
private let queue: DispatchQueue
|
||||
private let socket: SSKWebSocket
|
||||
private let enclaveClient: HsmEnclaveClient
|
||||
public weak var delegate: CDSHWebSocketDelegate?
|
||||
|
||||
private enum State {
|
||||
case disconnected
|
||||
case connecting(Future<Void>)
|
||||
case connected
|
||||
case handshaking(Future<Data>)
|
||||
case established
|
||||
case finished
|
||||
}
|
||||
|
||||
private var state: State = .disconnected {
|
||||
didSet {
|
||||
Logger.verbose("State transition: \(oldValue) -> \(state)")
|
||||
}
|
||||
}
|
||||
|
||||
public init(callbackQueue: DispatchQueue, username: String, password: String) throws {
|
||||
let publicKeyString = TSConstants.contactDiscoveryPublicKey
|
||||
let publicKeyBytes = try Data(hexString: publicKeyString)
|
||||
let codeHashStrings = TSConstants.contactDiscoveryCodeHashes
|
||||
|
||||
let codeHashes = try codeHashStrings.reduce(into: HsmCodeHashList()) { builder, hexString in
|
||||
try builder.append(Data(hexString: hexString))
|
||||
}
|
||||
|
||||
let codeHashString = codeHashStrings.joined(separator: ",")
|
||||
let baseUrl = URL(string: TSConstants.contactDiscoveryHSMURL)!
|
||||
let websocketUrl = URL(
|
||||
string: "\(TSConstants.contactDiscoveryPublicKey)/\(codeHashString)",
|
||||
relativeTo: baseUrl)!
|
||||
|
||||
let httpHeaders = OWSHttpHeaders()
|
||||
httpHeaders.addDefaultHeaders()
|
||||
try httpHeaders.addAuthHeader(username: username, password: password)
|
||||
|
||||
var request = URLRequest(url: websocketUrl)
|
||||
request.add(httpHeaders: httpHeaders)
|
||||
|
||||
let newSocket = Self.webSocketFactory.buildSocket(
|
||||
request: request,
|
||||
callbackQueue: callbackQueue)
|
||||
|
||||
queue = callbackQueue
|
||||
enclaveClient = try HsmEnclaveClient(publicKey: publicKeyBytes, codeHashes: codeHashes)
|
||||
socket = newSocket!
|
||||
socket.delegate = self
|
||||
}
|
||||
|
||||
// MARK: - Public API
|
||||
|
||||
/// Perform initial websocket connection and HSM handshake
|
||||
public func bootstrapPromise() -> Promise<Void> {
|
||||
firstly(on: queue) {
|
||||
self.performConnection()
|
||||
}.then(on: queue) {
|
||||
self.performHandshake()
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts and sends the plaintext to the CDSH service
|
||||
/// Must have waited on `bootstrapPromise` before calling this method
|
||||
public func sendBytes(_ plaintext: Data) {
|
||||
queue.async {
|
||||
guard case .established = self.state else {
|
||||
owsFailDebug("Trying to send to invalid cdsh socket: \(self.state)")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let ciphertext = try self.enclaveClient.establishedSend(plaintext)
|
||||
self.socket.write(data: Data(ciphertext))
|
||||
} catch {
|
||||
owsFailDebug("Failed to construct HSM request body: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func performConnection() -> Promise<Void> {
|
||||
firstly(on: queue) { () -> Promise<Void> in
|
||||
guard case .disconnected = self.state else {
|
||||
throw ContactDiscoveryError.assertionError(description: "Invalid state")
|
||||
}
|
||||
let (connectPromise, connectFuture) = Promise<Void>.pending()
|
||||
self.state = .connecting(connectFuture)
|
||||
self.socket.connect()
|
||||
return connectPromise
|
||||
|
||||
}.done(on: queue) {
|
||||
self.state = .connected
|
||||
}
|
||||
}
|
||||
|
||||
private func performHandshake() -> Promise<Void> {
|
||||
return firstly(on: queue) { () -> Promise<Data> in
|
||||
guard case .connected = self.state else {
|
||||
throw ContactDiscoveryError.assertionError(description: "Invalid state")
|
||||
}
|
||||
let (handshakePromise, handshakeFuture) = Promise<Data>.pending()
|
||||
self.state = .handshaking(handshakeFuture)
|
||||
|
||||
let handshakeRequest = Data(self.enclaveClient.initialRequest())
|
||||
self.socket.write(data: handshakeRequest)
|
||||
return handshakePromise
|
||||
|
||||
}.done(on: queue) { response in
|
||||
try self.enclaveClient.completeHandshake(response)
|
||||
self.state = .established
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - WebSocketDelegate
|
||||
|
||||
public func websocketDidConnect(socket: SSKWebSocket) {
|
||||
assertOnQueue(queue)
|
||||
Logger.info("\(socket) did connect")
|
||||
|
||||
switch state {
|
||||
case .connecting(let future):
|
||||
future.resolve()
|
||||
default:
|
||||
owsFailDebug("Invalid state during connect: \(state)")
|
||||
}
|
||||
}
|
||||
|
||||
public func websocketDidDisconnectOrFail(socket: SSKWebSocket, error: Error?) {
|
||||
assertOnQueue(queue)
|
||||
Logger.info("Socket did disconnect with error: \(String(describing: error))")
|
||||
|
||||
let resultCode: CDSHResult
|
||||
if let error = error {
|
||||
switch webSocketFactory.statusCode(forError: error) {
|
||||
case 1000: resultCode = .completed
|
||||
case 4003: resultCode = .invalidArgument
|
||||
case 4008: resultCode = .rateLimited
|
||||
case 4013: resultCode = .serverError
|
||||
case 4016: resultCode = .unauthenticated
|
||||
default: resultCode = .unknown(error)
|
||||
}
|
||||
} else {
|
||||
// We should always expect an error code, even in the success case.
|
||||
// If we don't have one, it's an error
|
||||
resultCode = .unknown(error)
|
||||
}
|
||||
|
||||
state = .finished
|
||||
delegate?.socketDidClose(self, result: resultCode)
|
||||
}
|
||||
|
||||
public func websocket(
|
||||
_ socket: SSKWebSocket,
|
||||
didReceiveData data: Data
|
||||
) {
|
||||
assertOnQueue(queue)
|
||||
Logger.info("\(socket) did receive: \(data.count) bytes")
|
||||
|
||||
switch state {
|
||||
case .handshaking(let future):
|
||||
future.resolve(data)
|
||||
|
||||
case .established:
|
||||
do {
|
||||
let decryptedBytes = try enclaveClient.establishedRecv(data)
|
||||
delegate?.socketDidReceiveData(self, data: Data(decryptedBytes))
|
||||
} catch {
|
||||
owsFailDebug("Failed to decrypt bytes: \(error)")
|
||||
}
|
||||
|
||||
default:
|
||||
owsFailDebug("Invalid state handling response: \(state)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension HsmCodeHashList {
|
||||
mutating func append(_ data: Data) throws {
|
||||
let byteArray = [UInt8](data)
|
||||
try append(byteArray)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should just be in SignalCoreKit next to Data.data(fromHex:)
|
||||
private extension Data {
|
||||
init(hexString: String) throws {
|
||||
self = try Data.data(fromHex: hexString) ?? {
|
||||
throw ContactDiscoveryError.assertionError(description: "Invalid hex string")
|
||||
}()
|
||||
}
|
||||
}
|
||||
@ -99,11 +99,7 @@ public class ContactDiscoveryTask: NSObject {
|
||||
// MARK: - Private
|
||||
|
||||
private func createContactDiscoveryOperation() -> ContactDiscovering {
|
||||
if FeatureFlags.hsmContactDiscovery {
|
||||
return HSMContactDiscoveryOperation(e164sToLookup: e164FetchSet)
|
||||
} else {
|
||||
return SGXContactDiscoveryOperation(e164sToLookup: e164FetchSet)
|
||||
}
|
||||
return SGXContactDiscoveryOperation(e164sToLookup: e164FetchSet)
|
||||
}
|
||||
|
||||
private func storeResults(
|
||||
|
||||
@ -1,214 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalCoreKit
|
||||
import LibSignalClient
|
||||
|
||||
class HSMContactDiscoveryOperation: ContactDiscovering, CDSHWebSocketDelegate, Dependencies {
|
||||
static let batchSize = 5000
|
||||
private let e164sToLookup: Set<String>
|
||||
|
||||
private var websocket: CDSHWebSocket!
|
||||
private var socketClosePromise: Promise<CDSHResult>?
|
||||
private var socketCloseFuture: Future<CDSHResult>?
|
||||
|
||||
private let format = Format.v1
|
||||
private var resultData = Data()
|
||||
|
||||
required init(e164sToLookup: Set<String>) {
|
||||
self.e164sToLookup = e164sToLookup
|
||||
Logger.debug("with e164sToLookup.count: \(e164sToLookup.count)")
|
||||
}
|
||||
|
||||
func perform(on queue: DispatchQueue) -> Promise<Set<DiscoveredContactInfo>> {
|
||||
firstly {
|
||||
self.fetchAuthentication(on: queue)
|
||||
|
||||
}.then(on: queue) { (username, password) -> Promise<Void> in
|
||||
let (promise, future) = Promise<CDSHResult>.pending()
|
||||
self.socketClosePromise = promise
|
||||
self.socketCloseFuture = future
|
||||
|
||||
self.websocket = try CDSHWebSocket(callbackQueue: queue, username: username, password: password)
|
||||
self.websocket.delegate = self
|
||||
return self.websocket.bootstrapPromise()
|
||||
|
||||
}.then(on: queue) { _ -> Promise<CDSHResult> in
|
||||
try self.sendRequestBody()
|
||||
|
||||
if let resultPromise = self.socketClosePromise {
|
||||
return resultPromise
|
||||
} else {
|
||||
throw ContactDiscoveryError.assertionError(description: "Missing socket promise")
|
||||
}
|
||||
|
||||
}.map(on: queue) { result in
|
||||
switch result {
|
||||
case .completed:
|
||||
return try self.parseResults()
|
||||
|
||||
case .unauthenticated:
|
||||
throw ContactDiscoveryError(
|
||||
kind: .unauthorized,
|
||||
debugDescription: "User is unauthorized",
|
||||
retryable: false,
|
||||
retryAfterDate: self.parseRetryAfterDate())
|
||||
|
||||
case .rateLimited:
|
||||
throw ContactDiscoveryError(
|
||||
kind: .rateLimit,
|
||||
debugDescription: "Rate limit",
|
||||
retryable: true,
|
||||
retryAfterDate: self.parseRetryAfterDate())
|
||||
|
||||
case .invalidArgument:
|
||||
throw ContactDiscoveryError(
|
||||
kind: .genericClientError,
|
||||
debugDescription: "Bad argument",
|
||||
retryable: false,
|
||||
retryAfterDate: self.parseRetryAfterDate())
|
||||
|
||||
case .serverError:
|
||||
throw ContactDiscoveryError(
|
||||
kind: .genericServerError,
|
||||
debugDescription: "Server error",
|
||||
retryable: true,
|
||||
retryAfterDate: self.parseRetryAfterDate())
|
||||
|
||||
case .unknown(let networkError?) where networkError.isNetworkConnectivityFailure:
|
||||
// Anything network related should be returned directly
|
||||
throw networkError
|
||||
|
||||
case .unknown(let error):
|
||||
throw ContactDiscoveryError(
|
||||
kind: .generic,
|
||||
debugDescription: "Unknown error: \((error as NSError?).debugDescription)",
|
||||
retryable: false,
|
||||
retryAfterDate: self.parseRetryAfterDate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchAuthentication(on queue: DispatchQueue) -> Promise<(username: String, password: String)> {
|
||||
let request = OWSRequestFactory.hsmDirectoryAuthRequest()
|
||||
|
||||
return firstly {
|
||||
networkManager.makePromise(request: request)
|
||||
}.map(on: queue) { response in
|
||||
guard let json = response.responseBodyJson else {
|
||||
throw OWSAssertionError("Missing or invalid JSON.")
|
||||
}
|
||||
guard let parser = ParamParser(responseObject: json) else {
|
||||
throw OWSAssertionError("Missing or invalid response.")
|
||||
}
|
||||
let username: String = try parser.required(key: "username")
|
||||
let password: String = try parser.required(key: "password")
|
||||
return (username: username, password: password)
|
||||
}
|
||||
}
|
||||
|
||||
private func sendRequestBody() throws {
|
||||
let batches = Array(self.e164sToLookup).chunked(by: Self.batchSize)
|
||||
|
||||
try batches.enumerated().forEach { idx, batch in
|
||||
var builder = ContactDiscoveryMessageClientRequest.builder()
|
||||
let encodedE164s = try ContactDiscoveryE164Collection(batch).encodedValues
|
||||
builder.setNewE164List(encodedE164s)
|
||||
|
||||
let lastBatchIdx = batches.count - 1
|
||||
builder.setMoreComing(idx != lastBatchIdx)
|
||||
|
||||
var requestBody = Data()
|
||||
switch format {
|
||||
case .v1:
|
||||
requestBody.append(1)
|
||||
case .v2:
|
||||
requestBody.append(2)
|
||||
throw ContactDiscoveryError.assertionError(description: "v2 unsupported")
|
||||
}
|
||||
requestBody.append(try builder.buildSerializedData())
|
||||
self.websocket.sendBytes(requestBody)
|
||||
}
|
||||
}
|
||||
|
||||
private func parseResults() throws -> Set<DiscoveredContactInfo> {
|
||||
let clientResponse = try ContactDiscoveryMessageClientResponse(serializedData: self.resultData)
|
||||
guard let triples = clientResponse.e164PniAciTriples else { return Set() }
|
||||
|
||||
return try triples.chunked(by: 40).reduce(into: Set()) { builder, tripleBytes in
|
||||
if let triple = try parseTriple(tripleBytes) {
|
||||
builder.insert(triple.discoveredContact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Triple {
|
||||
let e164: String
|
||||
let pni: UUID?
|
||||
let aci: UUID
|
||||
|
||||
var discoveredContact: DiscoveredContactInfo {
|
||||
DiscoveredContactInfo(e164: e164, uuid: aci)
|
||||
}
|
||||
}
|
||||
|
||||
private func parseTriple(_ bytes: Data.SubSequence) throws -> Triple? {
|
||||
guard bytes.count == 40 else {
|
||||
owsFailDebug("Invalid triple bytes")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch format {
|
||||
case .v1:
|
||||
let e164Buffer = bytes.prefix(8)
|
||||
let aciBuffer = bytes.dropFirst(24).prefix(16)
|
||||
|
||||
// Nil values indicate this wasn't found
|
||||
guard e164Buffer.contains(where: { $0 != 0 }) else { return nil }
|
||||
guard aciBuffer.contains(where: { $0 != 0 }) else { return nil }
|
||||
|
||||
return bytes.withUnsafeBytes { buffer -> Triple in
|
||||
let bigEndianE164 = buffer.load(fromByteOffset: 0, as: UInt64.self)
|
||||
let hostE164 = UInt64(bigEndian: bigEndianE164)
|
||||
let e164String = "+\(hostE164)"
|
||||
let aci = UUID(uuid: buffer.load(fromByteOffset: 24, as: uuid_t.self))
|
||||
|
||||
return Triple(e164: e164String, pni: nil, aci: aci)
|
||||
}
|
||||
|
||||
case .v2:
|
||||
throw ContactDiscoveryError.assertionError(description: "v2 unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
private func parseRetryAfterDate() -> Date {
|
||||
switch format {
|
||||
case .v1:
|
||||
// TODO: Currently unspecified for v1. Let's default to 30s for now
|
||||
return Date(timeIntervalSinceNow: 30)
|
||||
case .v2:
|
||||
owsFailDebug("v2 unsupported")
|
||||
return Date(timeIntervalSinceNow: 30)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Delegate
|
||||
|
||||
func socketDidReceiveData(_ socket: CDSHWebSocket, data: Data) {
|
||||
resultData.append(data)
|
||||
}
|
||||
|
||||
func socketDidClose(_ socket: CDSHWebSocket, result: CDSHResult) {
|
||||
socketCloseFuture?.resolve(result)
|
||||
}
|
||||
}
|
||||
|
||||
private extension HSMContactDiscoveryOperation {
|
||||
enum Format {
|
||||
case v1
|
||||
case v2
|
||||
}
|
||||
}
|
||||
@ -153,8 +153,6 @@ typedef NS_ENUM(uint8_t, OWSIdentity);
|
||||
+ (TSRequest *)cdsFeedbackRequestWithStatus:(NSString *)status
|
||||
reason:(nullable NSString *)reason NS_SWIFT_NAME(cdsFeedbackRequest(status:reason:));
|
||||
|
||||
+ (TSRequest *)hsmDirectoryAuthRequest;
|
||||
|
||||
#pragma mark - KBS
|
||||
|
||||
+ (TSRequest *)kbsEnclaveTokenRequestWithEnclaveName:(NSString *)enclaveName
|
||||
|
||||
@ -698,12 +698,6 @@ static NSString *_Nullable queryParamForIdentity(OWSIdentity identity)
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
|
||||
}
|
||||
|
||||
+ (TSRequest *)hsmDirectoryAuthRequest
|
||||
{
|
||||
NSURL *url = [NSURL URLWithString:@"v2/directory/auth"];
|
||||
return [TSRequest requestWithUrl:url method:@"GET" parameters:@{}];
|
||||
}
|
||||
|
||||
#pragma mark - KBS
|
||||
|
||||
+ (TSRequest *)kbsEnclaveTokenRequestWithEnclaveName:(NSString *)enclaveName
|
||||
|
||||
@ -1,211 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: ContactDiscovery.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
//
|
||||
// Copyright 2019 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
struct ContactDiscoveryMessages_ClientRequest {
|
||||
// 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.
|
||||
|
||||
/// Each ACI/UAK pair is a 32-byte buffer, containing the 16-byte ACI followed
|
||||
/// by its 16-byte UAK.
|
||||
var aciUakPairs: Data = Data()
|
||||
|
||||
/// Each E164 is an 8-byte big-endian number, as 8 bytes.
|
||||
var prevE164List: Data = Data()
|
||||
|
||||
var newE164List: Data = Data()
|
||||
|
||||
var discardE164List: Data = Data()
|
||||
|
||||
/// If true, the client has more pairs or e164s to send. If false or unset,
|
||||
/// this is the client's last request, and processing should commence.
|
||||
var moreComing: Bool = false
|
||||
|
||||
/// If set, a token which allows rate limiting to discount the e164s in
|
||||
/// the request's prev_e164s, only counting new_e164s. If not set, then
|
||||
/// rate limiting considers both prev_e164s' and new_e164s' size.
|
||||
var token: Data = Data()
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
struct ContactDiscoveryMessages_ClientResponse {
|
||||
// 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.
|
||||
|
||||
/// Each triple is an 8-byte e164, a 16-byte PNI, and a 16-byte ACI.
|
||||
/// If the e164 was not found, PNI and ACI are all zeros. If the PNI
|
||||
/// was found but the ACI was not, the PNI will be non-zero and the ACI
|
||||
/// will be all zeros. ACI will be returned if one of the returned
|
||||
/// PNIs has an ACI/UAK pair that matches.
|
||||
///
|
||||
/// Should the request be successful (IE: a successful status returned),
|
||||
/// |e164_pni_aci_triple| will always equal |e164| of the request,
|
||||
/// so the entire marshalled size of the response will be (2+32)*|e164|,
|
||||
/// where the additional 2 bytes are the id/type/length additions of the
|
||||
/// protobuf marshaling added to each byte array. This avoids any data
|
||||
/// leakage based on the size of the encrypted output.
|
||||
var e164PniAciTriples: Data = Data()
|
||||
|
||||
/// If the user has run out of quota for lookups, they will receive
|
||||
/// a response with just the following field set, followed by a websocket
|
||||
/// closure of type 4008 (RESOURCE_EXHAUSTED). Should they retry exactly
|
||||
/// the same request after the provided number of seconds has passed,
|
||||
/// we expect it should work.
|
||||
var retryAfterSecs: Int32 = 0
|
||||
|
||||
/// A token which allows subsequent calls' rate limiting to discount the
|
||||
/// e164s sent up in this request, only counting those in the next
|
||||
/// request's new_e164s.
|
||||
var token: Data = Data()
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension ContactDiscoveryMessages_ClientRequest: @unchecked Sendable {}
|
||||
extension ContactDiscoveryMessages_ClientResponse: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "ContactDiscoveryMessages"
|
||||
|
||||
extension ContactDiscoveryMessages_ClientRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".ClientRequest"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "aciUakPairs"),
|
||||
2: .same(proto: "prevE164List"),
|
||||
3: .same(proto: "newE164List"),
|
||||
4: .same(proto: "discardE164List"),
|
||||
5: .same(proto: "moreComing"),
|
||||
6: .same(proto: "token"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self.aciUakPairs) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self.prevE164List) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.newE164List) }()
|
||||
case 4: try { try decoder.decodeSingularBytesField(value: &self.discardE164List) }()
|
||||
case 5: try { try decoder.decodeSingularBoolField(value: &self.moreComing) }()
|
||||
case 6: try { try decoder.decodeSingularBytesField(value: &self.token) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.aciUakPairs.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.aciUakPairs, fieldNumber: 1)
|
||||
}
|
||||
if !self.prevE164List.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.prevE164List, fieldNumber: 2)
|
||||
}
|
||||
if !self.newE164List.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.newE164List, fieldNumber: 3)
|
||||
}
|
||||
if !self.discardE164List.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.discardE164List, fieldNumber: 4)
|
||||
}
|
||||
if self.moreComing != false {
|
||||
try visitor.visitSingularBoolField(value: self.moreComing, fieldNumber: 5)
|
||||
}
|
||||
if !self.token.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.token, fieldNumber: 6)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: ContactDiscoveryMessages_ClientRequest, rhs: ContactDiscoveryMessages_ClientRequest) -> Bool {
|
||||
if lhs.aciUakPairs != rhs.aciUakPairs {return false}
|
||||
if lhs.prevE164List != rhs.prevE164List {return false}
|
||||
if lhs.newE164List != rhs.newE164List {return false}
|
||||
if lhs.discardE164List != rhs.discardE164List {return false}
|
||||
if lhs.moreComing != rhs.moreComing {return false}
|
||||
if lhs.token != rhs.token {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactDiscoveryMessages_ClientResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".ClientResponse"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "e164PniAciTriples"),
|
||||
2: .same(proto: "retryAfterSecs"),
|
||||
3: .same(proto: "token"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBytesField(value: &self.e164PniAciTriples) }()
|
||||
case 2: try { try decoder.decodeSingularInt32Field(value: &self.retryAfterSecs) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.token) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.e164PniAciTriples.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.e164PniAciTriples, fieldNumber: 1)
|
||||
}
|
||||
if self.retryAfterSecs != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.retryAfterSecs, fieldNumber: 2)
|
||||
}
|
||||
if !self.token.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.token, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: ContactDiscoveryMessages_ClientResponse, rhs: ContactDiscoveryMessages_ClientResponse) -> Bool {
|
||||
if lhs.e164PniAciTriples != rhs.e164PniAciTriples {return false}
|
||||
if lhs.retryAfterSecs != rhs.retryAfterSecs {return false}
|
||||
if lhs.token != rhs.token {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1,412 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SignalCoreKit
|
||||
import SwiftProtobuf
|
||||
|
||||
// WARNING: This code is generated. Only edit within the markers.
|
||||
|
||||
public enum ContactDiscoveryMessageError: Error {
|
||||
case invalidProtobuf(description: String)
|
||||
}
|
||||
|
||||
// MARK: - ContactDiscoveryMessageClientRequest
|
||||
|
||||
public struct ContactDiscoveryMessageClientRequest: Codable, CustomDebugStringConvertible {
|
||||
|
||||
fileprivate let proto: ContactDiscoveryMessages_ClientRequest
|
||||
|
||||
public var aciUakPairs: Data? {
|
||||
guard hasAciUakPairs else {
|
||||
return nil
|
||||
}
|
||||
return proto.aciUakPairs
|
||||
}
|
||||
public var hasAciUakPairs: Bool {
|
||||
return !proto.aciUakPairs.isEmpty
|
||||
}
|
||||
|
||||
public var prevE164List: Data? {
|
||||
guard hasPrevE164List else {
|
||||
return nil
|
||||
}
|
||||
return proto.prevE164List
|
||||
}
|
||||
public var hasPrevE164List: Bool {
|
||||
return !proto.prevE164List.isEmpty
|
||||
}
|
||||
|
||||
public var newE164List: Data? {
|
||||
guard hasNewE164List else {
|
||||
return nil
|
||||
}
|
||||
return proto.newE164List
|
||||
}
|
||||
public var hasNewE164List: Bool {
|
||||
return !proto.newE164List.isEmpty
|
||||
}
|
||||
|
||||
public var discardE164List: Data? {
|
||||
guard hasDiscardE164List else {
|
||||
return nil
|
||||
}
|
||||
return proto.discardE164List
|
||||
}
|
||||
public var hasDiscardE164List: Bool {
|
||||
return !proto.discardE164List.isEmpty
|
||||
}
|
||||
|
||||
public var moreComing: Bool {
|
||||
return proto.moreComing
|
||||
}
|
||||
public var hasMoreComing: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public var token: Data? {
|
||||
guard hasToken else {
|
||||
return nil
|
||||
}
|
||||
return proto.token
|
||||
}
|
||||
public var hasToken: Bool {
|
||||
return !proto.token.isEmpty
|
||||
}
|
||||
|
||||
public var hasUnknownFields: Bool {
|
||||
return !proto.unknownFields.data.isEmpty
|
||||
}
|
||||
public var unknownFields: SwiftProtobuf.UnknownStorage? {
|
||||
guard hasUnknownFields else { return nil }
|
||||
return proto.unknownFields
|
||||
}
|
||||
|
||||
private init(proto: ContactDiscoveryMessages_ClientRequest) {
|
||||
self.proto = proto
|
||||
}
|
||||
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
public init(serializedData: Data) throws {
|
||||
let proto = try ContactDiscoveryMessages_ClientRequest(serializedData: serializedData)
|
||||
try self.init(proto)
|
||||
}
|
||||
|
||||
fileprivate init(_ proto: ContactDiscoveryMessages_ClientRequest) throws {
|
||||
// MARK: - Begin Validation Logic for ContactDiscoveryMessageClientRequest -
|
||||
|
||||
// MARK: - End Validation Logic for ContactDiscoveryMessageClientRequest -
|
||||
|
||||
self.init(proto: proto)
|
||||
}
|
||||
|
||||
public init(from decoder: Swift.Decoder) throws {
|
||||
let singleValueContainer = try decoder.singleValueContainer()
|
||||
let serializedData = try singleValueContainer.decode(Data.self)
|
||||
try self.init(serializedData: serializedData)
|
||||
}
|
||||
public func encode(to encoder: Swift.Encoder) throws {
|
||||
var singleValueContainer = encoder.singleValueContainer()
|
||||
try singleValueContainer.encode(try serializedData())
|
||||
}
|
||||
|
||||
public var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactDiscoveryMessageClientRequest {
|
||||
public static func builder() -> ContactDiscoveryMessageClientRequestBuilder {
|
||||
return ContactDiscoveryMessageClientRequestBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
public func asBuilder() -> ContactDiscoveryMessageClientRequestBuilder {
|
||||
var builder = ContactDiscoveryMessageClientRequestBuilder()
|
||||
if let _value = aciUakPairs {
|
||||
builder.setAciUakPairs(_value)
|
||||
}
|
||||
if let _value = prevE164List {
|
||||
builder.setPrevE164List(_value)
|
||||
}
|
||||
if let _value = newE164List {
|
||||
builder.setNewE164List(_value)
|
||||
}
|
||||
if let _value = discardE164List {
|
||||
builder.setDiscardE164List(_value)
|
||||
}
|
||||
if hasMoreComing {
|
||||
builder.setMoreComing(moreComing)
|
||||
}
|
||||
if let _value = token {
|
||||
builder.setToken(_value)
|
||||
}
|
||||
if let _value = unknownFields {
|
||||
builder.setUnknownFields(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContactDiscoveryMessageClientRequestBuilder {
|
||||
|
||||
private var proto = ContactDiscoveryMessages_ClientRequest()
|
||||
|
||||
fileprivate init() {}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setAciUakPairs(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.aciUakPairs = valueParam
|
||||
}
|
||||
|
||||
public mutating func setAciUakPairs(_ valueParam: Data) {
|
||||
proto.aciUakPairs = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setPrevE164List(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.prevE164List = valueParam
|
||||
}
|
||||
|
||||
public mutating func setPrevE164List(_ valueParam: Data) {
|
||||
proto.prevE164List = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setNewE164List(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.newE164List = valueParam
|
||||
}
|
||||
|
||||
public mutating func setNewE164List(_ valueParam: Data) {
|
||||
proto.newE164List = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setDiscardE164List(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.discardE164List = valueParam
|
||||
}
|
||||
|
||||
public mutating func setDiscardE164List(_ valueParam: Data) {
|
||||
proto.discardE164List = valueParam
|
||||
}
|
||||
|
||||
public mutating func setMoreComing(_ valueParam: Bool) {
|
||||
proto.moreComing = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setToken(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.token = valueParam
|
||||
}
|
||||
|
||||
public mutating func setToken(_ valueParam: Data) {
|
||||
proto.token = valueParam
|
||||
}
|
||||
|
||||
public mutating func setUnknownFields(_ unknownFields: SwiftProtobuf.UnknownStorage) {
|
||||
proto.unknownFields = unknownFields
|
||||
}
|
||||
|
||||
public func build() throws -> ContactDiscoveryMessageClientRequest {
|
||||
return try ContactDiscoveryMessageClientRequest(proto)
|
||||
}
|
||||
|
||||
public func buildSerializedData() throws -> Data {
|
||||
return try ContactDiscoveryMessageClientRequest(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
#if TESTABLE_BUILD
|
||||
|
||||
extension ContactDiscoveryMessageClientRequest {
|
||||
public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactDiscoveryMessageClientRequestBuilder {
|
||||
public func buildIgnoringErrors() -> ContactDiscoveryMessageClientRequest? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - ContactDiscoveryMessageClientResponse
|
||||
|
||||
public struct ContactDiscoveryMessageClientResponse: Codable, CustomDebugStringConvertible {
|
||||
|
||||
fileprivate let proto: ContactDiscoveryMessages_ClientResponse
|
||||
|
||||
public var e164PniAciTriples: Data? {
|
||||
guard hasE164PniAciTriples else {
|
||||
return nil
|
||||
}
|
||||
return proto.e164PniAciTriples
|
||||
}
|
||||
public var hasE164PniAciTriples: Bool {
|
||||
return !proto.e164PniAciTriples.isEmpty
|
||||
}
|
||||
|
||||
public var retryAfterSecs: Int32? {
|
||||
guard hasRetryAfterSecs else {
|
||||
return nil
|
||||
}
|
||||
return proto.retryAfterSecs
|
||||
}
|
||||
public var hasRetryAfterSecs: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public var token: Data? {
|
||||
guard hasToken else {
|
||||
return nil
|
||||
}
|
||||
return proto.token
|
||||
}
|
||||
public var hasToken: Bool {
|
||||
return !proto.token.isEmpty
|
||||
}
|
||||
|
||||
public var hasUnknownFields: Bool {
|
||||
return !proto.unknownFields.data.isEmpty
|
||||
}
|
||||
public var unknownFields: SwiftProtobuf.UnknownStorage? {
|
||||
guard hasUnknownFields else { return nil }
|
||||
return proto.unknownFields
|
||||
}
|
||||
|
||||
private init(proto: ContactDiscoveryMessages_ClientResponse) {
|
||||
self.proto = proto
|
||||
}
|
||||
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
public init(serializedData: Data) throws {
|
||||
let proto = try ContactDiscoveryMessages_ClientResponse(serializedData: serializedData)
|
||||
try self.init(proto)
|
||||
}
|
||||
|
||||
fileprivate init(_ proto: ContactDiscoveryMessages_ClientResponse) throws {
|
||||
// MARK: - Begin Validation Logic for ContactDiscoveryMessageClientResponse -
|
||||
|
||||
// MARK: - End Validation Logic for ContactDiscoveryMessageClientResponse -
|
||||
|
||||
self.init(proto: proto)
|
||||
}
|
||||
|
||||
public init(from decoder: Swift.Decoder) throws {
|
||||
let singleValueContainer = try decoder.singleValueContainer()
|
||||
let serializedData = try singleValueContainer.decode(Data.self)
|
||||
try self.init(serializedData: serializedData)
|
||||
}
|
||||
public func encode(to encoder: Swift.Encoder) throws {
|
||||
var singleValueContainer = encoder.singleValueContainer()
|
||||
try singleValueContainer.encode(try serializedData())
|
||||
}
|
||||
|
||||
public var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactDiscoveryMessageClientResponse {
|
||||
public static func builder() -> ContactDiscoveryMessageClientResponseBuilder {
|
||||
return ContactDiscoveryMessageClientResponseBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
public func asBuilder() -> ContactDiscoveryMessageClientResponseBuilder {
|
||||
var builder = ContactDiscoveryMessageClientResponseBuilder()
|
||||
if let _value = e164PniAciTriples {
|
||||
builder.setE164PniAciTriples(_value)
|
||||
}
|
||||
if let _value = retryAfterSecs {
|
||||
builder.setRetryAfterSecs(_value)
|
||||
}
|
||||
if let _value = token {
|
||||
builder.setToken(_value)
|
||||
}
|
||||
if let _value = unknownFields {
|
||||
builder.setUnknownFields(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContactDiscoveryMessageClientResponseBuilder {
|
||||
|
||||
private var proto = ContactDiscoveryMessages_ClientResponse()
|
||||
|
||||
fileprivate init() {}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setE164PniAciTriples(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.e164PniAciTriples = valueParam
|
||||
}
|
||||
|
||||
public mutating func setE164PniAciTriples(_ valueParam: Data) {
|
||||
proto.e164PniAciTriples = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setRetryAfterSecs(_ valueParam: Int32?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.retryAfterSecs = valueParam
|
||||
}
|
||||
|
||||
public mutating func setRetryAfterSecs(_ valueParam: Int32) {
|
||||
proto.retryAfterSecs = valueParam
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 1.0)
|
||||
public mutating func setToken(_ valueParam: Data?) {
|
||||
guard let valueParam = valueParam else { return }
|
||||
proto.token = valueParam
|
||||
}
|
||||
|
||||
public mutating func setToken(_ valueParam: Data) {
|
||||
proto.token = valueParam
|
||||
}
|
||||
|
||||
public mutating func setUnknownFields(_ unknownFields: SwiftProtobuf.UnknownStorage) {
|
||||
proto.unknownFields = unknownFields
|
||||
}
|
||||
|
||||
public func build() throws -> ContactDiscoveryMessageClientResponse {
|
||||
return try ContactDiscoveryMessageClientResponse(proto)
|
||||
}
|
||||
|
||||
public func buildSerializedData() throws -> Data {
|
||||
return try ContactDiscoveryMessageClientResponse(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
#if TESTABLE_BUILD
|
||||
|
||||
extension ContactDiscoveryMessageClientResponse {
|
||||
public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactDiscoveryMessageClientResponseBuilder {
|
||||
public func buildIgnoringErrors() -> ContactDiscoveryMessageClientResponse? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -53,8 +53,6 @@ public class TSConstants: NSObject {
|
||||
@objc
|
||||
public static var contactDiscoveryV2URL: String { shared.contactDiscoveryV2URL }
|
||||
@objc
|
||||
public static var contactDiscoveryHSMURL: String { shared.contactDiscoveryHSMURL }
|
||||
@objc
|
||||
public static var keyBackupURL: String { shared.keyBackupURL }
|
||||
@objc
|
||||
public static var storageServiceURL: String { shared.storageServiceURL }
|
||||
@ -93,10 +91,6 @@ public class TSConstants: NSObject {
|
||||
public static var contactDiscoveryEnclaveName: String { shared.contactDiscoveryMrEnclave.stringValue }
|
||||
public static var contactDiscoveryMrEnclave: MrEnclave { shared.contactDiscoveryMrEnclave }
|
||||
static var contactDiscoveryV2MrEnclave: MrEnclave { shared.contactDiscoveryV2MrEnclave }
|
||||
@objc
|
||||
public static var contactDiscoveryPublicKey: String { shared.contactDiscoveryPublicKey }
|
||||
@objc
|
||||
public static var contactDiscoveryCodeHashes: [String] { shared.contactDiscoveryCodeHashes }
|
||||
|
||||
static var keyBackupEnclave: KeyBackupEnclave { shared.keyBackupEnclave }
|
||||
static var keyBackupPreviousEnclaves: [KeyBackupEnclave] { shared.keyBackupPreviousEnclaves }
|
||||
@ -127,7 +121,6 @@ private protocol TSConstantsProtocol: AnyObject {
|
||||
var textSecureCDN2ServerURL: String { get }
|
||||
var contactDiscoverySGXURL: String { get }
|
||||
var contactDiscoveryV2URL: String { get }
|
||||
var contactDiscoveryHSMURL: String { get }
|
||||
var keyBackupURL: String { get }
|
||||
var storageServiceURL: String { get }
|
||||
var sfuURL: String { get }
|
||||
@ -151,10 +144,6 @@ private protocol TSConstantsProtocol: AnyObject {
|
||||
var contactDiscoveryMrEnclave: MrEnclave { get }
|
||||
var contactDiscoveryV2MrEnclave: MrEnclave { get }
|
||||
|
||||
// HSM Backed Contact Discovery
|
||||
var contactDiscoveryPublicKey: String { get }
|
||||
var contactDiscoveryCodeHashes: [String] { get }
|
||||
|
||||
var keyBackupEnclave: KeyBackupEnclave { get }
|
||||
var keyBackupPreviousEnclaves: [KeyBackupEnclave] { get }
|
||||
|
||||
@ -197,7 +186,6 @@ private class TSConstantsProduction: TSConstantsProtocol {
|
||||
public let textSecureCDN2ServerURL = "https://cdn2.signal.org"
|
||||
public let contactDiscoverySGXURL = "https://api.directory.signal.org"
|
||||
public let contactDiscoveryV2URL = "wss://cdsi.signal.org"
|
||||
public let contactDiscoveryHSMURL = "wss://cdsh.signal.org/discovery/"
|
||||
public let keyBackupURL = "https://api.backup.signal.org"
|
||||
public let storageServiceURL = "https://storage.signal.org"
|
||||
public let sfuURL = "https://sfu.voip.signal.org"
|
||||
@ -220,15 +208,6 @@ private class TSConstantsProduction: TSConstantsProtocol {
|
||||
public var contactDiscoveryMrEnclave = MrEnclave("74778bb0f93ae1f78c26e67152bab0bbeb693cd56d1bb9b4e9244157acc58081")
|
||||
public let contactDiscoveryV2MrEnclave = MrEnclave("ef4787a56a154ac6d009138cac17155acd23cfe4329281252365dd7c252e7fbf")
|
||||
|
||||
public var contactDiscoveryPublicKey: String {
|
||||
owsFailDebug("CDSH unsupported in production")
|
||||
return ""
|
||||
}
|
||||
public var contactDiscoveryCodeHashes: [String] {
|
||||
owsFailDebug("CDSH unsupported in production")
|
||||
return []
|
||||
}
|
||||
|
||||
public let keyBackupEnclave = KeyBackupEnclave(
|
||||
name: "e18376436159cda3ad7a45d9320e382e4a497f26b0dca34d8eab0bd0139483b5",
|
||||
mrenclave: MrEnclave("45627094b2ea4a66f4cf0b182858a8dcf4b8479122c3820fe7fd0551a6d4cf5c"),
|
||||
@ -266,7 +245,6 @@ private class TSConstantsStaging: TSConstantsProtocol {
|
||||
public let textSecureCDN2ServerURL = "https://cdn2-staging.signal.org"
|
||||
public let contactDiscoverySGXURL = "https://api-staging.directory.signal.org"
|
||||
public let contactDiscoveryV2URL = "wss://cdsi.staging.signal.org"
|
||||
public let contactDiscoveryHSMURL = "wss://cdsh.staging.signal.org/discovery/"
|
||||
public let keyBackupURL = "https://api-staging.backup.signal.org"
|
||||
public let storageServiceURL = "https://storage-staging.signal.org"
|
||||
public let sfuURL = "https://sfu.staging.voip.signal.org"
|
||||
@ -292,11 +270,6 @@ private class TSConstantsStaging: TSConstantsProtocol {
|
||||
public var contactDiscoveryMrEnclave = MrEnclave("74778bb0f93ae1f78c26e67152bab0bbeb693cd56d1bb9b4e9244157acc58081")
|
||||
public let contactDiscoveryV2MrEnclave = MrEnclave("ef4787a56a154ac6d009138cac17155acd23cfe4329281252365dd7c252e7fbf")
|
||||
|
||||
public let contactDiscoveryPublicKey = "2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74"
|
||||
public let contactDiscoveryCodeHashes = [
|
||||
"2f79dc6c1599b71c70fc2d14f3ea2e3bc65134436eb87011c88845b137af673a"
|
||||
]
|
||||
|
||||
public let keyBackupEnclave = KeyBackupEnclave(
|
||||
name: "39963b736823d5780be96ab174869a9499d56d66497aa8f9b2244f777ebc366b",
|
||||
mrenclave: MrEnclave("45627094b2ea4a66f4cf0b182858a8dcf4b8479122c3820fe7fd0551a6d4cf5c"),
|
||||
|
||||
@ -89,9 +89,6 @@ public class FeatureFlags: BaseFlags {
|
||||
@objc
|
||||
public static let canUseNativeWebsocket = true
|
||||
|
||||
@objc
|
||||
public static let hsmContactDiscovery = false
|
||||
|
||||
public static let shouldUseRemoteConfigForReceivingGiftBadges = true
|
||||
|
||||
public static let isPrerelease = build.includes(.beta)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user