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