xref: /aosp_15_r20/external/federated-compute/fcp/secagg/client/secagg_client.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2018 Google LLC
3*14675a02SAndroid Build Coastguard Worker  *
4*14675a02SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker  *
8*14675a02SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker  *
10*14675a02SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker  * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker  */
16*14675a02SAndroid Build Coastguard Worker 
17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_SECAGG_CLIENT_SECAGG_CLIENT_H_
18*14675a02SAndroid Build Coastguard Worker #define FCP_SECAGG_CLIENT_SECAGG_CLIENT_H_
19*14675a02SAndroid Build Coastguard Worker 
20*14675a02SAndroid Build Coastguard Worker #include <memory>
21*14675a02SAndroid Build Coastguard Worker #include <string>
22*14675a02SAndroid Build Coastguard Worker #include <vector>
23*14675a02SAndroid Build Coastguard Worker 
24*14675a02SAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
26*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/client/secagg_client_state.h"
27*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/client/send_to_server_interface.h"
28*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/client/state_transition_listener_interface.h"
29*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/aes_prng_factory.h"
30*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/async_abort.h"
31*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/input_vector_specification.h"
32*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/prng.h"
33*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/secagg_messages.pb.h"
34*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/secagg_vector.h"
35*14675a02SAndroid Build Coastguard Worker 
36*14675a02SAndroid Build Coastguard Worker namespace fcp {
37*14675a02SAndroid Build Coastguard Worker namespace secagg {
38*14675a02SAndroid Build Coastguard Worker 
39*14675a02SAndroid Build Coastguard Worker // Represents a client for the secure aggregation protocol. Each instance of
40*14675a02SAndroid Build Coastguard Worker // this class performs just *one* session of the protocol.
41*14675a02SAndroid Build Coastguard Worker //
42*14675a02SAndroid Build Coastguard Worker // To create a new instance, use the public constructor. The Start method can be
43*14675a02SAndroid Build Coastguard Worker // used to produce the first message of the protocol, the SetInput method sets
44*14675a02SAndroid Build Coastguard Worker // the input for this client and the ReceiveMessage method is used to process
45*14675a02SAndroid Build Coastguard Worker // incoming messages from the server.
46*14675a02SAndroid Build Coastguard Worker //
47*14675a02SAndroid Build Coastguard Worker // The class is thread-safe, but will deadlock if accessed reentrantly from
48*14675a02SAndroid Build Coastguard Worker // the SendToServerInterface callback.
49*14675a02SAndroid Build Coastguard Worker //
50*14675a02SAndroid Build Coastguard Worker // Functions are marked virtual for mockability.  Additional virtual attributes
51*14675a02SAndroid Build Coastguard Worker // should be added as needed by tests.
52*14675a02SAndroid Build Coastguard Worker 
53*14675a02SAndroid Build Coastguard Worker class SecAggClient {
54*14675a02SAndroid Build Coastguard Worker  public:
55*14675a02SAndroid Build Coastguard Worker   // Creates a new instance of the client.
56*14675a02SAndroid Build Coastguard Worker   //
57*14675a02SAndroid Build Coastguard Worker   // max_neighbors_expected is the upper bound on the total number of neighbors
58*14675a02SAndroid Build Coastguard Worker   // this client may interact with. If the server tries to start a protocol
59*14675a02SAndroid Build Coastguard Worker   // session with more than this many neighbors, this client will abort.
60*14675a02SAndroid Build Coastguard Worker   //
61*14675a02SAndroid Build Coastguard Worker   // minimum_surviving_neighbors_for_reconstruction is the threshold lower bound
62*14675a02SAndroid Build Coastguard Worker   // on the number of neighbors participating. If there are ever fewer than this
63*14675a02SAndroid Build Coastguard Worker   // number of remaining neighbors in the protocol, this client will abort.
64*14675a02SAndroid Build Coastguard Worker   //
65*14675a02SAndroid Build Coastguard Worker   // input_vector_specs must contain one InputVectorSpecification for each input
66*14675a02SAndroid Build Coastguard Worker   // vector which the protocol will aggregate.  This may optionally be moved
67*14675a02SAndroid Build Coastguard Worker   // from using std::move(caller_input_vector_specs).
68*14675a02SAndroid Build Coastguard Worker   //
69*14675a02SAndroid Build Coastguard Worker   // prng should always be an instance of CryptoRandPrng, except as needed for
70*14675a02SAndroid Build Coastguard Worker   // testing purposes. The client will consume prng, taking ownership of it.
71*14675a02SAndroid Build Coastguard Worker   //
72*14675a02SAndroid Build Coastguard Worker   // sender is used by the client to send messages to the server. The client
73*14675a02SAndroid Build Coastguard Worker   // will consume sender, taking ownership of it.
74*14675a02SAndroid Build Coastguard Worker   //
75*14675a02SAndroid Build Coastguard Worker   // transition_listener is used to trigger state transition events, used for
76*14675a02SAndroid Build Coastguard Worker   // logging.
77*14675a02SAndroid Build Coastguard Worker   //
78*14675a02SAndroid Build Coastguard Worker   // prng_factory is a pointer to an instance of a subclass of AesPrngFactory.
79*14675a02SAndroid Build Coastguard Worker   // The type of prng_factory must be consistent with the one used on the
80*14675a02SAndroid Build Coastguard Worker   // server.
81*14675a02SAndroid Build Coastguard Worker   //
82*14675a02SAndroid Build Coastguard Worker   // async_abort_for_test, optionally, allows the caller to reset the abort
83*14675a02SAndroid Build Coastguard Worker   // signal. This is used to exhaustively test all abort paths, and should not
84*14675a02SAndroid Build Coastguard Worker   // be used in production; specifically, if this paramter is not nullptr,
85*14675a02SAndroid Build Coastguard Worker   // Abort() will no longer abort a state-in-progress; it will only abort across
86*14675a02SAndroid Build Coastguard Worker   // state transitions.
87*14675a02SAndroid Build Coastguard Worker   SecAggClient(
88*14675a02SAndroid Build Coastguard Worker       int max_neighbors_expected,
89*14675a02SAndroid Build Coastguard Worker       int minimum_surviving_neighbors_for_reconstruction,
90*14675a02SAndroid Build Coastguard Worker       std::vector<InputVectorSpecification> input_vector_specs,
91*14675a02SAndroid Build Coastguard Worker       std::unique_ptr<SecurePrng> prng,
92*14675a02SAndroid Build Coastguard Worker       std::unique_ptr<SendToServerInterface> sender,
93*14675a02SAndroid Build Coastguard Worker       std::unique_ptr<StateTransitionListenerInterface> transition_listener,
94*14675a02SAndroid Build Coastguard Worker       std::unique_ptr<AesPrngFactory> prng_factory,
95*14675a02SAndroid Build Coastguard Worker       std::atomic<std::string*>* abort_signal_for_test = nullptr);
96*14675a02SAndroid Build Coastguard Worker   virtual ~SecAggClient() = default;
97*14675a02SAndroid Build Coastguard Worker 
98*14675a02SAndroid Build Coastguard Worker   // Disallow copy and move.
99*14675a02SAndroid Build Coastguard Worker   SecAggClient(const SecAggClient&) = delete;
100*14675a02SAndroid Build Coastguard Worker   SecAggClient& operator=(const SecAggClient&) = delete;
101*14675a02SAndroid Build Coastguard Worker 
102*14675a02SAndroid Build Coastguard Worker   // Initiates the protocol by computing its first message and sending it to
103*14675a02SAndroid Build Coastguard Worker   // the server. This method should only be called once. The output will be OK
104*14675a02SAndroid Build Coastguard Worker   // unless it is called more than once.
105*14675a02SAndroid Build Coastguard Worker   virtual Status Start();
106*14675a02SAndroid Build Coastguard Worker 
107*14675a02SAndroid Build Coastguard Worker   // Makes this client abort the protocol and sends a message to notify the
108*14675a02SAndroid Build Coastguard Worker   // server. All the state is erased. A new instance of SecAggClient will have
109*14675a02SAndroid Build Coastguard Worker   // to be created to restart the protocol.
110*14675a02SAndroid Build Coastguard Worker   //
111*14675a02SAndroid Build Coastguard Worker   // The status will be OK unless the protocol was already completed or aborted.
112*14675a02SAndroid Build Coastguard Worker   Status Abort();
113*14675a02SAndroid Build Coastguard Worker 
114*14675a02SAndroid Build Coastguard Worker   // Makes this client abort the protocol and sends a message to notify the
115*14675a02SAndroid Build Coastguard Worker   // server. All the state is erased. A new instance of SecAggClient will have
116*14675a02SAndroid Build Coastguard Worker   // to be created to restart the protocol.
117*14675a02SAndroid Build Coastguard Worker   //
118*14675a02SAndroid Build Coastguard Worker   // The specified reason for aborting will be sent to the server and logged.
119*14675a02SAndroid Build Coastguard Worker   //
120*14675a02SAndroid Build Coastguard Worker   // The status will be OK unless the protocol was already completed or aborted.
121*14675a02SAndroid Build Coastguard Worker   Status Abort(const std::string& reason);
122*14675a02SAndroid Build Coastguard Worker 
123*14675a02SAndroid Build Coastguard Worker   // Sets the input of this client for this protocol session. This method should
124*14675a02SAndroid Build Coastguard Worker   // only be called once.
125*14675a02SAndroid Build Coastguard Worker   //
126*14675a02SAndroid Build Coastguard Worker   // If the input does not match the format laid out in input_vector_specs,
127*14675a02SAndroid Build Coastguard Worker   // this will return INVALID_ARGUMENT. If SetInput has already been called or
128*14675a02SAndroid Build Coastguard Worker   // if the client is in an aborted or completed state, this will return
129*14675a02SAndroid Build Coastguard Worker   // FAILED_PRECONDITION. Otherwise returns OK.
130*14675a02SAndroid Build Coastguard Worker   Status SetInput(std::unique_ptr<SecAggVectorMap> input_map);
131*14675a02SAndroid Build Coastguard Worker 
132*14675a02SAndroid Build Coastguard Worker   // Returns a string uniquely describing the current state of the client's FSM.
133*14675a02SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT std::string State() const;
134*14675a02SAndroid Build Coastguard Worker 
135*14675a02SAndroid Build Coastguard Worker   // Returns true if the client has aborted the protocol, false else.
136*14675a02SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT bool IsAborted() const;
137*14675a02SAndroid Build Coastguard Worker 
138*14675a02SAndroid Build Coastguard Worker   // Returns true if the client has successfully completed the protocol,
139*14675a02SAndroid Build Coastguard Worker   // false else.
140*14675a02SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT bool IsCompletedSuccessfully() const;
141*14675a02SAndroid Build Coastguard Worker 
142*14675a02SAndroid Build Coastguard Worker   // Returns a string describing the reason that the client aborted.
143*14675a02SAndroid Build Coastguard Worker   // If the client has not actually aborted, returns an error Status with code
144*14675a02SAndroid Build Coastguard Worker   // PRECONDITION_FAILED.
145*14675a02SAndroid Build Coastguard Worker   ABSL_MUST_USE_RESULT StatusOr<std::string> ErrorMessage() const;
146*14675a02SAndroid Build Coastguard Worker 
147*14675a02SAndroid Build Coastguard Worker   // Used to process an incoming message from the server. This method uses the
148*14675a02SAndroid Build Coastguard Worker   // SendToServerInterface passed to the constructor to send the response
149*14675a02SAndroid Build Coastguard Worker   // directly to the server.
150*14675a02SAndroid Build Coastguard Worker   //
151*14675a02SAndroid Build Coastguard Worker   // The output will be true if the client is still active, or false if the
152*14675a02SAndroid Build Coastguard Worker   // client is now in a terminal state. The output will be a failure status if
153*14675a02SAndroid Build Coastguard Worker   // the client did not process the message because it was in a terminal state,
154*14675a02SAndroid Build Coastguard Worker   // or because the message was the wrong type.
155*14675a02SAndroid Build Coastguard Worker   StatusOr<bool> ReceiveMessage(const ServerToClientWrapperMessage& incoming);
156*14675a02SAndroid Build Coastguard Worker 
157*14675a02SAndroid Build Coastguard Worker  private:
158*14675a02SAndroid Build Coastguard Worker   mutable absl::Mutex mu_;
159*14675a02SAndroid Build Coastguard Worker 
160*14675a02SAndroid Build Coastguard Worker   std::atomic<std::string*> abort_signal_;
161*14675a02SAndroid Build Coastguard Worker   AsyncAbort async_abort_;
162*14675a02SAndroid Build Coastguard Worker 
163*14675a02SAndroid Build Coastguard Worker   // The internal State object, containing details about this client's current
164*14675a02SAndroid Build Coastguard Worker   // state.
165*14675a02SAndroid Build Coastguard Worker   std::unique_ptr<SecAggClientState> state_ ABSL_GUARDED_BY(mu_);
166*14675a02SAndroid Build Coastguard Worker };
167*14675a02SAndroid Build Coastguard Worker 
168*14675a02SAndroid Build Coastguard Worker }  // namespace secagg
169*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
170*14675a02SAndroid Build Coastguard Worker 
171*14675a02SAndroid Build Coastguard Worker #endif  // FCP_SECAGG_CLIENT_SECAGG_CLIENT_H_
172