| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/crypto/strike_register.h" | 5 #include "net/quic/crypto/strike_register.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 | 8 |
| 9 using std::pair; | 9 using std::pair; |
| 10 using std::set; | 10 using std::set; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 uint8 otherbits() const { return data_[1]; } | 48 uint8 otherbits() const { return data_[1]; } |
| 49 | 49 |
| 50 // These bytes are organised thus: | 50 // These bytes are organised thus: |
| 51 // <24 bits> left child | 51 // <24 bits> left child |
| 52 // <8 bits> crit-byte | 52 // <8 bits> crit-byte |
| 53 // <24 bits> right child | 53 // <24 bits> right child |
| 54 // <8 bits> other-bits | 54 // <8 bits> other-bits |
| 55 uint32 data_[2]; | 55 uint32 data_[2]; |
| 56 }; | 56 }; |
| 57 | 57 |
| 58 // kCreationTimeFromInternalEpoch contains the number of seconds between the |
| 59 // start of the internal epoch and |creation_time_external_|. This allows us |
| 60 // to consider times that are before |creation_time_external_|. |
| 61 static const uint32 kCreationTimeFromInternalEpoch = 63115200.0; // 2 years. |
| 62 |
| 58 StrikeRegister::StrikeRegister(unsigned max_entries, | 63 StrikeRegister::StrikeRegister(unsigned max_entries, |
| 59 uint32 current_time, | 64 uint32 current_time, |
| 60 uint32 window_secs, | 65 uint32 window_secs, |
| 61 const uint8 orbit[8]) | 66 const uint8 orbit[8], |
| 67 StartupType startup) |
| 62 : max_entries_(max_entries), | 68 : max_entries_(max_entries), |
| 63 window_secs_(window_secs), | 69 window_secs_(window_secs), |
| 64 // The horizon is initially set |window_secs| into the future because, if | 70 // The horizon is initially set |window_secs| into the future because, if |
| 65 // we just crashed, then we may have accepted nonces in the span | 71 // we just crashed, then we may have accepted nonces in the span |
| 66 // [current_time...current_time+window_secs) and so we conservatively | 72 // [current_time...current_time+window_secs) and so we conservatively |
| 67 // reject the whole timespan. | 73 // reject the whole timespan unless |startup| tells us otherwise. |
| 68 horizon_(current_time + window_secs) { | 74 creation_time_external_(current_time), |
| 75 internal_epoch_(current_time > kCreationTimeFromInternalEpoch |
| 76 ? current_time - kCreationTimeFromInternalEpoch |
| 77 : 0), |
| 78 horizon_(ExternalTimeToInternal(current_time) + window_secs), |
| 79 horizon_valid_(startup == DENY_REQUESTS_AT_STARTUP) { |
| 69 memcpy(orbit_, orbit, sizeof(orbit_)); | 80 memcpy(orbit_, orbit, sizeof(orbit_)); |
| 70 | 81 |
| 82 // TODO(rtenneti): Remove the following check, Added the following to silence |
| 83 // "is not used" error. |
| 84 CHECK_GE(creation_time_external_, 0u); |
| 85 |
| 71 // We only have 23 bits of index available. | 86 // We only have 23 bits of index available. |
| 72 CHECK_LT(max_entries, 1u << 23); | 87 CHECK_LT(max_entries, 1u << 23); |
| 73 CHECK_GT(max_entries, 1u); // There must be at least two entries. | 88 CHECK_GT(max_entries, 1u); // There must be at least two entries. |
| 74 CHECK_EQ(sizeof(InternalNode), 8u); // in case of compiler changes. | 89 CHECK_EQ(sizeof(InternalNode), 8u); // in case of compiler changes. |
| 75 internal_nodes_ = new InternalNode[max_entries]; | 90 internal_nodes_ = new InternalNode[max_entries]; |
| 76 external_nodes_.reset(new uint8[kExternalNodeSize * max_entries]); | 91 external_nodes_.reset(new uint8[kExternalNodeSize * max_entries]); |
| 77 | 92 |
| 78 Reset(); | 93 Reset(); |
| 79 } | 94 } |
| 80 | 95 |
| 81 StrikeRegister::~StrikeRegister() { delete[] internal_nodes_; } | 96 StrikeRegister::~StrikeRegister() { delete[] internal_nodes_; } |
| 82 | 97 |
| 83 void StrikeRegister::Reset() { | 98 void StrikeRegister::Reset() { |
| 84 // Thread a free list through all of the internal nodes. | 99 // Thread a free list through all of the internal nodes. |
| 85 internal_node_free_head_ = 0; | 100 internal_node_free_head_ = 0; |
| 86 for (unsigned i = 0; i < max_entries_ - 1; i++) | 101 for (unsigned i = 0; i < max_entries_ - 1; i++) |
| 87 internal_nodes_[i].SetNextPtr(i + 1); | 102 internal_nodes_[i].SetNextPtr(i + 1); |
| 88 internal_nodes_[max_entries_ - 1].SetNextPtr(kNil); | 103 internal_nodes_[max_entries_ - 1].SetNextPtr(kNil); |
| 89 | 104 |
| 90 // Also thread a free list through the external nodes. | 105 // Also thread a free list through the external nodes. |
| 91 external_node_free_head_ = 0; | 106 external_node_free_head_ = 0; |
| 92 for (unsigned i = 0; i < max_entries_ - 1; i++) | 107 for (unsigned i = 0; i < max_entries_ - 1; i++) |
| 93 external_node_next_ptr(i) = i + 1; | 108 external_node_next_ptr(i) = i + 1; |
| 94 external_node_next_ptr(max_entries_ - 1) = kNil; | 109 external_node_next_ptr(max_entries_ - 1) = kNil; |
| 95 | 110 |
| 96 // This is the root of the tree. | 111 // This is the root of the tree. |
| 97 internal_node_head_ = kNil; | 112 internal_node_head_ = kNil; |
| 98 } | 113 } |
| 99 | 114 |
| 100 bool StrikeRegister::Insert(const uint8 nonce[32], | 115 bool StrikeRegister::Insert(const uint8 nonce[32], |
| 101 const uint32 current_time) { | 116 const uint32 current_time_external) { |
| 102 // If current_time is very small or very large then we assume that we have | 117 const uint32 current_time = ExternalTimeToInternal(current_time_external); |
| 103 // just rolled over / are about to roll over and it's 2038 or 2106. Since | |
| 104 // we don't deal with this situation we flush everything and start over. | |
| 105 // This means that we reject everything for 2 * |window_secs_| every 68 | |
| 106 // years. | |
| 107 if (current_time < window_secs_ || | |
| 108 current_time + window_secs_ < current_time) { | |
| 109 if (internal_node_head_ != kNil) { | |
| 110 Reset(); | |
| 111 } | |
| 112 horizon_ = current_time; | |
| 113 return false; | |
| 114 } | |
| 115 | 118 |
| 116 // Check to see if the orbit is correct. | 119 // Check to see if the orbit is correct. |
| 117 if (memcmp(nonce + sizeof(current_time), orbit_, sizeof(orbit_))) { | 120 if (memcmp(nonce + sizeof(current_time), orbit_, sizeof(orbit_))) { |
| 118 return false; | 121 return false; |
| 119 } | 122 } |
| 120 const uint32 nonce_time = TimeFromBytes(nonce); | 123 const uint32 nonce_time = ExternalTimeToInternal(TimeFromBytes(nonce)); |
| 121 // We have dropped one or more nonces with a time value of |horizon_|, so | 124 // We have dropped one or more nonces with a time value of |horizon_|, so |
| 122 // we have to reject anything with a timestamp less than or equal to that. | 125 // we have to reject anything with a timestamp less than or equal to that. |
| 123 if (nonce_time <= horizon_) { | 126 if (horizon_valid_ && nonce_time <= horizon_) { |
| 124 return false; | 127 return false; |
| 125 } | 128 } |
| 126 | 129 |
| 127 // Check that the timestamp is in the current window. | 130 // Check that the timestamp is in the current window. |
| 128 if (nonce_time < (current_time - window_secs_) || | 131 if ((current_time > window_secs_ && |
| 132 nonce_time < (current_time - window_secs_)) || |
| 129 nonce_time > (current_time + window_secs_)) { | 133 nonce_time > (current_time + window_secs_)) { |
| 130 return false; | 134 return false; |
| 131 } | 135 } |
| 132 | 136 |
| 133 // We strip the orbit out of the nonce. | 137 // We strip the orbit out of the nonce. |
| 134 uint8 value[24]; | 138 uint8 value[24]; |
| 135 memcpy(value, nonce, sizeof(current_time)); | 139 memcpy(value, &nonce_time, sizeof(nonce_time)); |
| 136 memcpy(value + sizeof(current_time), | 140 memcpy(value + sizeof(nonce_time), |
| 137 nonce + sizeof(current_time) + sizeof(orbit_), | 141 nonce + sizeof(nonce_time) + sizeof(orbit_), |
| 138 sizeof(value) - sizeof(current_time)); | 142 sizeof(value) - sizeof(nonce_time)); |
| 139 | 143 |
| 140 // Find the best match to |value| in the crit-bit tree. The best match is | 144 // Find the best match to |value| in the crit-bit tree. The best match is |
| 141 // simply the value which /could/ match |value|, if any does, so we still | 145 // simply the value which /could/ match |value|, if any does, so we still |
| 142 // need a memcmp to check. | 146 // need a memcmp to check. |
| 143 uint32 best_match_index = BestMatch(value); | 147 uint32 best_match_index = BestMatch(value); |
| 144 if (best_match_index == kNil) { | 148 if (best_match_index == kNil) { |
| 145 // Empty tree. Just insert the new value at the root. | 149 // Empty tree. Just insert the new value at the root. |
| 146 uint32 index = GetFreeExternalNode(); | 150 uint32 index = GetFreeExternalNode(); |
| 147 memcpy(external_node(index), value, sizeof(value)); | 151 memcpy(external_node(index), value, sizeof(value)); |
| 148 internal_node_head_ = (index | kExternalFlag) << 8; | 152 internal_node_head_ = (index | kExternalFlag) << 8; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 } | 274 } |
| 271 | 275 |
| 272 // static | 276 // static |
| 273 uint32 StrikeRegister::TimeFromBytes(const uint8 d[4]) { | 277 uint32 StrikeRegister::TimeFromBytes(const uint8 d[4]) { |
| 274 return static_cast<uint32>(d[0]) << 24 | | 278 return static_cast<uint32>(d[0]) << 24 | |
| 275 static_cast<uint32>(d[1]) << 16 | | 279 static_cast<uint32>(d[1]) << 16 | |
| 276 static_cast<uint32>(d[2]) << 8 | | 280 static_cast<uint32>(d[2]) << 8 | |
| 277 static_cast<uint32>(d[3]); | 281 static_cast<uint32>(d[3]); |
| 278 } | 282 } |
| 279 | 283 |
| 284 uint32 StrikeRegister::ExternalTimeToInternal(uint32 external_time) { |
| 285 return external_time - internal_epoch_; |
| 286 } |
| 287 |
| 280 uint32 StrikeRegister::BestMatch(const uint8 v[24]) const { | 288 uint32 StrikeRegister::BestMatch(const uint8 v[24]) const { |
| 281 if (internal_node_head_ == kNil) { | 289 if (internal_node_head_ == kNil) { |
| 282 return kNil; | 290 return kNil; |
| 283 } | 291 } |
| 284 | 292 |
| 285 uint32 next = internal_node_head_ >> 8; | 293 uint32 next = internal_node_head_ >> 8; |
| 286 while ((next & kExternalFlag) == 0) { | 294 while ((next & kExternalFlag) == 0) { |
| 287 InternalNode* node = &internal_nodes_[next]; | 295 InternalNode* node = &internal_nodes_[next]; |
| 288 uint8 b = v[node->critbyte()]; | 296 uint8 b = v[node->critbyte()]; |
| 289 unsigned direction = | 297 unsigned direction = |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 CHECK_EQ(free_internal_nodes.count(inter), 0u); | 452 CHECK_EQ(free_internal_nodes.count(inter), 0u); |
| 445 CHECK_EQ(used_internal_nodes->count(inter), 0u); | 453 CHECK_EQ(used_internal_nodes->count(inter), 0u); |
| 446 used_internal_nodes->insert(inter); | 454 used_internal_nodes->insert(inter); |
| 447 ValidateTree(inter, bit, bits, free_internal_nodes, free_external_nodes, | 455 ValidateTree(inter, bit, bits, free_internal_nodes, free_external_nodes, |
| 448 used_internal_nodes, used_external_nodes); | 456 used_internal_nodes, used_external_nodes); |
| 449 } | 457 } |
| 450 } | 458 } |
| 451 } | 459 } |
| 452 | 460 |
| 453 } // namespace net | 461 } // namespace net |
| OLD | NEW |