rippled
utils.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2016 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_CONDITIONS_UTILS_H
21 #define RIPPLE_CONDITIONS_UTILS_H
22 
23 #include <ripple/basics/strHex.h>
24 #include <ripple/conditions/impl/error.h>
25 #include <boost/dynamic_bitset.hpp>
26 #include <iomanip>
27 #include <limits>
28 #include <sstream>
29 #include <stdexcept>
30 #include <string>
31 #include <utility>
32 #include <vector>
33 
34 namespace ripple {
35 namespace cryptoconditions {
36 
37 // A collection of functions to decode binary blobs
38 // encoded with X.690 Distinguished Encoding Rules.
39 //
40 // This is a very trivial decoder and only implements
41 // the bare minimum needed to support PreimageSha256.
42 namespace der {
43 
44 // The preamble encapsulates the DER identifier and
45 // length octets:
46 struct Preamble
47 {
48  explicit Preamble() = default;
52 };
53 
54 inline bool
56 {
57  return (p.type & 0x20) == 0;
58 }
59 
60 inline bool
62 {
63  return !isPrimitive(p);
64 }
65 
66 inline bool
68 {
69  return (p.type & 0xC0) == 0;
70 }
71 
72 inline bool
74 {
75  return (p.type & 0xC0) == 0x40;
76 }
77 
78 inline bool
80 {
81  return (p.type & 0xC0) == 0x80;
82 }
83 
84 inline bool
86 {
87  return (p.type & 0xC0) == 0xC0;
88 }
89 
90 inline Preamble
92 {
93  Preamble p;
94 
95  if (s.size() < 2)
96  {
98  return p;
99  }
100 
101  p.type = s[0] & 0xE0;
102  p.tag = s[0] & 0x1F;
103 
104  s += 1;
105 
106  if (p.tag == 0x1F)
107  { // Long tag form, which we do not support:
108  ec = error::long_tag;
109  return p;
110  }
111 
112  p.length = s[0];
113  s += 1;
114 
115  if (p.length & 0x80)
116  { // Long form length:
117  std::size_t const cnt = p.length & 0x7F;
118 
119  if (cnt == 0)
120  {
122  return p;
123  }
124 
125  if (cnt > sizeof(std::size_t))
126  {
127  ec = error::large_size;
128  return p;
129  }
130 
131  if (cnt > s.size())
132  {
134  return p;
135  }
136 
137  p.length = 0;
138 
139  for (std::size_t i = 0; i != cnt; ++i)
140  p.length = (p.length << 8) + s[i];
141 
142  s += cnt;
143 
144  if (p.length == 0)
145  {
147  return p;
148  }
149  }
150 
151  return p;
152 }
153 
154 inline Buffer
156 {
157  if (count > s.size())
158  {
160  return {};
161  }
162 
163  if (count > 65535)
164  {
165  ec = error::large_size;
166  return {};
167  }
168 
169  Buffer b(s.data(), count);
170  s += count;
171  return b;
172 }
173 
174 template <class Integer>
175 Integer
177 {
178  Integer v{0};
179 
180  if (s.empty())
181  {
182  // can never have zero sized integers
184  return v;
185  }
186 
187  if (count > s.size())
188  {
190  return v;
191  }
192 
193  const bool isSigned = std::numeric_limits<Integer>::is_signed;
194  // unsigned types may have a leading zero octet
195  const size_t maxLength = isSigned ? sizeof(Integer) : sizeof(Integer) + 1;
196  if (count > maxLength)
197  {
198  ec = error::large_size;
199  return v;
200  }
201 
202  if (!isSigned && (s[0] & (1 << 7)))
203  {
204  // trying to decode a negative number into a positive value
206  return v;
207  }
208 
209  if (!isSigned && count == sizeof(Integer) + 1 && s[0])
210  {
211  // since integers are coded as two's complement, the first byte may
212  // be zero for unsigned reps
214  return v;
215  }
216 
217  v = 0;
218  for (size_t i = 0; i < count; ++i)
219  v = (v << 8) | (s[i] & 0xff);
220 
221  if (isSigned && (s[0] & (1 << 7)))
222  {
223  for (int i = count; i < sizeof(Integer); ++i)
224  v |= (Integer(0xff) << (8 * i));
225  }
226  s += count;
227  return v;
228 }
229 
230 } // namespace der
231 } // namespace cryptoconditions
232 } // namespace ripple
233 
234 #endif
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:80
sstream
ripple::cryptoconditions::der::parseOctetString
Buffer parseOctetString(Slice &s, std::uint32_t count, std::error_code &ec)
Definition: utils.h:155
ripple::cryptoconditions::der::Preamble::Preamble
Preamble()=default
utility
ripple::cryptoconditions::der::isApplication
bool isApplication(Preamble const &p)
Definition: utils.h:73
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
vector
ripple::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:97
ripple::cryptoconditions::der::parseInteger
Integer parseInteger(Slice &s, std::size_t count, std::error_code &ec)
Definition: utils.h:176
ripple::Buffer
Like std::vector<char> but better.
Definition: Buffer.h:35
ripple::Slice::empty
bool empty() const noexcept
Return true if the byte range is empty.
Definition: Slice.h:69
ripple::cryptoconditions::der::isConstructed
bool isConstructed(Preamble const &p)
Definition: utils.h:61
std::error_code
STL class.
ripple::cryptoconditions::der::isPrimitive
bool isPrimitive(Preamble const &p)
Definition: utils.h:55
ripple::cryptoconditions::der::isContextSpecific
bool isContextSpecific(Preamble const &p)
Definition: utils.h:79
stdexcept
ripple::cryptoconditions::error::short_preamble
@ short_preamble
ripple::cryptoconditions::error::buffer_underfull
@ buffer_underfull
ripple::cryptoconditions::der::Preamble::length
std::size_t length
Definition: utils.h:51
ripple::cryptoconditions::der::isPrivate
bool isPrivate(Preamble const &p)
Definition: utils.h:85
ripple::cryptoconditions::der::parsePreamble
Preamble parsePreamble(Slice &s, std::error_code &ec)
Definition: utils.h:91
ripple::cryptoconditions::der::Preamble::tag
std::size_t tag
Definition: utils.h:50
std::uint8_t
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
iomanip
ripple::cryptoconditions::error::long_tag
@ long_tag
limits
ripple::cryptoconditions::der::Preamble
Definition: utils.h:46
ripple::cryptoconditions::der::isUniversal
bool isUniversal(Preamble const &p)
Definition: utils.h:67
std::size_t
ripple::cryptoconditions::der::Preamble::type
std::uint8_t type
Definition: utils.h:49
ripple::cryptoconditions::error::large_size
@ large_size
std::numeric_limits
ripple::cryptoconditions::error::malformed_encoding
@ malformed_encoding
string