Skip to content

Commit

Permalink
Added unittest to make sure future changes in P224EncryptedKeyExchang…
Browse files Browse the repository at this point in the history
…e don't change output.

External implementations already expect this values.

BUG=438470
R=agl@chromium.org, gene@chromium.org

Review URL: https://codereview.chromium.org/789743002

Cr-Commit-Position: refs/heads/master@{#307654}
  • Loading branch information
vitalybuka committed Dec 10, 2014
1 parent ef3b866 commit bd85b56
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
20 changes: 16 additions & 4 deletions crypto/p224_spake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <crypto/p224_spake.h>

#include <algorithm>

#include <base/logging.h>
#include <crypto/p224.h>
#include <crypto/random.h>
Expand Down Expand Up @@ -105,14 +107,18 @@ P224EncryptedKeyExchange::P224EncryptedKeyExchange(
// x_ is a random scalar.
RandBytes(x_, sizeof(x_));

// X = g**x_
p224::Point X;
p224::ScalarBaseMult(x_, &X);

// Calculate |password| hash to get SPAKE password value.
SHA256HashString(std::string(password.data(), password.length()),
pw_, sizeof(pw_));

Init();
}

void P224EncryptedKeyExchange::Init() {
// X = g**x_
p224::Point X;
p224::ScalarBaseMult(x_, &X);

// The client masks the Diffie-Hellman value, X, by adding M**pw and the
// server uses N**pw.
p224::Point MNpw;
Expand Down Expand Up @@ -253,4 +259,10 @@ const std::string& P224EncryptedKeyExchange::GetUnverifiedKey() const {
return key_;
}

void P224EncryptedKeyExchange::SetXForTesting(const std::string& x) {
memset(&x_, 0, sizeof(x_));
memcpy(&x_, x.data(), std::min(x.size(), sizeof(x_)));
Init();
}

} // namespace crypto
12 changes: 10 additions & 2 deletions crypto/p224_spake.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef CRYPTO_P224_SPAKE_H_
#define CRYPTO_P224_SPAKE_H_

#include <base/gtest_prod_util.h>
#include <base/strings/string_piece.h>
#include <crypto/p224.h>
#include <crypto/sha2.h>
Expand All @@ -14,7 +15,7 @@ namespace crypto {
// P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted
// Key Exchange. It allows two parties that have a secret common
// password to establish a common secure key by exchanging messages
// over unsecure channel without disclosing the password.
// over an insecure channel without disclosing the password.
//
// The password can be low entropy as authenticating with an attacker only
// gives the attacker a one-shot password oracle. No other information about
Expand Down Expand Up @@ -85,6 +86,13 @@ class CRYPTO_EXPORT P224EncryptedKeyExchange {
kStateDone,
};

FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues);

void Init();

// Sets internal random scalar. Should be used by tests only.
void SetXForTesting(const std::string& x);

State state_;
const bool is_server_;
// next_message_ contains a value for GetMessage() to return.
Expand All @@ -104,7 +112,7 @@ class CRYPTO_EXPORT P224EncryptedKeyExchange {
// 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).
// big-endian length prefix (see paper referenced in .cc file).
uint8 pw_[p224::kScalarBytes];
// expected_authenticator_ is used to store the hash value expected from the
// other party.
Expand Down
44 changes: 43 additions & 1 deletion crypto/p224_spake_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/p224_spake.h"

#include <string>
#include <crypto/p224_spake.h>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace crypto {

namespace {

std::string HexEncodeString(const std::string& binary_data) {
return base::HexEncode(binary_data.c_str(), binary_data.size());
}

bool RunExchange(P224EncryptedKeyExchange* client,
P224EncryptedKeyExchange* server,
bool is_password_same) {
Expand Down Expand Up @@ -71,6 +77,42 @@ TEST(MutualAuth, IncorrectPassword) {
EXPECT_FALSE(RunExchange(&client, &server, false));
}

TEST(MutualAuth, ExpectedValues) {
P224EncryptedKeyExchange client(P224EncryptedKeyExchange::kPeerTypeClient,
kPassword);
client.SetXForTesting("Client x");
P224EncryptedKeyExchange server(P224EncryptedKeyExchange::kPeerTypeServer,
kPassword);
server.SetXForTesting("Server x");

std::string client_message = client.GetMessage();
EXPECT_EQ(
"3508EF7DECC8AB9F9C439FBB0154288BBECC0A82E8448F4CF29554EB"
"BE9D486686226255EAD1D077C635B1A41F46AC91D7F7F32CED9EC3E0",
HexEncodeString(client_message));

std::string server_message = server.GetMessage();
EXPECT_EQ(
"A3088C18B75D2C2B107105661AEC85424777475EB29F1DDFB8C14AFB"
"F1603D0DF38413A00F420ACF2059E7997C935F5A957A193D09A2B584",
HexEncodeString(server_message));

EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
client.ProcessMessage(server_message));
EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
server.ProcessMessage(client_message));

EXPECT_EQ(client.GetUnverifiedKey(), server.GetUnverifiedKey());
// Must stay the same. External implementations should be able to pair with.
EXPECT_EQ(
"CE7CCFC435CDA4F01EC8826788B1F8B82EF7D550A34696B371096E64"
"C487D4FE193F7D1A6FF6820BC7F807796BA3889E8F999BBDEFC32FFA",
HexEncodeString(server.GetUnverifiedKey()));

EXPECT_TRUE(RunExchange(&client, &server, true));
EXPECT_EQ(client.GetKey(), server.GetKey());
}

TEST(MutualAuth, Fuzz) {
static const unsigned kIterations = 40;

Expand Down

0 comments on commit bd85b56

Please sign in to comment.