xrpld
Loading...
Searching...
No Matches
include/xrpl/conditions/detail/utils.h
1#pragma once
2
3#include <xrpl/basics/Buffer.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/conditions/detail/error.h>
6
7#include <boost/dynamic_bitset.hpp>
8
9#include <limits>
10
11// A collection of functions to decode binary blobs
12// encoded with X.690 Distinguished Encoding Rules.
13//
14// This is a very trivial decoder and only implements
15// the bare minimum needed to support PreimageSha256.
17
18// The preamble encapsulates the DER identifier and
19// length octets:
21{
22 explicit Preamble() = default;
26};
27
28inline bool
30{
31 return (p.type & 0x20) == 0;
32}
33
34inline bool
36{
37 return !isPrimitive(p);
38}
39
40inline bool
42{
43 return (p.type & 0xC0) == 0;
44}
45
46inline bool
48{
49 return (p.type & 0xC0) == 0x40;
50}
51
52inline bool
54{
55 return (p.type & 0xC0) == 0x80;
56}
57
58inline bool
60{
61 return (p.type & 0xC0) == 0xC0;
62}
63
64inline Preamble
66{
67 Preamble p;
68
69 if (s.size() < 2)
70 {
72 return p;
73 }
74
75 p.type = s[0] & 0xE0;
76 p.tag = s[0] & 0x1F;
77
78 s += 1;
79
80 if (p.tag == 0x1F)
81 { // Long tag form, which we do not support:
82 ec = Error::LongTag;
83 return p;
84 }
85
86 p.length = s[0];
87 s += 1;
88
89 if ((p.length & 0x80) != 0u)
90 { // Long form length:
91 std::size_t const cnt = p.length & 0x7F;
92
93 if (cnt == 0)
94 {
96 return p;
97 }
98
99 if (cnt > sizeof(std::size_t))
100 {
101 ec = Error::LargeSize;
102 return p;
103 }
104
105 if (cnt > s.size())
106 {
108 return p;
109 }
110
111 p.length = 0;
112
113 for (std::size_t i = 0; i != cnt; ++i)
114 p.length = (p.length << 8) + s[i];
115
116 s += cnt;
117
118 if (p.length == 0)
119 {
121 return p;
122 }
123 }
124
125 return p;
126}
127
128inline Buffer
130{
131 if (count > s.size())
132 {
134 return {};
135 }
136
137 if (count > 65535)
138 {
139 ec = Error::LargeSize;
140 return {};
141 }
142
143 Buffer b(s.data(), count);
144 s += count;
145 return b;
146}
147
148template <class Integer>
149Integer
151{
152 Integer v{0};
153
154 if (s.empty())
155 {
156 // can never have zero sized integers
158 return v;
159 }
160
161 if (count > s.size())
162 {
164 return v;
165 }
166
167 bool const isSigned = std::numeric_limits<Integer>::is_signed;
168 // unsigned types may have a leading zero octet
169 size_t const maxLength = isSigned ? sizeof(Integer) : sizeof(Integer) + 1;
170 if (count > maxLength)
171 {
172 ec = Error::LargeSize;
173 return v;
174 }
175
176 if (!isSigned && (s[0] & (1 << 7)))
177 {
178 // trying to decode a negative number into a positive value
180 return v;
181 }
182
183 if (!isSigned && count == sizeof(Integer) + 1 && s[0])
184 {
185 // since integers are coded as two's complement, the first byte may
186 // be zero for unsigned reps
188 return v;
189 }
190
191 v = 0;
192 for (size_t i = 0; i < count; ++i)
193 v = (v << 8) | (s[i] & 0xff);
194
195 if (isSigned && (s[0] & (1 << 7)))
196 {
197 for (int i = count; i < sizeof(Integer); ++i)
198 v |= (Integer(0xff) << (8 * i));
199 }
200 s += count;
201 return v;
202}
203
204} // namespace xrpl::cryptoconditions::der
Like std::vector<char> but better.
Definition Buffer.h:16
An immutable linear range of bytes.
Definition Slice.h:26
bool empty() const noexcept
Return true if the byte range is empty.
Definition Slice.h:50
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Slice.h:78
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition Slice.h:61
Integer parseInteger(Slice &s, std::size_t count, std::error_code &ec)
Buffer parseOctetString(Slice &s, std::uint32_t count, std::error_code &ec)
Preamble parsePreamble(Slice &s, std::error_code &ec)