Commit 5c942e8e authored by Balazs Engedy's avatar Balazs Engedy Committed by Commit Bot

Add u2f_parsing_utils::Extract[Suffix][Span].

Bug: 780078
Change-Id: I8f538a29306f1f94a2b5b5c307d743d485f33336
Reviewed-on: https://chromium-review.googlesource.com/975542
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545090}
parent d16b10ac
......@@ -73,6 +73,7 @@ test("device_unittests") {
"fido/fido_discovery_unittest.cc",
"fido/fido_hid_message_unittest.cc",
"fido/test_callback_receiver_unittest.cc",
"fido/u2f_parsing_utils_unittest.cc",
"fido/u2f_register_unittest.cc",
"fido/u2f_request_unittest.cc",
"fido/u2f_sign_unittest.cc",
......
......@@ -13,19 +13,37 @@ const uint32_t kU2fResponseKeyHandleLengthPos = 66u;
const uint32_t kU2fResponseKeyHandleStartPos = 67u;
const char kEs256[] = "ES256";
std::vector<uint8_t> Materialize(base::span<const uint8_t> span) {
return std::vector<uint8_t>(span.begin(), span.end());
}
void Append(std::vector<uint8_t>* target, base::span<const uint8_t> in_values) {
target->insert(target->end(), in_values.begin(), in_values.end());
}
std::vector<uint8_t> Extract(base::span<const uint8_t> source,
std::vector<uint8_t> Extract(base::span<const uint8_t> span,
size_t pos,
size_t length) {
if (!(pos <= source.size() && length <= source.size() - pos)) {
return std::vector<uint8_t>();
}
return Materialize(ExtractSpan(span, pos, length));
}
return std::vector<uint8_t>(source.begin() + pos,
source.begin() + pos + length);
base::span<const uint8_t> ExtractSpan(base::span<const uint8_t> span,
size_t pos,
size_t length) {
if (!(pos <= span.size() && length <= span.size() - pos))
return base::span<const uint8_t>();
return span.subspan(pos, length);
}
std::vector<uint8_t> ExtractSuffix(base::span<const uint8_t> span, size_t pos) {
return Materialize(ExtractSuffixSpan(span, pos));
}
base::span<const uint8_t> ExtractSuffixSpan(base::span<const uint8_t> span,
size_t pos) {
if (pos > span.size())
return std::vector<uint8_t>();
return span.subspan(pos);
}
} // namespace u2f_parsing_utils
......
......@@ -23,14 +23,36 @@ COMPONENT_EXPORT(DEVICE_FIDO)
extern const uint32_t kU2fResponseKeyHandleStartPos;
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kEs256[];
// Returns copy of |span|, that is, a vector with the same elements.
COMPONENT_EXPORT(DEVICE_FIDO)
std::vector<uint8_t> Materialize(base::span<const uint8_t> span);
// Appends |in_values| to the end of |target|. The underlying container for
// |in_values| should *not* be |target|.
COMPONENT_EXPORT(DEVICE_FIDO)
void Append(std::vector<uint8_t>* target, base::span<const uint8_t> in_values);
// Parses out a sub-vector after verifying no out-of-bound reads.
// Safely extracts, with bound checking, a contiguous subsequence of |span| of
// the given |length| and starting at |pos|. Returns an empty vector/span if the
// requested range is out-of-bound.
COMPONENT_EXPORT(DEVICE_FIDO)
std::vector<uint8_t> Extract(base::span<const uint8_t> source,
std::vector<uint8_t> Extract(base::span<const uint8_t> span,
size_t pos,
size_t length);
COMPONENT_EXPORT(DEVICE_FIDO)
base::span<const uint8_t> ExtractSpan(base::span<const uint8_t> span,
size_t pos,
size_t length);
// Safely extracts, with bound checking, the suffix of the given |span| starting
// at the given position |pos|. Returns an empty vector/span if the requested
// starting position is out-of-bound.
COMPONENT_EXPORT(DEVICE_FIDO)
std::vector<uint8_t> ExtractSuffix(base::span<const uint8_t> span, size_t pos);
COMPONENT_EXPORT(DEVICE_FIDO)
base::span<const uint8_t> ExtractSuffixSpan(base::span<const uint8_t> span,
size_t pos);
} // namespace u2f_parsing_utils
} // namespace device
......
// Copyright 2018 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.
#include "device/fido/u2f_parsing_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
namespace u2f_parsing_utils {
namespace {
constexpr uint8_t kOne[] = {0x01};
constexpr uint8_t kTwoThree[] = {0x02, 0x03};
constexpr uint8_t kThree[] = {0x03};
constexpr uint8_t kOneTwoThree[] = {0x01, 0x02, 0x03};
} // namespace
TEST(U2fParsingUtils, Materialize) {
const std::vector<uint8_t> empty;
EXPECT_THAT(Materialize(empty), ::testing::IsEmpty());
EXPECT_THAT(Materialize(base::span<const uint8_t>()), ::testing::IsEmpty());
EXPECT_THAT(Materialize(kOne), ::testing::ElementsAreArray(kOne));
EXPECT_THAT(Materialize(kOneTwoThree),
::testing::ElementsAreArray(kOneTwoThree));
}
TEST(U2fParsingUtils, Append) {
std::vector<uint8_t> target;
Append(&target, base::span<const uint8_t>());
EXPECT_THAT(target, ::testing::IsEmpty());
// Should be idempotent, try twice for good measure.
Append(&target, base::span<const uint8_t>());
EXPECT_THAT(target, ::testing::IsEmpty());
const std::vector<uint8_t> one(std::begin(kOne), std::end(kOne));
Append(&target, one);
EXPECT_THAT(target, ::testing::ElementsAreArray(kOne));
Append(&target, kTwoThree);
EXPECT_THAT(target, ::testing::ElementsAreArray(kOneTwoThree));
}
// ExtractSpan and ExtractSuffixSpan are implicitly tested as they used by
// the Extract and ExtractSuffix implementations.
TEST(U2fParsingUtils, ExtractEmpty) {
const std::vector<uint8_t> empty;
EXPECT_THAT(Extract(empty, 0, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOne, 0, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOne, 1, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 0, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 1, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 2, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 3, 0), ::testing::IsEmpty());
}
TEST(U2fParsingUtils, ExtractInBounds) {
EXPECT_THAT(Extract(kOne, 0, 1), ::testing::ElementsAreArray(kOne));
EXPECT_THAT(Extract(kOneTwoThree, 0, 1), ::testing::ElementsAreArray(kOne));
EXPECT_THAT(Extract(kOneTwoThree, 2, 1), ::testing::ElementsAreArray(kThree));
EXPECT_THAT(Extract(kOneTwoThree, 1, 2),
::testing::ElementsAreArray(kTwoThree));
EXPECT_THAT(Extract(kOneTwoThree, 0, 3),
::testing::ElementsAreArray(kOneTwoThree));
}
TEST(U2fParsingUtils, ExtractOutOfBounds) {
const std::vector<uint8_t> empty;
EXPECT_THAT(Extract(empty, 0, 1), ::testing::IsEmpty());
EXPECT_THAT(Extract(empty, 1, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOne, 0, 2), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOne, 1, 1), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOne, 2, 0), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 0, 4), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 1, 3), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 2, 2), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 3, 1), ::testing::IsEmpty());
EXPECT_THAT(Extract(kOneTwoThree, 4, 0), ::testing::IsEmpty());
}
TEST(U2fParsingUtils, ExtractSuffixEmpty) {
const std::vector<uint8_t> empty;
EXPECT_THAT(ExtractSuffix(empty, 0), ::testing::IsEmpty());
EXPECT_THAT(ExtractSuffix(kOne, 1), ::testing::IsEmpty());
EXPECT_THAT(ExtractSuffix(kOneTwoThree, 3), ::testing::IsEmpty());
}
TEST(U2fParsingUtils, ExtractSuffixInBounds) {
EXPECT_THAT(ExtractSuffix(kOne, 0), ::testing::ElementsAreArray(kOne));
EXPECT_THAT(ExtractSuffix(kOneTwoThree, 1),
::testing::ElementsAreArray(kTwoThree));
EXPECT_THAT(ExtractSuffix(kOneTwoThree, 2),
::testing::ElementsAreArray(kThree));
}
TEST(U2fParsingUtils, ExtractSuffixOutOfBounds) {
const std::vector<uint8_t> empty;
EXPECT_THAT(ExtractSuffix(empty, 1), ::testing::IsEmpty());
EXPECT_THAT(ExtractSuffix(kOne, 2), ::testing::IsEmpty());
EXPECT_THAT(ExtractSuffix(kOneTwoThree, 4), ::testing::IsEmpty());
}
} // namespace u2f_parsing_utils
} // namespace device
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