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/regex.hpp>
26 #include <iostream>
27 #include <vector>
28 
29 namespace ripple {
30 namespace cryptoconditions {
31 
32 namespace detail {
33 // The binary encoding of conditions differs based on their
34 // type. All types define at least a fingerprint and cost
35 // sub-field. Some types, such as the compound condition
36 // types, define additional sub-fields that are required to
37 // convey essential properties of the cryptocondition (such
38 // as the sub-types used by sub-conditions in the case of
39 // the compound types).
40 //
41 // Conditions are encoded as follows:
42 //
43 // Condition ::= CHOICE {
44 // preimageSha256 [0] SimpleSha256Condition,
45 // prefixSha256 [1] CompoundSha256Condition,
46 // thresholdSha256 [2] CompoundSha256Condition,
47 // rsaSha256 [3] SimpleSha256Condition,
48 // ed25519Sha256 [4] SimpleSha256Condition
49 // }
50 //
51 // SimpleSha256Condition ::= SEQUENCE {
52 // fingerprint OCTET STRING (SIZE(32)),
53 // cost INTEGER (0..4294967295)
54 // }
55 //
56 // CompoundSha256Condition ::= SEQUENCE {
57 // fingerprint OCTET STRING (SIZE(32)),
58 // cost INTEGER (0..4294967295),
59 // subtypes ConditionTypes
60 // }
61 //
62 // ConditionTypes ::= BIT STRING {
63 // preImageSha256 (0),
64 // prefixSha256 (1),
65 // thresholdSha256 (2),
66 // rsaSha256 (3),
67 // ed25519Sha256 (4)
68 // }
69 
71 
74 {
75  using namespace der;
76 
77  auto p = parsePreamble(s, ec);
78 
79  if (ec)
80  return {};
81 
82  if (!isPrimitive(p) || !isContextSpecific(p))
83  {
85  return {};
86  }
87 
88  if (p.tag != 0)
89  {
91  return {};
92  }
93 
94  if (p.length != fingerprintSize)
95  {
97  return {};
98  }
99 
100  Buffer b = parseOctetString(s, p.length, ec);
101 
102  if (ec)
103  return {};
104 
105  p = parsePreamble(s, ec);
106 
107  if (ec)
108  return {};
109 
110  if (!isPrimitive(p) || !isContextSpecific(p))
111  {
113  return {};
114  }
115 
116  if (p.tag != 1)
117  {
119  return {};
120  }
121 
122  auto cost = parseInteger<std::uint32_t>(s, p.length, ec);
123 
124  if (ec)
125  return {};
126 
127  if (!s.empty())
128  {
130  return {};
131  }
132 
133  switch (type)
134  {
137  {
139  return {};
140  }
141  break;
142 
143  default:
144  break;
145  }
146 
147  return std::make_unique<Condition>(type, cost, std::move(b));
148 }
149 
150 } // namespace detail
151 
154 {
155  // Per the RFC, in a condition we choose a type based
156  // on the tag of the item we contain:
157  //
158  // Condition ::= CHOICE {
159  // preimageSha256 [0] SimpleSha256Condition,
160  // prefixSha256 [1] CompoundSha256Condition,
161  // thresholdSha256 [2] CompoundSha256Condition,
162  // rsaSha256 [3] SimpleSha256Condition,
163  // ed25519Sha256 [4] SimpleSha256Condition
164  // }
165  if (s.empty())
166  {
167  ec = error::buffer_empty;
168  return {};
169  }
170 
171  using namespace der;
172 
173  auto const p = parsePreamble(s, ec);
174  if (ec)
175  return {};
176 
177  // All fulfillments are context-specific, constructed
178  // types
179  if (!isConstructed(p) || !isContextSpecific(p))
180  {
182  return {};
183  }
184 
185  if (p.length > s.size())
186  {
188  return {};
189  }
190 
191  if (s.size() > maxSerializedCondition)
192  {
193  ec = error::large_size;
194  return {};
195  }
196 
198 
199  switch (p.tag)
200  {
201  case 0: // PreimageSha256
203  Type::preimageSha256, Slice(s.data(), p.length), ec);
204  if (!ec)
205  s += p.length;
206  break;
207 
208  case 1: // PrefixSha256
210  return {};
211 
212  case 2: // ThresholdSha256
214  return {};
215 
216  case 3: // RsaSha256
218  return {};
219 
220  case 4: // Ed25519Sha256
222  return {};
223 
224  default:
225  ec = error::unknown_type;
226  return {};
227  }
228 
229  if (!s.empty())
230  {
232  return {};
233  }
234 
235  return c;
236 }
237 
238 } // namespace cryptoconditions
239 } // 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:73
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:70
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:153