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