Commit 44594085 authored by rtenneti@chromium.org's avatar rtenneti@chromium.org

Reject reasons from strike register when nonce validation fails.

Send reject reason to client for debugging purposes.

Merge internal change: 70366491

R=wtc@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283692 0039d316-1c4b-4281-b951-d872f2087c98
parent d4b87557
......@@ -26,49 +26,54 @@ enum HandshakeFailureReason {
// Failure reasons for an invalid client nonce in CHLO.
//
// The default error value for nonce verification failures from strike
// register (covers old strike registers and unknown failures).
CLIENT_NONCE_UNKNOWN_FAILURE = 1,
// Client nonce had incorrect length.
CLIENT_NONCE_INVALID_FAILURE = 1,
CLIENT_NONCE_INVALID_FAILURE = 2,
// Client nonce is not unique.
CLIENT_NONCE_NOT_UNIQUE_FAILURE = 2,
CLIENT_NONCE_NOT_UNIQUE_FAILURE = 3,
// Client orbit is invalid or incorrect.
CLIENT_NONCE_INVALID_ORBIT_FAILURE = 3,
CLIENT_NONCE_INVALID_ORBIT_FAILURE = 4,
// Client nonce's timestamp is not in the strike register's valid time range.
CLIENT_NONCE_INVALID_TIME_FAILURE = 4,
// Client nonce verification has failed because strike register is down.
CLIENT_NONCE_NO_STRIKE_REGISTER_FAILURE = 5,
CLIENT_NONCE_INVALID_TIME_FAILURE = 5,
// Strike register's RPC call timed out, client nonce couldn't be verified.
CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT = 6,
// Strike register is down, client nonce couldn't be verified.
CLIENT_NONCE_STRIKE_REGISTER_FAILURE = 7,
// Failure reasons for an invalid server nonce in CHLO.
//
// Unbox of server nonce failed.
SERVER_NONCE_DECRYPTION_FAILURE = 6,
SERVER_NONCE_DECRYPTION_FAILURE = 8,
// Decrypted server nonce had incorrect length.
SERVER_NONCE_INVALID_FAILURE = 7,
SERVER_NONCE_INVALID_FAILURE = 9,
// Server nonce is not unique.
SERVER_NONCE_NOT_UNIQUE_FAILURE = 8,
SERVER_NONCE_NOT_UNIQUE_FAILURE = 10,
// Server nonce's timestamp is not in the strike register's valid time range.
SERVER_NONCE_INVALID_TIME_FAILURE = 9,
SERVER_NONCE_INVALID_TIME_FAILURE = 11,
// Failure reasons for an invalid server config in CHLO.
//
// Missing Server config id (kSCID) tag.
SERVER_CONFIG_INCHOATE_HELLO_FAILURE = 10,
SERVER_CONFIG_INCHOATE_HELLO_FAILURE = 12,
// Couldn't find the Server config id (kSCID).
SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE = 11,
SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE = 13,
// Failure reasons for an invalid source-address token.
//
// Missing Source-address token (kSourceAddressTokenTag) tag.
SOURCE_ADDRESS_TOKEN_INVALID_FAILURE = 12,
SOURCE_ADDRESS_TOKEN_INVALID_FAILURE = 14,
// Unbox of Source-address token failed.
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE = 13,
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE = 15,
// Couldn't parse the unbox'ed Source-address token.
SOURCE_ADDRESS_TOKEN_PARSE_FAILURE = 14,
SOURCE_ADDRESS_TOKEN_PARSE_FAILURE = 16,
// Source-address token is for a different IP address.
SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE = 15,
SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE = 17,
// The source-address token has a timestamp in the future.
SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE = 16,
SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE = 18,
// The source-address token has expired.
SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE = 17,
SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE = 19,
MAX_FAILURE_REASON,
};
......
......@@ -365,7 +365,7 @@ TEST_F(CryptoServerTest, DISABLED_DefaultCert) {
EXPECT_NE(0u, cert.size());
EXPECT_NE(0u, proof.size());
const HandshakeFailureReason kRejectReasons[] = {
CLIENT_NONCE_INVALID_FAILURE
CLIENT_NONCE_INVALID_TIME_FAILURE
};
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}
......@@ -551,7 +551,7 @@ TEST_P(CryptoServerTest, ReplayProtection) {
ASSERT_EQ(kREJ, out_.tag());
const HandshakeFailureReason kRejectReasons[] = {
CLIENT_NONCE_INVALID_FAILURE
CLIENT_NONCE_INVALID_TIME_FAILURE
};
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
......@@ -652,7 +652,7 @@ TEST_P(CryptoServerTestNoConfig, DontCrash) {
NULL));
const HandshakeFailureReason kRejectReasons[] = {
CLIENT_NONCE_INVALID_FAILURE
SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}
......
......@@ -30,19 +30,21 @@ bool LocalStrikeRegisterClient::IsKnownOrbit(StringPiece orbit) const {
}
void LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique(
StringPiece nonce, QuicWallTime now, ResultCallback* cb) {
bool nonce_is_valid_and_unique;
StringPiece nonce,
QuicWallTime now,
ResultCallback* cb) {
InsertStatus nonce_error;
if (nonce.length() != kNonceSize) {
nonce_is_valid_and_unique = false;
nonce_error = NONCE_INVALID_FAILURE;
} else {
base::AutoLock lock(m_);
nonce_is_valid_and_unique = strike_register_.Insert(
nonce_error = strike_register_.Insert(
reinterpret_cast<const uint8*>(nonce.data()),
static_cast<uint32>(now.ToUNIXSeconds()));
}
// m_ must not be held when the ResultCallback runs.
cb->Run(nonce_is_valid_and_unique);
cb->Run((nonce_error == NONCE_OK), nonce_error);
}
} // namespace net
......@@ -25,21 +25,27 @@ class RecordResultCallback : public StrikeRegisterClient::ResultCallback {
// RecordResultCallback stores the argument to RunImpl in
// |*saved_value| and sets |*called| to true. The callback is self
// deleting.
RecordResultCallback(bool* called, bool* saved_value)
RecordResultCallback(bool* called,
bool* saved_value,
InsertStatus* saved_nonce_error)
: called_(called),
saved_value_(saved_value) {
saved_value_(saved_value),
saved_nonce_error_(saved_nonce_error) {
*called_ = false;
}
protected:
virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
virtual void RunImpl(bool nonce_is_valid_and_unique,
InsertStatus nonce_error) OVERRIDE {
*called_ = true;
*saved_value_ = nonce_is_valid_and_unique;
*saved_nonce_error_ = nonce_error;
}
private:
bool* called_;
bool* saved_value_;
InsertStatus* saved_nonce_error_;
DISALLOW_COPY_AND_ASSIGN(RecordResultCallback);
};
......@@ -85,39 +91,45 @@ TEST_F(LocalStrikeRegisterClientTest, IncorrectNonceLength) {
// Validation fails if you remove a byte from the nonce.
bool called = false;
bool is_valid = false;
InsertStatus nonce_error = NONCE_UNKNOWN_FAILURE;
string short_nonce = valid_nonce.substr(0, valid_nonce.length() - 1);
strike_register_->VerifyNonceIsValidAndUnique(
short_nonce,
QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
new RecordResultCallback(&called, &is_valid));
new RecordResultCallback(&called, &is_valid, &nonce_error));
EXPECT_TRUE(called);
EXPECT_FALSE(is_valid);
EXPECT_EQ(NONCE_INVALID_FAILURE, nonce_error);
}
{
// Validation fails if you add a byte to the nonce.
bool called = false;
bool is_valid = false;
InsertStatus nonce_error = NONCE_UNKNOWN_FAILURE;
string long_nonce(valid_nonce);
long_nonce.append("a");
strike_register_->VerifyNonceIsValidAndUnique(
long_nonce,
QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
new RecordResultCallback(&called, &is_valid));
new RecordResultCallback(&called, &is_valid, &nonce_error));
EXPECT_TRUE(called);
EXPECT_FALSE(is_valid);
EXPECT_EQ(NONCE_INVALID_FAILURE, nonce_error);
}
{
// Verify that the base nonce validates was valid.
bool called = false;
bool is_valid = false;
InsertStatus nonce_error = NONCE_UNKNOWN_FAILURE;
strike_register_->VerifyNonceIsValidAndUnique(
valid_nonce,
QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
new RecordResultCallback(&called, &is_valid));
new RecordResultCallback(&called, &is_valid, &nonce_error));
EXPECT_TRUE(called);
EXPECT_TRUE(is_valid);
EXPECT_EQ(NONCE_OK, nonce_error);
}
}
......
......@@ -148,13 +148,40 @@ class VerifyNonceIsValidAndUniqueCallback
}
protected:
virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique;
virtual void RunImpl(bool nonce_is_valid_and_unique,
InsertStatus nonce_error) OVERRIDE {
DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
<< " nonce_error: " << nonce_error;
result_->info.unique = nonce_is_valid_and_unique;
// TODO(rtenneti): Implement capturing of error from strike register.
// Temporarily treat them as CLIENT_NONCE_INVALID_FAILURE.
if (!nonce_is_valid_and_unique) {
result_->info.reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
HandshakeFailureReason client_nonce_error;
switch (nonce_error) {
case NONCE_INVALID_FAILURE:
client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
break;
case NONCE_NOT_UNIQUE_FAILURE:
client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
break;
case NONCE_INVALID_ORBIT_FAILURE:
client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
break;
case NONCE_INVALID_TIME_FAILURE:
client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
break;
case STRIKE_REGISTER_TIMEOUT:
client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
break;
case STRIKE_REGISTER_FAILURE:
client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
break;
case NONCE_OK:
case NONCE_UNKNOWN_FAILURE:
default:
LOG(WARNING) << "Unexpected nonce error: " << nonce_error;
client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
break;
}
result_->info.reject_reasons.push_back(client_nonce_error);
}
done_cb_->Run(result_);
}
......@@ -1440,7 +1467,7 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
bad_nonce_buffer_length);
bool is_unique;
InsertStatus nonce_error;
{
base::AutoLock auto_lock(server_nonce_strike_register_lock_);
if (server_nonce_strike_register_.get() == NULL) {
......@@ -1450,11 +1477,27 @@ HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
server_nonce_strike_register_window_secs_, server_nonce_orbit_,
StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
}
is_unique = server_nonce_strike_register_->Insert(
nonce_error = server_nonce_strike_register_->Insert(
server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
}
return is_unique ? HANDSHAKE_OK : SERVER_NONCE_NOT_UNIQUE_FAILURE;
switch (nonce_error) {
case NONCE_OK:
return HANDSHAKE_OK;
case NONCE_INVALID_FAILURE:
return SERVER_NONCE_INVALID_FAILURE;
case NONCE_NOT_UNIQUE_FAILURE:
return SERVER_NONCE_NOT_UNIQUE_FAILURE;
case NONCE_INVALID_TIME_FAILURE:
return SERVER_NONCE_INVALID_TIME_FAILURE;
case NONCE_UNKNOWN_FAILURE:
case NONCE_INVALID_ORBIT_FAILURE:
case STRIKE_REGISTER_TIMEOUT:
case STRIKE_REGISTER_FAILURE:
default:
LOG(WARNING) << "Unexpected nonce error: " << nonce_error;
return SERVER_NONCE_NOT_UNIQUE_FAILURE;
}
}
QuicCryptoServerConfig::Config::Config()
......
......@@ -130,8 +130,8 @@ void StrikeRegister::Reset() {
internal_node_head_ = kNil;
}
bool StrikeRegister::Insert(const uint8 nonce[32],
uint32 current_time_external) {
InsertStatus StrikeRegister::Insert(const uint8 nonce[32],
uint32 current_time_external) {
// Make space for the insertion if the strike register is full.
while (external_node_free_head_ == kNil ||
internal_node_free_head_ == kNil) {
......@@ -142,7 +142,7 @@ bool StrikeRegister::Insert(const uint8 nonce[32],
// Check to see if the orbit is correct.
if (memcmp(nonce + sizeof(current_time), orbit_, sizeof(orbit_))) {
return false;
return NONCE_INVALID_ORBIT_FAILURE;
}
const uint32 nonce_time = ExternalTimeToInternal(TimeFromBytes(nonce));
......@@ -151,7 +151,7 @@ bool StrikeRegister::Insert(const uint8 nonce[32],
pair<uint32, uint32> valid_range =
StrikeRegister::GetValidRange(current_time);
if (nonce_time < valid_range.first || nonce_time > valid_range.second) {
return false;
return NONCE_INVALID_TIME_FAILURE;
}
// We strip the orbit out of the nonce.
......@@ -171,13 +171,13 @@ bool StrikeRegister::Insert(const uint8 nonce[32],
memcpy(external_node(index), value, sizeof(value));
internal_node_head_ = (index | kExternalFlag) << 8;
DCHECK_LE(horizon_, nonce_time);
return true;
return NONCE_OK;
}
const uint8* best_match = external_node(best_match_index);
if (memcmp(best_match, value, sizeof(value)) == 0) {
// We found the value in the tree.
return false;
return NONCE_NOT_UNIQUE_FAILURE;
}
// We are going to insert a new entry into the tree, so get the nodes now.
......@@ -263,7 +263,7 @@ bool StrikeRegister::Insert(const uint8 nonce[32],
*where_index = (*where_index & 0xff) | (internal_node_index << 8);
DCHECK_LE(horizon_, nonce_time);
return true;
return NONCE_OK;
}
const uint8* StrikeRegister::orbit() const {
......
......@@ -15,6 +15,26 @@
namespace net {
// InsertStatus enum values cannot be changed, they need to be stable.
enum InsertStatus {
NONCE_OK = 0,
// The default error value for nonce verification failures from strike
// register (covers old strike registers and unknown failures).
NONCE_UNKNOWN_FAILURE = 1,
// Decrypted nonce had incorrect length.
NONCE_INVALID_FAILURE = 2,
// Nonce is not unique.
NONCE_NOT_UNIQUE_FAILURE = 3,
// Nonce's orbit is invalid or incorrect.
NONCE_INVALID_ORBIT_FAILURE = 4,
// Nonce's timestamp is not in the strike register's valid time range.
NONCE_INVALID_TIME_FAILURE = 5,
// Strike register's RPC call timed out, nonce couldn't be verified.
STRIKE_REGISTER_TIMEOUT = 6,
// Strike register is down, nonce couldn't be verified.
STRIKE_REGISTER_FAILURE = 7,
};
// A StrikeRegister is critbit tree which stores a set of observed nonces.
// We use a critbit tree because:
// 1) It's immune to algorithmic complexity attacks. If we had used a hash
......@@ -107,16 +127,17 @@ class NET_EXPORT_PRIVATE StrikeRegister {
// b) before the current horizon
// c) outside of the valid time window
// d) already in the set of observed nonces
// and returns false if any of these are true. It is also free to return
// false for other reasons as it's always safe to reject an nonce.
// and returns the failure reason if any of these are true. It is also free to
// return failure reason for other reasons as it's always safe to reject an
// nonce.
//
// nonces are:
// 4 bytes of timestamp (UNIX epoch seconds)
// 8 bytes of orbit value (a cluster id)
// 20 bytes of random data
//
// Otherwise, it inserts |nonce| into the observed set and returns true.
bool Insert(const uint8 nonce[32], uint32 current_time);
// Otherwise, it inserts |nonce| into the observed set and returns NONCE_OK.
InsertStatus Insert(const uint8 nonce[32], uint32 current_time);
// orbit returns a pointer to the 8-byte orbit value for this
// strike-register.
......
......@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/quic/crypto/strike_register.h"
#include "net/quic/quic_time.h"
namespace net {
......@@ -24,13 +25,14 @@ class NET_EXPORT_PRIVATE StrikeRegisterClient {
public:
ResultCallback() {}
virtual ~ResultCallback() {}
void Run(bool nonce_is_valid_and_unique) {
RunImpl(nonce_is_valid_and_unique);
void Run(bool nonce_is_valid_and_unique, InsertStatus nonce_error) {
RunImpl(nonce_is_valid_and_unique, nonce_error);
delete this;
}
protected:
virtual void RunImpl(bool nonce_is_valid_and_unique) = 0;
virtual void RunImpl(bool nonce_is_valid_and_unique,
InsertStatus nonce_error) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ResultCallback);
......@@ -42,7 +44,8 @@ class NET_EXPORT_PRIVATE StrikeRegisterClient {
// Returns true iff the strike register knows about the given orbit.
virtual bool IsKnownOrbit(base::StringPiece orbit) const = 0;
// Validate a nonce for freshness and uniqueness.
// Will invoke cb->Run(ValidateResponse::nonce_is_valid_and_unique())
// Will invoke cb->Run(ValidateResponse::nonce_is_valid_and_unique(),
// ValidateResponse::nonce_error())
// once the asynchronous operation is complete.
virtual void VerifyNonceIsValidAndUnique(
base::StringPiece nonce,
......
......@@ -13,6 +13,7 @@
namespace {
using net::InsertStatus;
using net::StrikeRegister;
using std::make_pair;
using std::min;
......@@ -40,9 +41,9 @@ TEST(StrikeRegisterTest, SimpleHorizon) {
StrikeRegister::DENY_REQUESTS_AT_STARTUP);
uint8 nonce[32];
SetNonce(nonce, 999, kOrbit);
ASSERT_FALSE(set.Insert(nonce, 1000));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000));
SetNonce(nonce, 1000, kOrbit);
ASSERT_FALSE(set.Insert(nonce, 1000));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000));
EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1000 /* current time */));
EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1100 /* current time */));
......@@ -60,8 +61,8 @@ TEST(StrikeRegisterTest, NoStartupMode) {
StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
uint8 nonce[32];
SetNonce(nonce, 1000, kOrbit);
ASSERT_TRUE(set.Insert(nonce, 1000));
ASSERT_FALSE(set.Insert(nonce, 1000));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1000));
EXPECT_EQ(net::NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1000));
EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1000 /* current time */));
EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1050 /* current time */));
......@@ -77,9 +78,9 @@ TEST(StrikeRegisterTest, WindowFuture) {
StrikeRegister::DENY_REQUESTS_AT_STARTUP);
uint8 nonce[32];
SetNonce(nonce, 1101, kOrbit);
ASSERT_FALSE(set.Insert(nonce, 1000));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000));
SetNonce(nonce, 999, kOrbit);
ASSERT_FALSE(set.Insert(nonce, 1100));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100));
}
TEST(StrikeRegisterTest, BadOrbit) {
......@@ -90,7 +91,7 @@ TEST(StrikeRegisterTest, BadOrbit) {
uint8 nonce[32];
static const uint8 kBadOrbit[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
SetNonce(nonce, 1101, kBadOrbit);
ASSERT_FALSE(set.Insert(nonce, 1100));
EXPECT_EQ(net::NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100));
}
TEST(StrikeRegisterTest, OneValue) {
......@@ -99,7 +100,7 @@ TEST(StrikeRegisterTest, OneValue) {
StrikeRegister::DENY_REQUESTS_AT_STARTUP);
uint8 nonce[32];
SetNonce(nonce, 1101, kOrbit);
ASSERT_TRUE(set.Insert(nonce, 1101));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1101));
}
TEST(StrikeRegisterTest, RejectDuplicate) {
......@@ -109,8 +110,8 @@ TEST(StrikeRegisterTest, RejectDuplicate) {
StrikeRegister::DENY_REQUESTS_AT_STARTUP);
uint8 nonce[32];
SetNonce(nonce, 1101, kOrbit);
ASSERT_TRUE(set.Insert(nonce, 1101));
ASSERT_FALSE(set.Insert(nonce, 1101));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1101));
EXPECT_EQ(net::NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101));
}
TEST(StrikeRegisterTest, HorizonUpdating) {
......@@ -127,7 +128,7 @@ TEST(StrikeRegisterTest, HorizonUpdating) {
for (unsigned i = 0; i < 5; i++) {
SetNonce(nonce[i], 1101 + i, kOrbit);
nonce[i][31] = i;
ASSERT_TRUE(set.Insert(nonce[i], 1100));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[i], 1100));
}
// Valid window is still equal to |window_secs + 1|.
......@@ -136,34 +137,34 @@ TEST(StrikeRegisterTest, HorizonUpdating) {
// This should push the oldest value out and force the horizon to
// be updated.
SetNonce(nonce[5], 1110, kOrbit);
ASSERT_TRUE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110));
// Effective horizon is computed based on the timestamp of the
// value that was pushed out.
EXPECT_EQ(9u, set.GetCurrentValidWindowSecs(1110));
SetNonce(nonce[5], 1111, kOrbit);
EXPECT_TRUE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110));
EXPECT_EQ(8u, set.GetCurrentValidWindowSecs(1110));
// This should be behind the horizon now:
SetNonce(nonce[5], 1101, kOrbit);
nonce[5][31] = 10;
EXPECT_FALSE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110));
// Insert beyond the valid range.
SetNonce(nonce[5], 1117, kOrbit);
nonce[5][31] = 2;
EXPECT_FALSE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110));
// Insert at the upper valid range.
SetNonce(nonce[5], 1116, kOrbit);
nonce[5][31] = 1;
EXPECT_TRUE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110));
// This should be beyond the upper valid range now:
SetNonce(nonce[5], 1116, kOrbit);
nonce[5][31] = 2;
EXPECT_FALSE(set.Insert(nonce[5], 1110));
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110));
}
}
......@@ -177,7 +178,7 @@ TEST(StrikeRegisterTest, InsertMany) {
for (unsigned i = 0; i < 100000; i++) {
SetNonce(nonce, 1101 + i/500, kOrbit);
memcpy(nonce + 12, &i, sizeof(i));
set.Insert(nonce, 1100);
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100));
}
}
......@@ -201,9 +202,9 @@ class SlowStrikeRegister {
memcpy(orbit_, orbit, sizeof(orbit_));
}
bool Insert(const uint8 nonce_bytes[32],
const uint32 nonce_time_external,
const uint32 current_time_external) {
InsertStatus Insert(const uint8 nonce_bytes[32],
const uint32 nonce_time_external,
const uint32 current_time_external) {
if (nonces_.size() == max_entries_) {
DropOldestEntry();
}
......@@ -212,7 +213,7 @@ class SlowStrikeRegister {
// Check to see if the orbit is correct.
if (memcmp(nonce_bytes + 4, orbit_, sizeof(orbit_))) {
return false;
return net::NONCE_INVALID_ORBIT_FAILURE;
}
const uint32 nonce_time =
ExternalTimeToInternal(TimeFromBytes(nonce_bytes));
......@@ -221,14 +222,14 @@ class SlowStrikeRegister {
// so we have to reject anything with a timestamp less than or
// equal to that.
if (nonce_time < horizon_) {
return false;
return net::NONCE_INVALID_TIME_FAILURE;
}
// Check that the timestamp is in the current window.
if ((current_time > window_secs_ &&
nonce_time < (current_time - window_secs_)) ||
nonce_time > (current_time + window_secs_)) {
return false;
return net::NONCE_INVALID_TIME_FAILURE;
}
pair<uint32, string> nonce = make_pair(
......@@ -237,11 +238,11 @@ class SlowStrikeRegister {
set<pair<uint32, string> >::const_iterator it = nonces_.find(nonce);
if (it != nonces_.end()) {
return false;
return net::NONCE_NOT_UNIQUE_FAILURE;
}
nonces_.insert(nonce);
return true;
return net::NONCE_OK;
}
uint32 GetCurrentValidWindowSecs(const uint32 current_time_external) const {
......@@ -314,11 +315,16 @@ TEST_F(StrikeRegisterStressTest, InOrderInsertion) {
nonce[30] = v >> 8;
nonce[31] = v;
const bool r2 = s2->Insert(nonce, time, time);
const bool r1 = s1->Insert(nonce, time);
EXPECT_EQ(r1, r2);
const InsertStatus nonce_error2 = s2->Insert(nonce, time, time);
const InsertStatus nonce_error1 = s1->Insert(nonce, time);
EXPECT_EQ(nonce_error1, nonce_error2);
// Inserts succeed after the startup period.
EXPECT_EQ(time > current_time + window, r1);
if (time > current_time + window) {
EXPECT_EQ(net::NONCE_OK, nonce_error1);
} else {
EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, nonce_error1);
}
EXPECT_EQ(s1->GetCurrentValidWindowSecs(time),
s2->GetCurrentValidWindowSecs(time));
......@@ -379,9 +385,9 @@ TEST_F(StrikeRegisterStressTest, Stress) {
nonce[30] = v >> 8;
nonce[31] = v;
const bool r2 = s2->Insert(nonce, time, time);
const bool r1 = s1->Insert(nonce, time);
EXPECT_EQ(r1, r2);
const InsertStatus nonce_error2 = s2->Insert(nonce, time, time);
const InsertStatus nonce_error1 = s1->Insert(nonce, time);
EXPECT_EQ(nonce_error1, nonce_error2);
EXPECT_EQ(s1->GetCurrentValidWindowSecs(time),
s2->GetCurrentValidWindowSecs(time));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment