rippled
Fulfillment.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/safe_cast.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 <type_traits>
28 #include <vector>
29 
30 namespace ripple {
31 namespace cryptoconditions {
32 
33 bool
34 match(Fulfillment const& f, Condition const& c)
35 {
36  // Fast check: the fulfillment's type must match the
37  // conditions's type:
38  if (f.type() != c.type)
39  return false;
40 
41  // Derive the condition from the given fulfillment
42  // and ensure that it matches the given condition.
43  return c == f.condition();
44 }
45 
46 bool
47 validate(Fulfillment const& f, Condition const& c, Slice m)
48 {
49  return match(f, c) && f.validate(m);
50 }
51 
52 bool
53 validate(Fulfillment const& f, Condition const& c)
54 {
55  return validate(f, c, {});
56 }
57 
60 {
61  // Per the RFC, in a fulfillment we choose a type based
62  // on the tag of the item we contain:
63  //
64  // Fulfillment ::= CHOICE {
65  // preimageSha256 [0] PreimageFulfillment ,
66  // prefixSha256 [1] PrefixFulfillment,
67  // thresholdSha256 [2] ThresholdFulfillment,
68  // rsaSha256 [3] RsaSha256Fulfillment,
69  // ed25519Sha256 [4] Ed25519Sha512Fulfillment
70  // }
71 
72  if (s.empty())
73  {
75  return nullptr;
76  }
77 
78  using namespace der;
79 
80  auto const p = parsePreamble(s, ec);
81  if (ec)
82  return nullptr;
83 
84  // All fulfillments are context-specific, constructed types
85  if (!isConstructed(p) || !isContextSpecific(p))
86  {
88  return nullptr;
89  }
90 
91  if (p.length > s.size())
92  {
94  return {};
95  }
96 
97  if (p.length < s.size())
98  {
100  return {};
101  }
102 
103  if (p.length > maxSerializedFulfillment)
104  {
105  ec = error::large_size;
106  return {};
107  }
108 
110 
111  using TagType = decltype(p.tag);
112  switch (p.tag)
113  {
114  case safe_cast<TagType>(Type::preimageSha256):
115  f = PreimageSha256::deserialize(Slice(s.data(), p.length), ec);
116  if (ec)
117  return {};
118  s += p.length;
119  break;
120 
121  case safe_cast<TagType>(Type::prefixSha256):
123  return {};
124  break;
125 
126  case safe_cast<TagType>(Type::thresholdSha256):
128  return {};
129  break;
130 
131  case safe_cast<TagType>(Type::rsaSha256):
133  return {};
134  break;
135 
136  case safe_cast<TagType>(Type::ed25519Sha256):
138  return {};
139 
140  default:
141  ec = error::unknown_type;
142  return {};
143  }
144 
145  if (!s.empty())
146  {
148  return {};
149  }
150 
151  return f;
152 }
153 
154 } // namespace cryptoconditions
155 } // 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::cryptoconditions::Fulfillment::deserialize
static std::unique_ptr< Fulfillment > deserialize(Slice s, std::error_code &ec)
Load a fulfillment from its binary form.
Definition: Fulfillment.cpp:59
ripple::cryptoconditions::Fulfillment::maxSerializedFulfillment
static constexpr std::size_t maxSerializedFulfillment
The largest binary fulfillment we support.
Definition: Fulfillment.h:42
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
vector
ripple::cryptoconditions::Fulfillment::type
virtual Type type() const =0
Returns the type of this condition.
ripple::cryptoconditions::Fulfillment::validate
virtual bool validate(Slice data) const =0
Validates a fulfillment.
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::Condition
Definition: Condition.h:44
ripple::Slice::empty
bool empty() const noexcept
Return true if the byte range is empty.
Definition: Slice.h:68
ripple::cryptoconditions::PreimageSha256::deserialize
static std::unique_ptr< Fulfillment > deserialize(Slice s, std::error_code &ec)
Parse the payload for a PreimageSha256 condition.
Definition: PreimageSha256.h:55
std::error_code
STL class.
ripple::cryptoconditions::Type::ed25519Sha256
@ ed25519Sha256
ripple::cryptoconditions::Condition::type
Type type
Definition: Condition.h:70
ripple::cryptoconditions::error::buffer_underfull
@ buffer_underfull
ripple::cryptoconditions::Type::thresholdSha256
@ thresholdSha256
ripple::cryptoconditions::error::unknown_type
@ unknown_type
ripple::cryptoconditions::validate
bool validate(Fulfillment const &f, Condition const &c, Slice m)
Verify if the given message satisfies the fulfillment.
Definition: Fulfillment.cpp:47
ripple::cryptoconditions::Fulfillment::condition
virtual Condition condition() const =0
Returns the condition associated with the given fulfillment.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::cryptoconditions::Type::prefixSha256
@ prefixSha256
ripple::cryptoconditions::Type::rsaSha256
@ rsaSha256
ripple::cryptoconditions::match
bool match(Fulfillment const &f, Condition const &c)
Determine whether the given fulfillment and condition match.
Definition: Fulfillment.cpp:34
ripple::cryptoconditions::Fulfillment
Definition: Fulfillment.h:32
ripple::cryptoconditions::error::buffer_overfull
@ buffer_overfull
ripple::cryptoconditions::error::large_size
@ large_size
std::unique_ptr
STL class.
ripple::cryptoconditions::error::trailing_garbage
@ trailing_garbage
type_traits
ripple::cryptoconditions::error::malformed_encoding
@ malformed_encoding
ripple::cryptoconditions::error::unsupported_type
@ unsupported_type