blob: 9b35fda17c931ff6a5782d0baad9e33d32e680b0 [file] [log] [blame]
Kim Paulhamus6efcf4952017-09-14 22:46:271// 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
5#ifndef CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_
6#define CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_
7
Kim Paulhamus6efcf4952017-09-14 22:46:278#include <string>
Adam Langley68672fd2017-10-17 19:35:279#include <tuple>
Kim Paulhamus6efcf4952017-09-14 22:46:2710#include <vector>
11
12#include "base/containers/flat_map.h"
13#include "base/macros.h"
Adam Langleydf763d792017-11-28 19:20:1514#include "base/strings/string_piece.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2715#include "content/common/content_export.h"
16
17namespace content {
18
19// A class for Concise Binary Object Representation (CBOR) values.
20// This does not support:
21// * Negative integers.
22// * Floating-point numbers.
23// * Indefinite-length encodings.
24class CONTENT_EXPORT CBORValue {
25 public:
Adam Langley68672fd2017-10-17 19:35:2726 struct CTAPLess {
27 // Comparison predicate to order keys in a dictionary as required by the
28 // Client-to-Authenticator Protocol (CTAP) spec 2.0.
29 //
30 // The sort order defined in CTAP is:
31 // • If the major types are different, the one with the lower value in
Jun Choi98a59e462017-12-14 23:04:0932 // numerical order sorts earlier.
Adam Langley68672fd2017-10-17 19:35:2733 // • If two keys have different lengths, the shorter one sorts earlier.
34 // • If two keys have the same length, the one with the lower value in
35 // (byte-wise) lexical order sorts earlier.
36 //
37 // See section 6 of https://fidoalliance.org/specs/fido-v2.0-rd-20170927/
Adam Langleydf763d792017-11-28 19:20:1538 // fido-client-to-authenticator-protocol-v2.0-rd-20170927.html.
39 //
Jun Choi98a59e462017-12-14 23:04:0940 // THE CTAP SORT ORDER IMPLEMENTED HERE DIFFERS FROM THE CANONICAL CBOR
41 // ORDER defined in https://tools.ietf.org/html/rfc7049#section-3.9, in that
42 // the latter sorts purely by serialised key and doesn't specify that major
43 // types are compared first. Thus the shortest key sorts first by the RFC
44 // rules (irrespective of the major type), but may not by CTAP rules.
45 bool operator()(const CBORValue& a, const CBORValue& b) const {
46 DCHECK((a.is_unsigned() || a.is_string()) &&
47 (b.is_unsigned() || b.is_string()));
48 if (a.type() != b.type())
49 return a.type() < b.type();
50 switch (a.type()) {
51 case Type::UNSIGNED:
52 return a.GetUnsigned() < b.GetUnsigned();
53 case Type::STRING: {
54 const auto& a_str = a.GetString();
55 const size_t a_length = a_str.size();
56 const auto& b_str = b.GetString();
57 const size_t b_length = b_str.size();
58 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
59 }
60 default:
61 break;
62 }
63
64 NOTREACHED();
65 return false;
Adam Langley68672fd2017-10-17 19:35:2766 }
67
Adam Langley68672fd2017-10-17 19:35:2768 using is_transparent = void;
69 };
70
Kim Paulhamus6efcf4952017-09-14 22:46:2771 using BinaryValue = std::vector<uint8_t>;
72 using ArrayValue = std::vector<CBORValue>;
Jun Choi98a59e462017-12-14 23:04:0973 using MapValue = base::flat_map<CBORValue, CBORValue, CTAPLess>;
Kim Paulhamus6efcf4952017-09-14 22:46:2774
75 enum class Type {
Jun Choi6d30c4a2017-12-09 01:10:3276 UNSIGNED = 0,
77 BYTE_STRING = 2,
78 STRING = 3,
79 ARRAY = 4,
80 MAP = 5,
Jun Choi07540c62017-12-21 02:51:4381 SIMPLE_VALUE = 7,
Jun Choi6d30c4a2017-12-09 01:10:3282 NONE = -1,
Kim Paulhamus6efcf4952017-09-14 22:46:2783 };
84
Jun Choi07540c62017-12-21 02:51:4385 enum class SimpleValue {
86 FALSE_VALUE = 20,
87 TRUE_VALUE = 21,
88 NULL_VALUE = 22,
89 UNDEFINED = 23,
90 };
91
Kim Paulhamus6efcf4952017-09-14 22:46:2792 CBORValue(CBORValue&& that) noexcept;
93 CBORValue() noexcept; // A NONE value.
94
95 explicit CBORValue(Type type);
96 explicit CBORValue(uint64_t in_unsigned);
97
98 explicit CBORValue(const BinaryValue& in_bytes);
99 explicit CBORValue(BinaryValue&& in_bytes) noexcept;
100
101 explicit CBORValue(const char* in_string);
102 explicit CBORValue(std::string&& in_string) noexcept;
103 explicit CBORValue(base::StringPiece in_string);
104
105 explicit CBORValue(const ArrayValue& in_array);
106 explicit CBORValue(ArrayValue&& in_array) noexcept;
107
108 explicit CBORValue(const MapValue& in_map);
109 explicit CBORValue(MapValue&& in_map) noexcept;
110
Jun Choi07540c62017-12-21 02:51:43111 explicit CBORValue(SimpleValue in_simple);
112
Kim Paulhamus6efcf4952017-09-14 22:46:27113 CBORValue& operator=(CBORValue&& that) noexcept;
114
115 ~CBORValue();
116
117 // CBORValue's copy constructor and copy assignment operator are deleted.
118 // Use this to obtain a deep copy explicitly.
119 CBORValue Clone() const;
120
121 // Returns the type of the value stored by the current Value object.
122 Type type() const { return type_; }
123
124 // Returns true if the current object represents a given type.
125 bool is_type(Type type) const { return type == type_; }
126 bool is_none() const { return type() == Type::NONE; }
127 bool is_unsigned() const { return type() == Type::UNSIGNED; }
Jun Choi6d30c4a2017-12-09 01:10:32128 bool is_bytestring() const { return type() == Type::BYTE_STRING; }
Kim Paulhamus6efcf4952017-09-14 22:46:27129 bool is_string() const { return type() == Type::STRING; }
130 bool is_array() const { return type() == Type::ARRAY; }
131 bool is_map() const { return type() == Type::MAP; }
Jun Choi07540c62017-12-21 02:51:43132 bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
Kim Paulhamus6efcf4952017-09-14 22:46:27133
134 // These will all fatally assert if the type doesn't match.
Jun Choi98a59e462017-12-14 23:04:09135 const uint64_t& GetUnsigned() const;
Jun Choi07540c62017-12-21 02:51:43136 SimpleValue GetSimpleValue() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27137 const BinaryValue& GetBytestring() const;
Jun Choi47be22c2017-12-14 07:55:16138 // Returned string may contain NUL characters.
Kim Paulhamus6efcf4952017-09-14 22:46:27139 const std::string& GetString() const;
140 const ArrayValue& GetArray() const;
141 const MapValue& GetMap() const;
142
143 private:
144 Type type_;
145
146 union {
Jun Choi07540c62017-12-21 02:51:43147 SimpleValue simple_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27148 uint64_t unsigned_value_;
Daniel Cheng9eb43fd342017-10-10 21:28:37149 BinaryValue bytestring_value_;
150 std::string string_value_;
151 ArrayValue array_value_;
152 MapValue map_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27153 };
154
155 void InternalMoveConstructFrom(CBORValue&& that);
156 void InternalCleanup();
157
158 DISALLOW_COPY_AND_ASSIGN(CBORValue);
159};
160} // namespace content
161
Daniel Cheng9eb43fd342017-10-10 21:28:37162#endif // CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_