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