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