Allow CBOR maps to use integer keys
Currently, CBOR maps only permit keys to be UTF-8 strings. Add support
for unsigned integer keys. Support for negative integer type keys will
be integrated as CL 777807 is lands.
Bug: 786218
Change-Id: Id28864a9c62d0b0d93e71a663b6e8b2b84b2de95
Reviewed-on: https://chromium-review.googlesource.com/781207
Commit-Queue: Jun Choi <[email protected]>
Reviewed-by: Chris Palmer <[email protected]>
Reviewed-by: Balazs Engedy <[email protected]>
Reviewed-by: Jeffrey Yasskin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#524223}
diff --git a/content/browser/webauth/cbor/cbor_values.h b/content/browser/webauth/cbor/cbor_values.h
index 83bbd49..bea7b38c 100644
--- a/content/browser/webauth/cbor/cbor_values.h
+++ b/content/browser/webauth/cbor/cbor_values.h
@@ -29,8 +29,7 @@
//
// The sort order defined in CTAP is:
// • If the major types are different, the one with the lower value in
- // numerical order sorts earlier. (Moot in this code because all keys
- // are strings.)
+ // numerical order sorts earlier.
// • If two keys have different lengths, the shorter one sorts earlier.
// • If two keys have the same length, the one with the lower value in
// (byte-wise) lexical order sorts earlier.
@@ -38,17 +37,32 @@
// See section 6 of https://fidoalliance.org/specs/fido-v2.0-rd-20170927/
// fido-client-to-authenticator-protocol-v2.0-rd-20170927.html.
//
- // The sort order defined in
- // https://tools.ietf.org/html/rfc7049#section-3.9 is similar to the CTAP
- // order implemented here, but it sorts purely by serialised key and
- // doesn't specify that major types are compared first. Thus the shortest
- // key sorts first by the RFC rules (irrespective of the major type), but
- // may not by CTAP rules.
- bool operator()(const base::StringPiece& a,
- const base::StringPiece& b) const {
- const size_t a_size = a.size();
- const size_t b_size = b.size();
- return std::tie(a_size, a) < std::tie(b_size, b);
+ // THE CTAP SORT ORDER IMPLEMENTED HERE DIFFERS FROM THE CANONICAL CBOR
+ // ORDER defined in https://tools.ietf.org/html/rfc7049#section-3.9, in that
+ // the latter sorts purely by serialised key and doesn't specify that major
+ // types are compared first. Thus the shortest key sorts first by the RFC
+ // rules (irrespective of the major type), but may not by CTAP rules.
+ bool operator()(const CBORValue& a, const CBORValue& b) const {
+ DCHECK((a.is_unsigned() || a.is_string()) &&
+ (b.is_unsigned() || b.is_string()));
+ if (a.type() != b.type())
+ return a.type() < b.type();
+ switch (a.type()) {
+ case Type::UNSIGNED:
+ return a.GetUnsigned() < b.GetUnsigned();
+ case Type::STRING: {
+ const auto& a_str = a.GetString();
+ const size_t a_length = a_str.size();
+ const auto& b_str = b.GetString();
+ const size_t b_length = b_str.size();
+ return std::tie(a_length, a_str) < std::tie(b_length, b_str);
+ }
+ default:
+ break;
+ }
+
+ NOTREACHED();
+ return false;
}
using is_transparent = void;
@@ -56,7 +70,7 @@
using BinaryValue = std::vector<uint8_t>;
using ArrayValue = std::vector<CBORValue>;
- using MapValue = base::flat_map<std::string, CBORValue, CTAPLess>;
+ using MapValue = base::flat_map<CBORValue, CBORValue, CTAPLess>;
enum class Type {
UNSIGNED = 0,
@@ -107,7 +121,7 @@
bool is_map() const { return type() == Type::MAP; }
// These will all fatally assert if the type doesn't match.
- uint64_t GetUnsigned() const;
+ const uint64_t& GetUnsigned() const;
const BinaryValue& GetBytestring() const;
// Returned string may contain NUL characters.
const std::string& GetString() const;