xref: /aosp_15_r20/external/cronet/crypto/p224_spake.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef CRYPTO_P224_SPAKE_H_
6*6777b538SAndroid Build Coastguard Worker #define CRYPTO_P224_SPAKE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <string>
11*6777b538SAndroid Build Coastguard Worker #include <string_view>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "crypto/sha2.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace crypto {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted
19*6777b538SAndroid Build Coastguard Worker // Key Exchange. It allows two parties that have a secret common
20*6777b538SAndroid Build Coastguard Worker // password to establish a common secure key by exchanging messages
21*6777b538SAndroid Build Coastguard Worker // over an insecure channel without disclosing the password.
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // The password can be low entropy as authenticating with an attacker only
24*6777b538SAndroid Build Coastguard Worker // gives the attacker a one-shot password oracle. No other information about
25*6777b538SAndroid Build Coastguard Worker // the password is leaked. (However, you must be sure to limit the number of
26*6777b538SAndroid Build Coastguard Worker // permitted authentication attempts otherwise they get many one-shot oracles.)
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // The protocol requires several RTTs (actually two, but you shouldn't assume
29*6777b538SAndroid Build Coastguard Worker // that.) To use the object, call GetNextMessage() and pass that message to the
30*6777b538SAndroid Build Coastguard Worker // peer. Get a message from the peer and feed it into ProcessMessage. Then
31*6777b538SAndroid Build Coastguard Worker // examine the return value of ProcessMessage:
32*6777b538SAndroid Build Coastguard Worker //   kResultPending: Another round is required. Call GetNextMessage and repeat.
33*6777b538SAndroid Build Coastguard Worker //   kResultFailed: The authentication has failed. You can get a human readable
34*6777b538SAndroid Build Coastguard Worker //       error message by calling error().
35*6777b538SAndroid Build Coastguard Worker //   kResultSuccess: The authentication was successful.
36*6777b538SAndroid Build Coastguard Worker //
37*6777b538SAndroid Build Coastguard Worker // In each exchange, each peer always sends a message.
38*6777b538SAndroid Build Coastguard Worker class CRYPTO_EXPORT P224EncryptedKeyExchange {
39*6777b538SAndroid Build Coastguard Worker  public:
40*6777b538SAndroid Build Coastguard Worker   enum Result {
41*6777b538SAndroid Build Coastguard Worker     kResultPending,
42*6777b538SAndroid Build Coastguard Worker     kResultFailed,
43*6777b538SAndroid Build Coastguard Worker     kResultSuccess,
44*6777b538SAndroid Build Coastguard Worker   };
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker   // PeerType's values are named client and server due to convention. But
47*6777b538SAndroid Build Coastguard Worker   // they could be called "A" and "B" as far as the protocol is concerned so
48*6777b538SAndroid Build Coastguard Worker   // long as the two parties don't both get the same label.
49*6777b538SAndroid Build Coastguard Worker   enum PeerType {
50*6777b538SAndroid Build Coastguard Worker     kPeerTypeClient,
51*6777b538SAndroid Build Coastguard Worker     kPeerTypeServer,
52*6777b538SAndroid Build Coastguard Worker   };
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   // peer_type: the type of the local authentication party.
55*6777b538SAndroid Build Coastguard Worker   // password: secret session password. Both parties to the
56*6777b538SAndroid Build Coastguard Worker   //     authentication must pass the same value. For the case of a
57*6777b538SAndroid Build Coastguard Worker   //     TLS connection, see RFC 5705.
58*6777b538SAndroid Build Coastguard Worker   P224EncryptedKeyExchange(PeerType peer_type, std::string_view password);
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   // GetNextMessage returns a byte string which must be passed to the other
61*6777b538SAndroid Build Coastguard Worker   // party in the authentication.
62*6777b538SAndroid Build Coastguard Worker   const std::string& GetNextMessage();
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   // ProcessMessage processes a message which must have been generated by a
65*6777b538SAndroid Build Coastguard Worker   // call to GetNextMessage() by the other party.
66*6777b538SAndroid Build Coastguard Worker   Result ProcessMessage(std::string_view message);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   // In the event that ProcessMessage() returns kResultFailed, error will
69*6777b538SAndroid Build Coastguard Worker   // return a human readable error message.
70*6777b538SAndroid Build Coastguard Worker   const std::string& error() const;
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   // The key established as result of the key exchange. Must be called
73*6777b538SAndroid Build Coastguard Worker   // at then end after ProcessMessage() returns kResultSuccess.
74*6777b538SAndroid Build Coastguard Worker   const std::string& GetKey() const;
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   // The key established as result of the key exchange. Can be called after
77*6777b538SAndroid Build Coastguard Worker   // the first ProcessMessage()
78*6777b538SAndroid Build Coastguard Worker   const std::string& GetUnverifiedKey() const;
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker  private:
81*6777b538SAndroid Build Coastguard Worker   // The authentication state machine is very simple and each party proceeds
82*6777b538SAndroid Build Coastguard Worker   // through each of these states, in order.
83*6777b538SAndroid Build Coastguard Worker   enum State {
84*6777b538SAndroid Build Coastguard Worker     kStateInitial,
85*6777b538SAndroid Build Coastguard Worker     kStateRecvDH,
86*6777b538SAndroid Build Coastguard Worker     kStateSendHash,
87*6777b538SAndroid Build Coastguard Worker     kStateRecvHash,
88*6777b538SAndroid Build Coastguard Worker     kStateDone,
89*6777b538SAndroid Build Coastguard Worker   };
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues);
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   void Init();
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   // Sets internal random scalar. Should be used by tests only.
96*6777b538SAndroid Build Coastguard Worker   void SetXForTesting(const std::string& x);
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   State state_;
99*6777b538SAndroid Build Coastguard Worker   const bool is_server_;
100*6777b538SAndroid Build Coastguard Worker   // next_message_ contains a value for GetNextMessage() to return.
101*6777b538SAndroid Build Coastguard Worker   std::string next_message_;
102*6777b538SAndroid Build Coastguard Worker   std::string error_;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker   // CalculateHash computes the verification hash for the given peer and writes
105*6777b538SAndroid Build Coastguard Worker   // |kSHA256Length| bytes at |out_digest|.
106*6777b538SAndroid Build Coastguard Worker   void CalculateHash(PeerType peer_type,
107*6777b538SAndroid Build Coastguard Worker                      const std::string& client_masked_dh,
108*6777b538SAndroid Build Coastguard Worker                      const std::string& server_masked_dh,
109*6777b538SAndroid Build Coastguard Worker                      const std::string& k,
110*6777b538SAndroid Build Coastguard Worker                      uint8_t* out_digest);
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   // kScalarBytes is the number of bytes in a P-224 scalar.
113*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kScalarBytes = 28;
114*6777b538SAndroid Build Coastguard Worker   // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc
115*6777b538SAndroid Build Coastguard Worker   // file).
116*6777b538SAndroid Build Coastguard Worker   uint8_t x_[kScalarBytes];
117*6777b538SAndroid Build Coastguard Worker   // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32_t,
118*6777b538SAndroid Build Coastguard Worker   // big-endian length prefix (see paper referenced in .cc file).
119*6777b538SAndroid Build Coastguard Worker   uint8_t pw_[kScalarBytes];
120*6777b538SAndroid Build Coastguard Worker   // expected_authenticator_ is used to store the hash value expected from the
121*6777b538SAndroid Build Coastguard Worker   // other party.
122*6777b538SAndroid Build Coastguard Worker   uint8_t expected_authenticator_[kSHA256Length];
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   std::string key_;
125*6777b538SAndroid Build Coastguard Worker };
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker }  // namespace crypto
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker #endif  // CRYPTO_P224_SPAKE_H_
130