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 <limits>
27 #include <stdexcept>
28 #include <string>
29 #include <vector>
30 #include <iomanip>
31 #include <sstream>
32 #include <utility>
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
55 bool
57 {
58  return (p.type & 0x20) == 0;
59 }
60 
61 inline
62 bool
64 {
65  return !isPrimitive(p);
66 }
67 
68 inline
69 bool
71 {
72  return (p.type & 0xC0) == 0;
73 }
74 
75 inline
76 bool
78 {
79  return (p.type & 0xC0) == 0x40;
80 }
81 
82 inline
83 bool
85 {
86  return (p.type & 0xC0) == 0x80;
87 }
88 
89 inline
90 bool
92 {
93  return (p.type & 0xC0) == 0xC0;
94 }
95 
96 inline
97 Preamble
99 {
100  Preamble p;
101 
102  if (s.size() < 2)
103  {
105  return p;
106  }
107 
108  p.type = s[0] & 0xE0;
109  p.tag = s[0] & 0x1F;
110 
111  s += 1;
112 
113  if (p.tag == 0x1F)
114  { // Long tag form, which we do not support:
115  ec = error::long_tag;
116  return p;
117  }
118 
119  p.length = s[0];
120  s += 1;
121 
122  if (p.length & 0x80)
123  { // Long form length:
124  std::size_t const cnt = p.length & 0x7F;
125 
126  if (cnt == 0)
127  {
129  return p;
130  }
131 
132  if (cnt > sizeof(std::size_t))
133  {
134  ec = error::large_size;
135  return p;
136  }
137 
138  if (cnt > s.size())
139  {
141  return p;
142  }
143 
144  p.length = 0;
145 
146  for (std::size_t i = 0; i != cnt; ++i)
147  p.length = (p.length << 8) + s[i];
148 
149  s += cnt;
150 
151  if (p.length == 0)
152  {
154  return p;
155  }
156  }
157 
158  return p;
159 }
160 
161 inline
162 Buffer
164 {
165  if (count > s.size())
166  {
168  return {};
169  }
170 
171  if (count > 65535)
172  {
173  ec = error::large_size;
174  return {};
175  }
176 
177  Buffer b(s.data(), count);
178  s += count;
179  return b;
180 }
181 
182 template <class Integer>
183 Integer
185 {
186  Integer v{0};
187 
188  if (s.empty())
189  {
190  // can never have zero sized integers
192  return v;
193  }
194 
195  if (count > s.size())
196  {
198  return v;
199  }
200 
201  const bool isSigned = std::numeric_limits<Integer>::is_signed;
202  // unsigned types may have a leading zero octet
203  const size_t maxLength = isSigned ? sizeof(Integer) : sizeof(Integer) + 1;
204  if (count > maxLength)
205  {
206  ec = error::large_size;
207  return v;
208  }
209 
210  if (!isSigned && (s[0] & (1 << 7)))
211  {
212  // trying to decode a negative number into a positive value
214  return v;
215  }
216 
217  if (!isSigned && count == sizeof(Integer) + 1 && s[0])
218  {
219  // since integers are coded as two's complement, the first byte may
220  // be zero for unsigned reps
222  return v;
223  }
224 
225  v = 0;
226  for (size_t i = 0; i < count; ++i)
227  v = (v << 8) | (s[i] & 0xff);
228 
229  if (isSigned && (s[0] & (1 << 7)))
230  {
231  for (int i = count; i < sizeof(Integer); ++i)
232  v |= (Integer(0xff) << (8 * i));
233  }
234  s += count;
235  return v;
236 }
237 
238 } // der
239 } // cryptoconditions
240 } // ripple
241 
242 #endif
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:77
sstream
ripple::cryptoconditions::der::parseOctetString
Buffer parseOctetString(Slice &s, std::uint32_t count, std::error_code &ec)
Definition: utils.h:163
ripple::cryptoconditions::der::Preamble::Preamble
Preamble()=default
utility
ripple::cryptoconditions::der::isApplication
bool isApplication(Preamble const &p)
Definition: utils.h:77
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:43
vector
ripple::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:87
ripple::cryptoconditions::der::parseInteger
Integer parseInteger(Slice &s, std::size_t count, std::error_code &ec)
Definition: utils.h:184
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:67
ripple::cryptoconditions::der::isConstructed
bool isConstructed(Preamble const &p)
Definition: utils.h:63
std::error_code
STL class.
ripple::cryptoconditions::der::isPrimitive
bool isPrimitive(Preamble const &p)
Definition: utils.h:56
ripple::cryptoconditions::der::isContextSpecific
bool isContextSpecific(Preamble const &p)
Definition: utils.h:84
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:91
ripple::cryptoconditions::der::parsePreamble
Preamble parsePreamble(Slice &s, std::error_code &ec)
Definition: utils.h:98
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:70
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