diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-22 01:29:37 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-22 01:29:37 +0000 |
commit | d9a262df8efd514cb91a99e38fbfd59926d93903 (patch) | |
tree | a0c6eed733fb254a9a4dee78b5d675986443d354 /crypto/p224_spake.h | |
parent | 023d8247d6efbd4fac3cf9f7bfa8d2204c268c5a (diff) | |
download | chromium_src-d9a262df8efd514cb91a99e38fbfd59926d93903.zip chromium_src-d9a262df8efd514cb91a99e38fbfd59926d93903.tar.gz chromium_src-d9a262df8efd514cb91a99e38fbfd59926d93903.tar.bz2 |
net: add low-entropy, shared secret authentication protocol.
BUG=none
TEST=crypto_unittests
Review URL: http://codereview.chromium.org/8499032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111070 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'crypto/p224_spake.h')
-rw-r--r-- | crypto/p224_spake.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/crypto/p224_spake.h b/crypto/p224_spake.h new file mode 100644 index 0000000..0441efb --- /dev/null +++ b/crypto/p224_spake.h @@ -0,0 +1,113 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_P224_SPAKE_H_ +#define CRYPTO_P224_SPAKE_H_ +#pragma once + +#include <base/string_piece.h> +#include <crypto/p224.h> +#include <crypto/sha2.h> + +namespace crypto { + +// P224EncryptedKeyExchange provides a means to authenticate an +// encrypted transport using a low-entropy, shared secret. +// +// You need a value derived from the master secret of the connection in order +// to bind the authentication to the encrypted channel. It's the |session| +// argument to the constructor and can be of any length. +// +// The password can be low entropy as authenticating with an attacker only +// gives the attacker a one-shot password oracle. No other information about +// the password is leaked. (However, you must be sure to limit the number of +// permitted authentication attempts otherwise they get many one-shot oracles.) +// +// The protocol requires several RTTs (actually two, but you shouldn't assume +// that.) To use the object, call GetMessage() and pass that message to the +// peer. Get a message from the peer and feed it into ProcessMessage. Then +// examine the return value of ProcessMessage: +// kResultPending: Another round is required. Call GetMessage and repeat. +// kResultFailed: The authentication has failed. You can get a human readable +// error message by calling error(). +// kResultSuccess: The authentication was successful. +// +// In each exchange, each peer always sends a message. +class CRYPTO_EXPORT P224EncryptedKeyExchange { + public: + enum Result { + kResultPending, + kResultFailed, + kResultSuccess, + }; + + // PeerType's values are named client and server due to convention. But + // they could be called "A" and "B" as far as the protocol is concerned so + // long as the two parties don't both get the same label. + enum PeerType { + kPeerTypeClient, + kPeerTypeServer, + }; + + // peer_type: the type of the local authentication party. + // password: a, possibly low-entropy, mutually known password. + // session: a value securely derived from the connection's master secret. + // Both parties to the authentication must pass the same value. For the + // case of a TLS connection, see RFC 5705. + P224EncryptedKeyExchange(PeerType peer_type, + const base::StringPiece& password, + const base::StringPiece& session); + + // GetMessage returns a byte string which must be passed to the other party + // in the authentication. + const std::string& GetMessage(); + + // ProcessMessage processes a message which must have been generated by a + // call to GetMessage() by the other party. + Result ProcessMessage(const base::StringPiece& message); + + // In the event that ProcessMessage() returns kResultFailed, error will + // return a human readable error message. + const std::string& error() const; + + private: + // The authentication state machine is very simple and each party proceeds + // through each of these states, in order. + enum State { + kStateInitial, + kStateRecvDH, + kStateSendHash, + kStateRecvHash, + kStateDone, + }; + + State state_; + const bool is_server_; + // next_message_ contains a value for GetMessage() to return. + std::string next_message_; + std::string error_; + + // CalculateHash computes the verification hash for the given peer and writes + // |kSHA256Length| bytes at |out_digest|. + void CalculateHash( + PeerType peer_type, + const std::string& client_masked_dh, + const std::string& server_masked_dh, + const std::string& k, + uint8* out_digest); + + // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc + // file). + uint8 x_[p224::kScalarBytes]; + // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32, + // big-endian length prefix (see paper refereneced in .cc file). + uint8 pw_[p224::kScalarBytes]; + // expected_authenticator_ is used to store the hash value expected from the + // other party. + uint8 expected_authenticator_[kSHA256Length]; +}; + +} // namespace crypto + +#endif // CRYPTO_P224_SPAKE_H_ |