p224_spake.h 4.6 KB

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