rippled
Condition.cpp
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 #include <ripple/basics/contract.h>
21 #include <ripple/conditions/Condition.h>
22 #include <ripple/conditions/Fulfillment.h>
23 #include <ripple/conditions/impl/PreimageSha256.h>
24 #include <ripple/conditions/impl/utils.h>
25 #include <boost/optional.hpp>
26 #include <boost/regex.hpp>
27 #include <iostream>
28 #include <vector>
29 
30 namespace ripple {
31 namespace cryptoconditions {
32 
33 namespace detail {
34 // The binary encoding of conditions differs based on their
35 // type. All types define at least a fingerprint and cost
36 // sub-field. Some types, such as the compound condition
37 // types, define additional sub-fields that are required to
38 // convey essential properties of the cryptocondition (such
39 // as the sub-types used by sub-conditions in the case of
40 // the compound types).
41 //
42 // Conditions are encoded as follows:
43 //
44 // Condition ::= CHOICE {
45 // preimageSha256 [0] SimpleSha256Condition,
46 // prefixSha256 [1] CompoundSha256Condition,
47 // thresholdSha256 [2] CompoundSha256Condition,
48 // rsaSha256 [3] SimpleSha256Condition,
49 // ed25519Sha256 [4] SimpleSha256Condition
50 // }
51 //
52 // SimpleSha256Condition ::= SEQUENCE {
53 // fingerprint OCTET STRING (SIZE(32)),
54 // cost INTEGER (0..4294967295)
55 // }
56 //
57 // CompoundSha256Condition ::= SEQUENCE {
58 // fingerprint OCTET STRING (SIZE(32)),
59 // cost INTEGER (0..4294967295),
60 // subtypes ConditionTypes
61 // }
62 //
63 // ConditionTypes ::= BIT STRING {
64 // preImageSha256 (0),
65 // prefixSha256 (1),
66 // thresholdSha256 (2),
67 // rsaSha256 (3),
68 // ed25519Sha256 (4)
69 // }
70 
72 
75 {
76  using namespace der;
77 
78  auto p = parsePreamble(s, ec);
79 
80  if (ec)
81  return {};
82 
83  if (!isPrimitive(p) || !isContextSpecific(p))
84  {
86  return {};
87  }
88 
89  if (p.tag != 0)
90  {
92  return {};
93  }
94 
95  if (p.length != fingerprintSize)
96  {
98  return {};
99  }
100 
101  Buffer b = parseOctetString(s, p.length, ec);
102 
103  if (ec)
104  return {};
105 
106  p = parsePreamble(s, ec);
107 
108  if (ec)
109  return {};
110 
111  if (!isPrimitive(p) || !isContextSpecific(p))
112  {
114  return {};
115  }
116 
117  if (p.tag != 1)
118  {
120  return {};
121  }
122 
123  auto cost = parseInteger<std::uint32_t>(s, p.length, ec);
124 
125  if (ec)
126  return {};
127 
128  if (!s.empty())
129  {
131  return {};
132  }
133 
134  switch (type)
135  {
138  {
140  return {};
141  }
142  break;
143 
144  default:
145  break;
146  }
147 
148  return std::make_unique<Condition>(type, cost, std::move(b));
149 }
150 
151 } // namespace detail
152 
155 {
156  // Per the RFC, in a condition we choose a type based
157  // on the tag of the item we contain:
158  //
159  // Condition ::= CHOICE {
160  // preimageSha256 [0] SimpleSha256Condition,
161  // prefixSha256 [1] CompoundSha256Condition,
162  // thresholdSha256 [2] CompoundSha256Condition,
163  // rsaSha256 [3] SimpleSha256Condition,
164  // ed25519Sha256 [4] SimpleSha256Condition
165  // }
166  if (s.empty())
167  {
168  ec = error::buffer_empty;
169  return {};
170  }
171 
172  using namespace der;
173 
174  auto const p = parsePreamble(s, ec);
175  if (ec)
176  return {};
177 
178  // All fulfillments are context-specific, constructed
179  // types
180  if (!isConstructed(p) || !isContextSpecific(p))
181  {
183  return {};
184  }
185 
186  if (p.length > s.size())
187  {
189  return {};
190  }
191 
192  if (s.size() > maxSerializedCondition)
193  {
194  ec = error::large_size;
195  return {};
196  }
197 
199 
200  switch (p.tag)
201  {
202  case 0: // PreimageSha256
204  Type::preimageSha256, Slice(s.data(), p.length), ec);
205  if (!ec)
206  s += p.length;
207  break;
208 
209  case 1: // PrefixSha256
211  return {};
212 
213  case 2: // ThresholdSha256
215  return {};
216 
217  case 3: // RsaSha256
219  return {};
220 
221  case 4: // Ed25519Sha256
223  return {};
224 
225  default:
226  ec = error::unknown_type;
227  return {};
228  }
229 
230  if (!s.empty())
231  {
233  return {};
234  }
235 
236  return c;
237 }
238 
239 } // namespace cryptoconditions
240 } // namespace ripple
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:79
ripple::cryptoconditions::error::buffer_empty
@ buffer_empty
ripple::cryptoconditions::Type::preimageSha256
@ preimageSha256
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:96
ripple::Slice::length
std::size_t length() const noexcept
Definition: Slice.h:85
ripple::cryptoconditions::error::fingerprint_size
@ fingerprint_size
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:68
ripple::cryptoconditions::error::incorrect_encoding
@ incorrect_encoding
iostream
std::error_code
STL class.
ripple::cryptoconditions::error::buffer_underfull
@ buffer_underfull
ripple::cryptoconditions::error::unexpected_tag
@ unexpected_tag
ripple::cryptoconditions::error::unknown_type
@ unknown_type
ripple::cryptoconditions::detail::loadSimpleSha256
std::unique_ptr< Condition > loadSimpleSha256(Type type, Slice s, std::error_code &ec)
Definition: Condition.cpp:74
ripple::cryptoconditions::Type
Type
Definition: Condition.h:36
ripple::cryptoconditions::error::preimage_too_long
@ preimage_too_long
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::size_t
ripple::cryptoconditions::detail::fingerprintSize
constexpr std::size_t fingerprintSize
Definition: Condition.cpp:71
ripple::cryptoconditions::error::large_size
@ large_size
std::unique_ptr
STL class.
ripple::cryptoconditions::error::trailing_garbage
@ trailing_garbage
ripple::cryptoconditions::error::malformed_encoding
@ malformed_encoding
ripple::cryptoconditions::PreimageSha256::maxPreimageLength
static constexpr std::size_t maxPreimageLength
The maximum allowed length of a preimage.
Definition: PreimageSha256.h:46
ripple::cryptoconditions::error::unsupported_type
@ unsupported_type
ripple::cryptoconditions::Condition::deserialize
static std::unique_ptr< Condition > deserialize(Slice s, std::error_code &ec)
Load a condition from its binary form.
Definition: Condition.cpp:154