fido_parsing_utils.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef DEVICE_FIDO_FIDO_PARSING_UTILS_H_
  5. #define DEVICE_FIDO_FIDO_PARSING_UTILS_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <algorithm>
  9. #include <array>
  10. #include <iterator>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/component_export.h"
  14. #include "base/containers/span.h"
  15. #include "base/strings/string_piece.h"
  16. #include "components/cbor/values.h"
  17. #include "crypto/sha2.h"
  18. #include "third_party/abseil-cpp/absl/types/optional.h"
  19. namespace device {
  20. namespace fido_parsing_utils {
  21. // Comparator object that calls std::lexicographical_compare on the begin and
  22. // end iterators of the passed in ranges. Useful when comparing sequence
  23. // containers that are of different types, but have similar semantics.
  24. struct RangeLess {
  25. template <typename T, typename U>
  26. constexpr bool operator()(T&& lhs, U&& rhs) const {
  27. using std::begin;
  28. using std::end;
  29. return std::lexicographical_compare(begin(lhs), end(lhs), begin(rhs),
  30. end(rhs));
  31. }
  32. using is_transparent = void;
  33. };
  34. // U2FResponse offsets. The format of a U2F response is defined in
  35. // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-response-message-success
  36. COMPONENT_EXPORT(DEVICE_FIDO)
  37. extern const uint32_t kU2fResponseKeyHandleLengthPos;
  38. COMPONENT_EXPORT(DEVICE_FIDO)
  39. extern const uint32_t kU2fResponseKeyHandleStartPos;
  40. COMPONENT_EXPORT(DEVICE_FIDO) extern const char kEs256[];
  41. // Returns a materialized copy of |span|, that is, a vector with the same
  42. // elements.
  43. COMPONENT_EXPORT(DEVICE_FIDO)
  44. std::vector<uint8_t> Materialize(base::span<const uint8_t> span);
  45. COMPONENT_EXPORT(DEVICE_FIDO)
  46. absl::optional<std::vector<uint8_t>> MaterializeOrNull(
  47. absl::optional<base::span<const uint8_t>> span);
  48. // Returns a materialized copy of the static |span|, that is, an array with the
  49. // same elements.
  50. template <size_t N>
  51. std::array<uint8_t, N> Materialize(base::span<const uint8_t, N> span) {
  52. std::array<uint8_t, N> array;
  53. std::copy(span.begin(), span.end(), array.begin());
  54. return array;
  55. }
  56. // Appends |in_values| to the end of |target|. The underlying container for
  57. // |in_values| should *not* be |target|.
  58. COMPONENT_EXPORT(DEVICE_FIDO)
  59. void Append(std::vector<uint8_t>* target, base::span<const uint8_t> in_values);
  60. // Safely extracts, with bound checking, a contiguous subsequence of |span| of
  61. // the given |length| and starting at |pos|. Returns an empty vector/span if the
  62. // requested range is out-of-bound.
  63. COMPONENT_EXPORT(DEVICE_FIDO)
  64. std::vector<uint8_t> Extract(base::span<const uint8_t> span,
  65. size_t pos,
  66. size_t length);
  67. COMPONENT_EXPORT(DEVICE_FIDO)
  68. base::span<const uint8_t> ExtractSpan(base::span<const uint8_t> span,
  69. size_t pos,
  70. size_t length);
  71. // Safely extracts, with bound checking, the suffix of the given |span| starting
  72. // at the given position |pos|. Returns an empty vector/span if the requested
  73. // starting position is out-of-bound.
  74. COMPONENT_EXPORT(DEVICE_FIDO)
  75. std::vector<uint8_t> ExtractSuffix(base::span<const uint8_t> span, size_t pos);
  76. COMPONENT_EXPORT(DEVICE_FIDO)
  77. base::span<const uint8_t> ExtractSuffixSpan(base::span<const uint8_t> span,
  78. size_t pos);
  79. template <size_t N>
  80. bool ExtractArray(base::span<const uint8_t> span,
  81. size_t pos,
  82. std::array<uint8_t, N>* array) {
  83. const auto extracted_span = ExtractSpan(span, pos, N);
  84. if (extracted_span.size() != N)
  85. return false;
  86. std::copy(extracted_span.begin(), extracted_span.end(), array->begin());
  87. return true;
  88. }
  89. // Partitions |span| into N = ⌈span.size() / max_chunk_size⌉ consecutive chunks.
  90. // The first N-1 chunks are of size |max_chunk_size|, and the Nth chunk is of
  91. // size span.size() % max_chunk_size. |max_chunk_size| must be greater than 0.
  92. // Returns an empty vector in case |span| is empty.
  93. COMPONENT_EXPORT(DEVICE_FIDO)
  94. std::vector<base::span<const uint8_t>> SplitSpan(base::span<const uint8_t> span,
  95. size_t max_chunk_size);
  96. COMPONENT_EXPORT(DEVICE_FIDO)
  97. std::array<uint8_t, crypto::kSHA256Length> CreateSHA256Hash(
  98. base::StringPiece data);
  99. COMPONENT_EXPORT(DEVICE_FIDO)
  100. base::StringPiece ConvertToStringPiece(base::span<const uint8_t> data);
  101. // Convert byte array into GUID formatted string as defined by RFC 4122.
  102. // As we are converting 128 bit UUID, |bytes| must be have length of 16.
  103. // https://tools.ietf.org/html/rfc4122
  104. COMPONENT_EXPORT(DEVICE_FIDO)
  105. std::string ConvertBytesToUuid(base::span<const uint8_t, 16> bytes);
  106. // Copies the contents of the bytestring, keyed by |key|, from |map| into |out|.
  107. // Returns true on success or false if the key if not found, the value is not a
  108. // bytestring, or the value has the wrong length.
  109. template <size_t N>
  110. bool CopyCBORBytestring(std::array<uint8_t, N>* out,
  111. const cbor::Value::MapValue& map,
  112. int key) {
  113. const auto it = map.find(cbor::Value(key));
  114. if (it == map.end() || !it->second.is_bytestring()) {
  115. return false;
  116. }
  117. const std::vector<uint8_t> bytestring = it->second.GetBytestring();
  118. return ExtractArray(bytestring, /*pos=*/0, out);
  119. }
  120. constexpr std::array<uint8_t, 4> Uint32LittleEndian(uint32_t value) {
  121. return {static_cast<uint8_t>(value), static_cast<uint8_t>(value >> 8),
  122. static_cast<uint8_t>(value >> 16), static_cast<uint8_t>(value >> 24)};
  123. }
  124. constexpr std::array<uint8_t, 8> Uint64LittleEndian(uint64_t value) {
  125. return {static_cast<uint8_t>(value), static_cast<uint8_t>(value >> 8),
  126. static_cast<uint8_t>(value >> 16), static_cast<uint8_t>(value >> 24),
  127. static_cast<uint8_t>(value >> 32), static_cast<uint8_t>(value >> 40),
  128. static_cast<uint8_t>(value >> 48), static_cast<uint8_t>(value >> 56)};
  129. }
  130. } // namespace fido_parsing_utils
  131. } // namespace device
  132. #endif // DEVICE_FIDO_FIDO_PARSING_UTILS_H_