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 <optional>
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 
117  getSignature() const;
118 
120  Blob
121  getMasterSignature() const;
122 };
123 
126 to_string(Manifest const& m);
127 
140 
143 {
144  return deserializeManifest(makeSlice(s));
145 }
146 
147 template <
148  class T,
149  class = std::enable_if_t<
153 {
154  return deserializeManifest(makeSlice(v));
155 }
158 inline bool
159 operator==(Manifest const& lhs, Manifest const& rhs)
160 {
161  // In theory, comparing the two serialized strings should be
162  // sufficient.
163  return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
164  lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
165  lhs.serialized == rhs.serialized;
166 }
167 
168 inline bool
169 operator!=(Manifest const& lhs, Manifest const& rhs)
170 {
171  return !(lhs == rhs);
172 }
173 
175 {
178 };
179 
182 
185  accepted = 0,
186 
188  stale,
189 
191  badMasterKey,
192 
195 
197  invalid
198 };
199 
200 inline std::string
202 {
203  switch (m)
204  {
206  return "accepted";
208  return "stale";
210  return "badMasterKey";
212  return "badEphemeralKey";
214  return "invalid";
215  default:
216  return "unknown";
217  }
218 }
219 
220 class DatabaseCon;
221 
224 {
225 private:
229 
232 
235 
237 
238 public:
239  explicit ManifestCache(
241  : j_(j)
242  {
243  }
244 
247  sequence() const
248  {
249  return seq_.load();
250  }
251 
262  PublicKey
263  getSigningKey(PublicKey const& pk) const;
264 
275  PublicKey
276  getMasterKey(PublicKey const& pk) const;
277 
284  getSequence(PublicKey const& pk) const;
285 
292  getDomain(PublicKey const& pk) const;
293 
300  getManifest(PublicKey const& pk) const;
301 
310  bool
311  revoked(PublicKey const& pk) const;
312 
326 
343  bool
344  load(
345  DatabaseCon& dbCon,
346  std::string const& dbTable,
347  std::string const& configManifest,
348  std::vector<std::string> const& configRevocation);
349 
360  void
361  load(DatabaseCon& dbCon, std::string const& dbTable);
362 
373  void
374  save(
375  DatabaseCon& dbCon,
376  std::string const& dbTable,
377  std::function<bool(PublicKey const&)> const& isTrusted);
378 
390  template <class Function>
391  void
392  for_each_manifest(Function&& f) const
393  {
395  for (auto const& [_, manifest] : map_)
396  {
397  (void)_;
398  f(manifest);
399  }
400  }
401 
416  template <class PreFun, class EachFun>
417  void
418  for_each_manifest(PreFun&& pf, EachFun&& f) const
419  {
421  pf(map_.size());
422  for (auto const& [_, manifest] : map_)
423  {
424  (void)_;
425  f(manifest);
426  }
427  }
428 };
429 
430 } // namespace ripple
431 
432 #endif
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:183
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:296
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:184
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:418
ripple::ValidatorToken
Definition: Manifest.h:174
std::lock_guard
STL class.
ripple::ManifestCache::map_
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition: Manifest.h:231
ripple::ManifestDisposition::badEphemeralKey
@ badEphemeralKey
The ephemeral key is not acceptable to us.
std::function
ripple::ValidatorToken::manifest
std::string manifest
Definition: Manifest.h:176
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:227
ripple::Manifest::revoked
bool revoked() const
Returns true if manifest revokes master key.
Definition: app/misc/impl/Manifest.cpp:209
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:541
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:159
ripple::Manifest::Manifest
Manifest()=default
ripple::ManifestCache::read_mutex_
std::mutex read_mutex_
Definition: Manifest.h:228
ripple::base_uint< 256 >
ripple::ManifestCache::signingToMasterKeys_
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition: Manifest.h:234
ripple::ManifestDisposition::badMasterKey
@ badMasterKey
The master key is not acceptable to us.
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:169
ripple::Manifest::getSignature
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition: app/misc/impl/Manifest.cpp:219
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:344
ripple::ManifestCache::j_
beast::Journal j_
Definition: Manifest.h:226
ripple::ManifestCache::for_each_manifest
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition: Manifest.h:392
ripple::loadValidatorToken
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
Definition: app/misc/impl/Manifest.cpp:239
ripple::ManifestCache::seq_
std::atomic< std::uint32_t > seq_
Definition: Manifest.h:236
ripple::ManifestCache::getSigningKey
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition: app/misc/impl/Manifest.cpp:284
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:230
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:308
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:223
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:332
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:320
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:239
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:200
optional
std::mutex
STL class.
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::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:484
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:356
std::unordered_map
STL class.
ripple::deserializeManifest
std::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:50
ripple::ValidatorToken::validationSecret
SecretKey validationSecret
Definition: Manifest.h:177
ripple::ManifestCache::sequence
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition: Manifest.h:247
string