| // Copyright 2017 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/fido_parsing_utils.h" |
| |
| #include "base/logging.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/strings/stringprintf.h" |
| |
| namespace device { |
| namespace fido_parsing_utils { |
| |
| namespace { |
| |
| constexpr bool AreSpansDisjoint(base::span<const uint8_t> lhs, |
| base::span<const uint8_t> rhs) { |
| return lhs.data() + lhs.size() <= rhs.data() || // [lhs)...[rhs) |
| rhs.data() + rhs.size() <= lhs.data(); // [rhs)...[lhs) |
| } |
| |
| } // namespace |
| |
| const char kEs256[] = "ES256"; |
| |
| std::vector<uint8_t> Materialize(base::span<const uint8_t> span) { |
| return std::vector<uint8_t>(span.begin(), span.end()); |
| } |
| |
| base::Optional<std::vector<uint8_t>> MaterializeOrNull( |
| base::Optional<base::span<const uint8_t>> span) { |
| if (span) |
| return Materialize(*span); |
| return base::nullopt; |
| } |
| |
| void Append(std::vector<uint8_t>* target, base::span<const uint8_t> in_values) { |
| CHECK(AreSpansDisjoint(*target, in_values)); |
| target->insert(target->end(), in_values.begin(), in_values.end()); |
| } |
| |
| std::vector<uint8_t> Extract(base::span<const uint8_t> span, |
| size_t pos, |
| size_t length) { |
| return Materialize(ExtractSpan(span, 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); |
| } |
| |
| std::vector<base::span<const uint8_t>> SplitSpan(base::span<const uint8_t> span, |
| size_t max_chunk_size) { |
| DCHECK_NE(0u, max_chunk_size); |
| std::vector<base::span<const uint8_t>> chunks; |
| const size_t num_chunks = (span.size() + max_chunk_size - 1) / max_chunk_size; |
| chunks.reserve(num_chunks); |
| while (!span.empty()) { |
| const size_t chunk_size = std::min(span.size(), max_chunk_size); |
| chunks.emplace_back(span.subspan(0, chunk_size)); |
| span = span.subspan(chunk_size); |
| } |
| |
| return chunks; |
| } |
| |
| std::array<uint8_t, crypto::kSHA256Length> CreateSHA256Hash( |
| base::StringPiece data) { |
| std::array<uint8_t, crypto::kSHA256Length> hashed_data; |
| crypto::SHA256HashString(data, hashed_data.data(), hashed_data.size()); |
| return hashed_data; |
| } |
| |
| base::StringPiece ConvertToStringPiece(base::span<const uint8_t> data) { |
| return {reinterpret_cast<const char*>(data.data()), data.size()}; |
| } |
| |
| std::string ConvertBytesToUuid(base::span<const uint8_t, 16> bytes) { |
| uint64_t most_significant_bytes = 0; |
| for (size_t i = 0; i < sizeof(uint64_t); i++) { |
| most_significant_bytes |= base::strict_cast<uint64_t>(bytes[i]) |
| << 8 * (7 - i); |
| } |
| |
| uint64_t least_significant_bytes = 0; |
| for (size_t i = 0; i < sizeof(uint64_t); i++) { |
| least_significant_bytes |= base::strict_cast<uint64_t>(bytes[i + 8]) |
| << 8 * (7 - i); |
| } |
| |
| return base::StringPrintf( |
| "%08x-%04x-%04x-%04x-%012llx", |
| static_cast<unsigned int>(most_significant_bytes >> 32), |
| static_cast<unsigned int>((most_significant_bytes >> 16) & 0x0000ffff), |
| static_cast<unsigned int>(most_significant_bytes & 0x0000ffff), |
| static_cast<unsigned int>(least_significant_bytes >> 48), |
| least_significant_bytes & 0x0000ffff'ffffffffULL); |
| } |
| |
| } // namespace fido_parsing_utils |
| } // namespace device |