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 
28 #include <optional>
29 #include <shared_mutex>
30 #include <string>
31 
32 namespace ripple {
33 
34 /*
35  Validator key manifests
36  -----------------------
37 
38  Suppose the secret keys installed on a Ripple validator are compromised. Not
39  only do you have to generate and install new key pairs on each validator,
40  EVERY rippled needs to have its config updated with the new public keys, and
41  is vulnerable to forged validation signatures until this is done. The
42  solution is a new layer of indirection: A master secret key under
43  restrictive access control is used to sign a "manifest": essentially, a
44  certificate including the master public key, an ephemeral public key for
45  verifying validations (which will be signed by its secret counterpart), a
46  sequence number, and a digital signature.
47 
48  The manifest has two serialized forms: one which includes the digital
49  signature and one which doesn't. There is an obvious causal dependency
50  relationship between the (latter) form with no signature, the signature
51  of that form, and the (former) form which includes that signature. In
52  other words, a message can't contain a signature of itself. The code
53  below stores a serialized manifest which includes the signature, and
54  dynamically generates the signatureless form when it needs to verify
55  the signature.
56 
57  An instance of ManifestCache stores, for each trusted validator, (a) its
58  master public key, and (b) the most senior of all valid manifests it has
59  seen for that validator, if any. On startup, the [validator_token] config
60  entry (which contains the manifest for this validator) is decoded and
61  added to the manifest cache. Other manifests are added as "gossip"
62  received from rippled peers.
63 
64  When an ephemeral key is compromised, a new signing key pair is created,
65  along with a new manifest vouching for it (with a higher sequence number),
66  signed by the master key. When a rippled peer receives the new manifest,
67  it verifies it with the master key and (assuming it's valid) discards the
68  old ephemeral key and stores the new one. If the master key itself gets
69  compromised, a manifest with sequence number 0xFFFFFFFF will supersede a
70  prior manifest and discard any existing ephemeral key without storing a
71  new one. These revocation manifests are loaded from the
72  [validator_key_revocation] config entry as well as received as gossip from
73  peers. Since no further manifests for this master key will be accepted
74  (since no higher sequence number is possible), and no signing key is on
75  record, no validations will be accepted from the compromised validator.
76 */
77 
78 //------------------------------------------------------------------------------
79 
80 struct Manifest
81 {
84 
87 
89  // A revoked manifest does not have a signingKey
90  // This field is specified as "optional" in manifestFormat's
91  // SOTemplate
93 
96 
99 
100  Manifest() = delete;
101 
103  std::string const& serialized_,
104  PublicKey const& masterKey_,
105  std::optional<PublicKey> const& signingKey_,
106  std::uint32_t seq,
107  std::string const& domain_)
108  : serialized(serialized_)
109  , masterKey(masterKey_)
110  , signingKey(signingKey_)
111  , sequence(seq)
112  , domain(domain_)
113  {
114  }
115 
116  Manifest(Manifest const& other) = delete;
117  Manifest&
118  operator=(Manifest const& other) = delete;
119  Manifest(Manifest&& other) = default;
120  Manifest&
121  operator=(Manifest&& other) = default;
122 
124  bool
125  verify() const;
126 
128  uint256
129  hash() const;
130 
132  // The maximum possible sequence number means that the master key has
133  // been revoked
134  static bool
136 
138  bool
139  revoked() const;
140 
143  getSignature() const;
144 
146  Blob
147  getMasterSignature() const;
148 };
149 
152 to_string(Manifest const& m);
153 
165 deserializeManifest(Slice s, beast::Journal journal);
166 
169  std::string const& s,
171 {
172  return deserializeManifest(makeSlice(s), journal);
173 }
174 
175 template <
176  class T,
177  class = std::enable_if_t<
181  std::vector<T> const& v,
183 {
184  return deserializeManifest(makeSlice(v), journal);
185 }
188 inline bool
189 operator==(Manifest const& lhs, Manifest const& rhs)
190 {
191  // In theory, comparing the two serialized strings should be
192  // sufficient.
193  return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
194  lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
195  lhs.serialized == rhs.serialized;
196 }
197 
198 inline bool
199 operator!=(Manifest const& lhs, Manifest const& rhs)
200 {
201  return !(lhs == rhs);
202 }
203 
205 {
208 };
209 
212  std::vector<std::string> const& blob,
214 
217  accepted = 0,
218 
220  stale,
221 
223  badMasterKey,
224 
227 
229  invalid
230 };
231 
232 inline std::string
234 {
235  switch (m)
236  {
238  return "accepted";
240  return "stale";
242  return "badMasterKey";
244  return "badEphemeralKey";
246  return "invalid";
247  default:
248  return "unknown";
249  }
250 }
251 
252 class DatabaseCon;
253 
256 {
257 private:
260 
263 
266 
268 
269 public:
270  explicit ManifestCache(
272  : j_(j)
273  {
274  }
275 
278  sequence() const
279  {
280  return seq_.load();
281  }
282 
294  getSigningKey(PublicKey const& pk) const;
295 
306  PublicKey
307  getMasterKey(PublicKey const& pk) const;
308 
315  getSequence(PublicKey const& pk) const;
316 
323  getDomain(PublicKey const& pk) const;
324 
331  getManifest(PublicKey const& pk) const;
332 
341  bool
342  revoked(PublicKey const& pk) const;
343 
357 
374  bool
375  load(
376  DatabaseCon& dbCon,
377  std::string const& dbTable,
378  std::string const& configManifest,
379  std::vector<std::string> const& configRevocation);
380 
391  void
392  load(DatabaseCon& dbCon, std::string const& dbTable);
393 
404  void
405  save(
406  DatabaseCon& dbCon,
407  std::string const& dbTable,
408  std::function<bool(PublicKey const&)> const& isTrusted);
409 
423  template <class Function>
424  void
425  for_each_manifest(Function&& f) const
426  {
427  std::shared_lock lock{mutex_};
428  for (auto const& [_, manifest] : map_)
429  {
430  (void)_;
431  f(manifest);
432  }
433  }
434 
451  template <class PreFun, class EachFun>
452  void
453  for_each_manifest(PreFun&& pf, EachFun&& f) const
454  {
455  std::shared_lock lock{mutex_};
456  pf(map_.size());
457  for (auto const& [_, manifest] : map_)
458  {
459  (void)_;
460  f(manifest);
461  }
462  }
463 };
464 
465 } // namespace ripple
466 
467 #endif
ripple::ManifestCache::mutex_
std::shared_mutex mutex_
Definition: Manifest.h:259
std::is_same
ripple::Manifest::domain
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition: Manifest.h:98
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:241
ripple::ManifestCache::getSigningKey
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition: app/misc/impl/Manifest.cpp:310
std::string
STL class.
ripple::ManifestDisposition
ManifestDisposition
Definition: Manifest.h:215
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:322
ripple::loadValidatorToken
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
Definition: app/misc/impl/Manifest.cpp:263
ripple::Manifest
Definition: Manifest.h:80
ripple::HashPrefix::manifest
@ manifest
Manifest.
std::vector< unsigned char >
ripple::Manifest::serialized
std::string serialized
The manifest in serialized form.
Definition: Manifest.h:83
ripple::Manifest::masterKey
PublicKey masterKey
The master key associated with this manifest.
Definition: Manifest.h:86
ripple::Manifest::verify
bool verify() const
Returns true if manifest signature is valid.
Definition: app/misc/impl/Manifest.cpp:195
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:453
ripple::ValidatorToken
Definition: Manifest.h:204
ripple::ManifestCache::map_
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition: Manifest.h:262
ripple::ManifestDisposition::badEphemeralKey
@ badEphemeralKey
The ephemeral key is not acceptable to us.
std::function
ripple::ValidatorToken::manifest
std::string manifest
Definition: Manifest.h:206
beast::Journal::getNullSink
static Sink & getNullSink()
Returns a Sink which does nothing.
Definition: beast_Journal.cpp:72
ripple::Manifest::revoked
bool revoked() const
Returns true if manifest revokes master key.
Definition: app/misc/impl/Manifest.cpp:225
ripple::ManifestCache::save
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
Definition: app/misc/impl/Manifest.cpp:605
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:189
ripple::base_uint< 256 >
ripple::Manifest::Manifest
Manifest()=delete
ripple::ManifestCache::signingToMasterKeys_
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition: Manifest.h:265
ripple::ManifestDisposition::badMasterKey
@ badMasterKey
The master key is not acceptable to us.
ripple::PublicKey
A public key.
Definition: PublicKey.h:61
std::atomic::load
T load(T... args)
std::enable_if_t
ripple::Manifest::Manifest
Manifest(std::string const &serialized_, PublicKey const &masterKey_, std::optional< PublicKey > const &signingKey_, std::uint32_t seq, std::string const &domain_)
Definition: Manifest.h:102
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:199
ripple::Manifest::getSignature
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition: app/misc/impl/Manifest.cpp:243
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:370
ripple::ManifestCache::j_
beast::Journal j_
Definition: Manifest.h:258
ripple::ManifestCache::for_each_manifest
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition: Manifest.h:425
ripple::ManifestCache::seq_
std::atomic< std::uint32_t > seq_
Definition: Manifest.h:267
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:254
std::atomic< std::uint32_t >
ripple::ManifestDisposition::invalid
@ invalid
Timely, but invalid signature.
ripple::ManifestCache::getSequence
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition: app/misc/impl/Manifest.cpp:334
ripple::ManifestDisposition::accepted
@ accepted
Manifest is valid.
ripple::Manifest::sequence
std::uint32_t sequence
The sequence number of this manifest.
Definition: Manifest.h:95
ripple::ManifestCache
Remembers manifests with the highest sequence number.
Definition: Manifest.h:255
ripple::ManifestCache::getManifest
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
Definition: app/misc/impl/Manifest.cpp:358
ripple::ManifestCache::getDomain
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition: app/misc/impl/Manifest.cpp:346
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::ManifestCache::ManifestCache
ManifestCache(beast::Journal j=beast::Journal(beast::Journal::getNullSink()))
Definition: Manifest.h:270
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:216
optional
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:38
ripple::Manifest::signingKey
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition: Manifest.h:92
ripple::deserializeManifest
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:53
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:548
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:382
shared_mutex
std::unordered_map
STL class.
ripple::ValidatorToken::validationSecret
SecretKey validationSecret
Definition: Manifest.h:207
std::shared_lock
STL class.
ripple::ManifestCache::sequence
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition: Manifest.h:278
string