rippled
Manifest.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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_APP_MISC_MANIFEST_H_INCLUDED
21 #define RIPPLE_APP_MISC_MANIFEST_H_INCLUDED
22 
23 #include <ripple/basics/UnorderedContainers.h>
24 #include <ripple/beast/utility/Journal.h>
25 #include <ripple/protocol/PublicKey.h>
26 #include <ripple/protocol/SecretKey.h>
27 #include <boost/optional.hpp>
28 #include <string>
29 
30 namespace ripple {
31 
32 /*
33  Validator key manifests
34  -----------------------
35 
36  Suppose the secret keys installed on a Ripple validator are compromised. Not
37  only do you have to generate and install new key pairs on each validator,
38  EVERY rippled needs to have its config updated with the new public keys, and
39  is vulnerable to forged validation signatures until this is done. The
40  solution is a new layer of indirection: A master secret key under
41  restrictive access control is used to sign a "manifest": essentially, a
42  certificate including the master public key, an ephemeral public key for
43  verifying validations (which will be signed by its secret counterpart), a
44  sequence number, and a digital signature.
45 
46  The manifest has two serialized forms: one which includes the digital
47  signature and one which doesn't. There is an obvious causal dependency
48  relationship between the (latter) form with no signature, the signature
49  of that form, and the (former) form which includes that signature. In
50  other words, a message can't contain a signature of itself. The code
51  below stores a serialized manifest which includes the signature, and
52  dynamically generates the signatureless form when it needs to verify
53  the signature.
54 
55  An instance of ManifestCache stores, for each trusted validator, (a) its
56  master public key, and (b) the most senior of all valid manifests it has
57  seen for that validator, if any. On startup, the [validator_token] config
58  entry (which contains the manifest for this validator) is decoded and
59  added to the manifest cache. Other manifests are added as "gossip"
60  received from rippled peers.
61 
62  When an ephemeral key is compromised, a new signing key pair is created,
63  along with a new manifest vouching for it (with a higher sequence number),
64  signed by the master key. When a rippled peer receives the new manifest,
65  it verifies it with the master key and (assuming it's valid) discards the
66  old ephemeral key and stores the new one. If the master key itself gets
67  compromised, a manifest with sequence number 0xFFFFFFFF will supersede a
68  prior manifest and discard any existing ephemeral key without storing a
69  new one. These revocation manifests are loaded from the
70  [validator_key_revocation] config entry as well as received as gossip from
71  peers. Since no further manifests for this master key will be accepted
72  (since no higher sequence number is possible), and no signing key is on
73  record, no validations will be accepted from the compromised validator.
74 */
75 
76 //------------------------------------------------------------------------------
77 
78 struct Manifest
79 {
82 
85 
88 
91 
94 
95  Manifest() = default;
96  Manifest(Manifest const& other) = delete;
97  Manifest&
98  operator=(Manifest const& other) = delete;
99  Manifest(Manifest&& other) = default;
100  Manifest&
101  operator=(Manifest&& other) = default;
102 
104  bool
105  verify() const;
106 
108  uint256
109  hash() const;
110 
112  bool
113  revoked() const;
114 
116  boost::optional<Blob>
117  getSignature() const;
118 
120  Blob
121  getMasterSignature() const;
122 };
123 
134 boost::optional<Manifest>
136 
137 inline boost::optional<Manifest>
139 {
140  return deserializeManifest(makeSlice(s));
141 }
142 
143 template <
144  class T,
145  class = std::enable_if_t<
147 boost::optional<Manifest>
149 {
150  return deserializeManifest(makeSlice(v));
151 }
154 inline bool
155 operator==(Manifest const& lhs, Manifest const& rhs)
156 {
157  // In theory, comparing the two serialized strings should be
158  // sufficient.
159  return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
160  lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
161  lhs.serialized == rhs.serialized;
162 }
163 
164 inline bool
165 operator!=(Manifest const& lhs, Manifest const& rhs)
166 {
167  return !(lhs == rhs);
168 }
169 
171 {
174 };
175 
176 boost::optional<ValidatorToken>
178 
181  accepted = 0,
182 
184  stale,
185 
187  invalid
188 };
189 
190 inline std::string
192 {
193  switch (m)
194  {
196  return "accepted";
198  return "stale";
200  return "invalid";
201  default:
202  return "unknown";
203  }
204 }
205 
206 class DatabaseCon;
207 
210 {
211 private:
215 
218 
221 
223 
224 public:
225  explicit ManifestCache(
227  : j_(j)
228  {
229  }
230 
233  sequence() const
234  {
235  return seq_.load();
236  }
237 
248  PublicKey
249  getSigningKey(PublicKey const& pk) const;
250 
261  PublicKey
262  getMasterKey(PublicKey const& pk) const;
263 
269  boost::optional<std::uint32_t>
270  getSequence(PublicKey const& pk) const;
271 
277  boost::optional<std::string>
278  getDomain(PublicKey const& pk) const;
279 
285  boost::optional<std::string>
286  getManifest(PublicKey const& pk) const;
287 
296  bool
297  revoked(PublicKey const& pk) const;
298 
312 
329  bool
330  load(
331  DatabaseCon& dbCon,
332  std::string const& dbTable,
333  std::string const& configManifest,
334  std::vector<std::string> const& configRevocation);
335 
346  void
347  load(DatabaseCon& dbCon, std::string const& dbTable);
348 
359  void
360  save(
361  DatabaseCon& dbCon,
362  std::string const& dbTable,
363  std::function<bool(PublicKey const&)> isTrusted);
364 
376  template <class Function>
377  void
378  for_each_manifest(Function&& f) const
379  {
381  for (auto const& [_, manifest] : map_)
382  {
383  (void)_;
384  f(manifest);
385  }
386  }
387 
402  template <class PreFun, class EachFun>
403  void
404  for_each_manifest(PreFun&& pf, EachFun&& f) const
405  {
407  pf(map_.size());
408  for (auto const& [_, manifest] : map_)
409  {
410  (void)_;
411  f(manifest);
412  }
413  }
414 };
415 
416 } // namespace ripple
417 
418 #endif
ripple::ManifestCache::save
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> isTrusted)
Save cached manifests to database.
Definition: app/misc/impl/Manifest.cpp:528
std::is_same
ripple::Manifest::domain
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition: Manifest.h:93
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:240
std::string
STL class.
ripple::ManifestDisposition
ManifestDisposition
Definition: Manifest.h:179
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:280
ripple::Manifest
Definition: Manifest.h:78
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
ripple::HashPrefix::manifest
@ manifest
Manifest.
ripple::Manifest::signingKey
PublicKey signingKey
The ephemeral key associated with this manifest.
Definition: Manifest.h:87
std::vector< unsigned char >
ripple::Manifest::serialized
std::string serialized
The manifest in serialized form.
Definition: Manifest.h:81
ripple::Manifest::masterKey
PublicKey masterKey
The master key associated with this manifest.
Definition: Manifest.h:84
ripple::Manifest::verify
bool verify() const
Returns true if manifest signature is valid.
Definition: app/misc/impl/Manifest.cpp:168
ripple::ManifestCache::for_each_manifest
void for_each_manifest(PreFun &&pf, EachFun &&f) const
Invokes the callback once for every populated manifest.
Definition: Manifest.h:404
ripple::ValidatorToken
Definition: Manifest.h:170
std::lock_guard
STL class.
ripple::ManifestCache::map_
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition: Manifest.h:217
std::function
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::ValidatorToken::manifest
std::string manifest
Definition: Manifest.h:172
beast::Journal::getNullSink
static Sink & getNullSink()
Returns a Sink which does nothing.
Definition: beast_Journal.cpp:72
ripple::ManifestCache::apply_mutex_
std::mutex apply_mutex_
Definition: Manifest.h:213
ripple::Manifest::revoked
bool revoked() const
Returns true if manifest revokes master key.
Definition: app/misc/impl/Manifest.cpp:193
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:155
ripple::Manifest::Manifest
Manifest()=default
ripple::ManifestCache::read_mutex_
std::mutex read_mutex_
Definition: Manifest.h:214
ripple::base_uint< 256 >
ripple::Manifest::getSignature
boost::optional< Blob > getSignature() const
Returns manifest signature.
Definition: app/misc/impl/Manifest.cpp:203
ripple::ManifestCache::signingToMasterKeys_
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition: Manifest.h:220
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
std::atomic::load
T load(T... args)
std::enable_if_t
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:165
ripple::ManifestCache::revoked
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
Definition: app/misc/impl/Manifest.cpp:328
ripple::ManifestCache::getManifest
boost::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
Definition: app/misc/impl/Manifest.cpp:316
ripple::ManifestCache::j_
beast::Journal j_
Definition: Manifest.h:212
ripple::ManifestCache::for_each_manifest
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition: Manifest.h:378
ripple::ManifestCache::seq_
std::atomic< std::uint32_t > seq_
Definition: Manifest.h:222
ripple::ManifestCache::getSigningKey
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition: app/misc/impl/Manifest.cpp:268
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::SecretKey
A secret key.
Definition: SecretKey.h:36
ripple::Manifest::getMasterSignature
Blob getMasterSignature() const
Returns manifest master key signature.
Definition: app/misc/impl/Manifest.cpp:214
std::atomic< std::uint32_t >
ripple::ManifestDisposition::invalid
@ invalid
Timely, but invalid signature.
ripple::ManifestDisposition::accepted
@ accepted
Manifest is valid.
ripple::Manifest::sequence
std::uint32_t sequence
The sequence number of this manifest.
Definition: Manifest.h:90
ripple::ManifestCache
Remembers manifests with the highest sequence number.
Definition: Manifest.h:209
ripple::ManifestDisposition::stale
@ stale
Sequence is too old.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::deserializeManifest
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:38
ripple::ManifestCache::ManifestCache
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition: Manifest.h:225
ripple::loadValidatorToken
boost::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
Definition: app/misc/impl/Manifest.cpp:223
ripple::Manifest::operator=
Manifest & operator=(Manifest const &other)=delete
ripple::DatabaseCon
Definition: DatabaseCon.h:81
ripple::Manifest::hash
uint256 hash() const
Returns hash of serialized manifest data.
Definition: app/misc/impl/Manifest.cpp:184
std::mutex
STL class.
ripple::ManifestCache::getSequence
boost::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition: app/misc/impl/Manifest.cpp:292
ripple::ManifestCache::load
bool load(DatabaseCon &dbCon, std::string const &dbTable, std::string const &configManifest, std::vector< std::string > const &configRevocation)
Populate manifest cache with manifests in database and config.
Definition: app/misc/impl/Manifest.cpp:471
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:340
std::unordered_map
STL class.
ripple::ManifestCache::getDomain
boost::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition: app/misc/impl/Manifest.cpp:304
ripple::ValidatorToken::validationSecret
SecretKey validationSecret
Definition: Manifest.h:173
ripple::ManifestCache::sequence
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition: Manifest.h:233
string