Split KeyExchange into synchronous and asynchronous variants

As part of the implementation of go/leto-II-design, an asynchronous interface was added to the KeyExchange class, to allow an implementation which would make an RPC to a service holding the private key.  This fit awkwardly into the existing code, and we intended it as a short-term patch until we could come up with a better separation of concerns.

This CL improves matters by splitting the KeyExchange class into two.  The AsyncKeyExchange interface has only an asynchronous interface.  SyncKeyExchange has both synchronous and asynchronous interfaces, with the latter implemented in terms of the former.  The existing "local" key-exchange classes inherit from SyncKeyExchange.  Handshaking code which may or may not need to talk to Leto uses the AsyncKeyExchange uniformly, but depending on whether Leto is enabled or not, the concrete objects being used might be local or remote.

This CL also removes the "Factory" pattern previously used for creating KeyExchange objects.  It required a bunch of boilerplate and provided little benefit.

gfe-relnote: no-op refactoring in the area of QUIC handshakes.  No functional change intended, not flag-protected.
PiperOrigin-RevId: 238508479
Change-Id: Ib5ca6ae5afbdcb712c7d2f86a4d272ef168b90f3
diff --git a/quic/core/crypto/key_exchange.h b/quic/core/crypto/key_exchange.h
index 7d4f76d..c695523 100644
--- a/quic/core/crypto/key_exchange.h
+++ b/quic/core/crypto/key_exchange.h
@@ -16,28 +16,12 @@
 
 class QuicRandom;
 
-// KeyExchange is an abstract class that provides an interface to a
-// key-exchange primitive.
-class QUIC_EXPORT_PRIVATE KeyExchange {
+// Interface for a Diffie-Hellman key exchange with an asynchronous interface.
+// This allows for implementations which hold the private key locally, as well
+// as ones which make an RPC to an external key-exchange service.
+class QUIC_EXPORT_PRIVATE AsynchronousKeyExchange {
  public:
-  virtual ~KeyExchange() {}
-
-  class Factory {
-   public:
-    virtual ~Factory() = default;
-    Factory(const Factory&) = delete;
-    Factory& operator=(const Factory&) = delete;
-
-    // Generates a new public, private key pair. (This is intended for
-    // servers that need to generate forward-secure keys.)
-    virtual std::unique_ptr<KeyExchange> Create(QuicRandom* rand) const = 0;
-
-    // Returns the tag value that identifies this key exchange function.
-    virtual QuicTag tag() const = 0;
-
-   protected:
-    Factory() = default;
-  };
+  virtual ~AsynchronousKeyExchange() = default;
 
   // Callback base class for receiving the results of an async call to
   // CalculateSharedKeys.
@@ -46,11 +30,11 @@
     Callback() = default;
     virtual ~Callback() = default;
 
-    // Invoked upon completion of CalculateSharedKeys.
+    // Invoked upon completion of CalculateSharedKeysAsync.
     //
     // |ok| indicates whether the operation completed successfully.  If false,
-    // then the value of |shared_key| passed in to CalculateSharedKey is
-    // undefined.
+    // then the value pointed to by |shared_key| passed in to
+    // CalculateSharedKeyAsync is undefined.
     virtual void Run(bool ok) = 0;
 
    private:
@@ -58,30 +42,64 @@
     Callback& operator=(const Callback&) = delete;
   };
 
-  // Get a reference to the singleton Factory object for this KeyExchange type.
-  virtual const Factory& GetFactory() const = 0;
+  // CalculateSharedKey computes the shared key between a private key which is
+  // conceptually owned by this object (though it may not be physically located
+  // in this process) and a public value from the peer.  Callers should expect
+  // that |callback| might be invoked synchronously.  Results will be written
+  // into |*shared_key|.
+  virtual void CalculateSharedKeyAsync(
+      QuicStringPiece peer_public_value,
+      std::string* shared_key,
+      std::unique_ptr<Callback> callback) const = 0;
 
-  // CalculateSharedKey computes the shared key between the local private key
-  // (which is implicitly known by a KeyExchange object) and a public value
-  // from the peer.
-  virtual bool CalculateSharedKey(QuicStringPiece peer_public_value,
-                                  std::string* shared_key) const = 0;
+  // Tag indicating the key-exchange algorithm this object will use.
+  virtual QuicTag type() const = 0;
+};
 
-  // CalculateSharedKey computes the shared key between the local private key
-  // (which is may not be locally known to a KeyExchange object) and a public
-  // value from the peer.
-  // Callers should expect that |callback| might be invoked synchronously.
-  virtual void CalculateSharedKey(QuicStringPiece peer_public_value,
-                                  std::string* shared_key,
-                                  std::unique_ptr<Callback> callback) const = 0;
+// Interface for a Diffie-Hellman key exchange with both synchronous and
+// asynchronous interfaces.  Only implementations which hold the private key
+// locally should implement this interface.
+class QUIC_EXPORT_PRIVATE SynchronousKeyExchange
+    : public AsynchronousKeyExchange {
+ public:
+  virtual ~SynchronousKeyExchange() = default;
+
+  // AyncKeyExchange API.  Note that this method is marked 'final.'  Subclasses
+  // should implement CalculateSharedKeySync only.
+  void CalculateSharedKeyAsync(QuicStringPiece peer_public_value,
+                               std::string* shared_key,
+                               std::unique_ptr<Callback> callback) const final {
+    const bool ok = CalculateSharedKeySync(peer_public_value, shared_key);
+    callback->Run(ok);
+  }
+
+  // CalculateSharedKey computes the shared key between a local private key and
+  // a public value from the peer.  Results will be written into |*shared_key|.
+  virtual bool CalculateSharedKeySync(QuicStringPiece peer_public_value,
+                                      std::string* shared_key) const = 0;
 
   // public_value returns the local public key which can be sent to a peer in
   // order to complete a key exchange. The returned QuicStringPiece is a
-  // reference to a member of the KeyExchange and is only valid for as long as
-  // the KeyExchange exists.
+  // reference to a member of this object and is only valid for as long as it
+  // exists.
   virtual QuicStringPiece public_value() const = 0;
 };
 
+// Create a SynchronousKeyExchange object which will use a keypair generated
+// from |private_key|, and a key-exchange algorithm specified by |type|, which
+// must be one of {kC255, kC256}.  Returns nullptr if |private_key| or |type| is
+// invalid.
+std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
+    QuicTag type,
+    QuicStringPiece private_key);
+
+// Create a SynchronousKeyExchange object which will use a keypair generated
+// from |rand|, and a key-exchange algorithm specified by |type|, which must be
+// one of {kC255, kC256}.  Returns nullptr if |type| is invalid.
+std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
+    QuicTag type,
+    QuicRandom* rand);
+
 }  // namespace quic
 
 #endif  // QUICHE_QUIC_CORE_CRYPTO_KEY_EXCHANGE_H_