Address issues identified by external review:

* RIPD-1617, RIPD-1619, RIPD-1621:
  Verify serialized public keys more strictly before
  using them.

* RIPD-1618:
    * Simplify the base58 decoder logic.
    * Reduce the complexity of the base58 encoder and
      eliminate a potential out-of-bounds memory access.
    * Improve type safety by using an `enum class` to
      enforce strict type checking for token types.

* RIPD-1616:
  Avoid calling `memcpy` with a null pointer even if the
  size is specified as zero, since it results in undefined
  behavior.

Acknowledgements:
Ripple thanks Guido Vranken for responsibly disclosing these
issues.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers
to responsibly disclose any issues that they may find. For
more on Ripple's Bug Bounty program, please visit:
https://ripple.com/bug-bounty
This commit is contained in:
Nikolaos D. Bougalis
2018-03-15 20:58:05 -07:00
parent 25de6b0a5f
commit d5f981f5fc
47 changed files with 393 additions and 264 deletions

View File

@@ -251,7 +251,7 @@ public:
std::string cfgManifest;
for (auto const& man : inManifests)
s1.push_back (toBase58(
TokenType::TOKEN_NODE_PUBLIC, man->masterKey));
TokenType::NodePublic, man->masterKey));
unl->load (emptyLocalKey, s1, keys);
m.save (dbCon, "ValidatorManifests",
@@ -428,7 +428,7 @@ public:
{
auto const valSecret = parseBase58<SecretKey>(
TokenType::TOKEN_NODE_PRIVATE,
TokenType::NodePrivate,
"paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi");
// Format token string to test trim()

View File

@@ -1065,8 +1065,21 @@ struct PayChan_test : public beast::unit_test::suite
jv.removeMember("PublicKey");
env (jv, ter(temMALFORMED));
jv["PublicKey"] = pkHex;
env (jv);
{
auto const txn = R"*(
{
"channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
"signature":
"304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
"public_key":
"aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
"amount": "1000000"
}
)*";
auto const r = env.rpc("json", "channel_verify", txn);
BEAST_EXPECT(r["result"]["error"] == "publicMalformed");
}
}
void

View File

@@ -82,7 +82,7 @@ public:
// Keys when using [validation_token]
auto const tokenSecretKey = *parseBase58<SecretKey>(
TokenType::TOKEN_NODE_PRIVATE, tokenSecretStr);
TokenType::NodePrivate, tokenSecretStr);
auto const tokenPublicKey =
derivePublicKey(KeyType::secp256k1, tokenSecretKey);

View File

@@ -172,7 +172,7 @@ private:
PublicKey const &publicKey,
char const* comment = nullptr)
{
auto ret = toBase58 (TokenType::TOKEN_NODE_PUBLIC, publicKey);
auto ret = toBase58 (TokenType::NodePublic, publicKey);
if (comment)
ret += comment;
@@ -271,7 +271,7 @@ private:
manifests, manifests, env.timeKeeper(), journal);
auto const localSigningPublic = parseBase58<PublicKey> (
TokenType::TOKEN_NODE_PUBLIC, cfgKeys.front());
TokenType::NodePublic, cfgKeys.front());
BEAST_EXPECT(trustedKeys->load (
*localSigningPublic, cfgKeys, emptyCfgPublishers));
@@ -330,7 +330,7 @@ private:
badPublishers.clear();
for (auto const& key : keys)
badPublishers.push_back (
toBase58 (TokenType::TOKEN_NODE_PUBLIC, key));
toBase58 (TokenType::NodePublic, key));
BEAST_EXPECT(! trustedKeys->load (
emptyLocalKey, emptyCfgKeys, badPublishers));
@@ -533,7 +533,7 @@ private:
{
auto const valKey = randomNode();
cfgKeys.push_back (toBase58(
TokenType::TOKEN_NODE_PUBLIC, valKey));
TokenType::NodePublic, valKey));
if (cfgKeys.size () <= n - 5)
activeValidators.emplace (valKey);
}
@@ -550,7 +550,7 @@ private:
for (auto const& val : cfgKeys)
{
if (auto const valKey = parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, val))
TokenType::NodePublic, val))
{
BEAST_EXPECT(trustedKeys->listed (*valKey));
if (i++ < activeValidators.size ())
@@ -567,7 +567,7 @@ private:
hash_set<PublicKey> activeValidators;
for (auto const valKey : cfgKeys)
activeValidators.emplace (*parseBase58<PublicKey>(
TokenType::TOKEN_NODE_PUBLIC, valKey));
TokenType::NodePublic, valKey));
trustedKeys->onConsensusStart (activeValidators);
BEAST_EXPECT(trustedKeys->quorum () == cfgKeys.size() * 4/5);
}
@@ -579,7 +579,7 @@ private:
derivePublicKey(KeyType::ed25519, masterPrivate);
std::vector<std::string> cfgKeys ({
toBase58 (TokenType::TOKEN_NODE_PUBLIC, masterPublic)});
toBase58 (TokenType::NodePublic, masterPublic)});
BEAST_EXPECT(trustedKeys->load (
emptyLocalKey, cfgKeys, cfgPublishers));
@@ -682,8 +682,8 @@ private:
std::vector<PublicKey> keys ({ randomNode (), randomNode () });
hash_set<PublicKey> activeValidators;
std::vector<std::string> cfgKeys ({
toBase58 (TokenType::TOKEN_NODE_PUBLIC, keys[0]),
toBase58 (TokenType::TOKEN_NODE_PUBLIC, keys[1])});
toBase58 (TokenType::NodePublic, keys[0]),
toBase58 (TokenType::NodePublic, keys[1])});
BEAST_EXPECT(trustedKeys->load (
emptyLocalKey, cfgKeys, cfgPublishers));
@@ -703,7 +703,7 @@ private:
auto const node = randomNode ();
std::vector<std::string> cfgKeys ({
toBase58 (TokenType::TOKEN_NODE_PUBLIC, node)});
toBase58 (TokenType::NodePublic, node)});
hash_set<PublicKey> activeValidators;
BEAST_EXPECT(trustedKeys->load (
@@ -724,8 +724,8 @@ private:
std::vector<PublicKey> keys ({ randomNode (), randomNode () });
hash_set<PublicKey> activeValidators ({ keys[0] });
std::vector<std::string> cfgKeys ({
toBase58 (TokenType::TOKEN_NODE_PUBLIC, keys[0]),
toBase58 (TokenType::TOKEN_NODE_PUBLIC, keys[1])});
toBase58 (TokenType::NodePublic, keys[0]),
toBase58 (TokenType::NodePublic, keys[1])});
auto const localKey = randomNode ();
BEAST_EXPECT(trustedKeys->load (
@@ -827,7 +827,7 @@ private:
{
auto const valKey = randomNode();
cfgKeys.push_back (toBase58(
TokenType::TOKEN_NODE_PUBLIC, valKey));
TokenType::NodePublic, valKey));
activeValidators.emplace (valKey);
BEAST_EXPECT(trustedKeys->load (
@@ -850,14 +850,14 @@ private:
hash_set<PublicKey> activeValidators;
std::vector<std::string> cfgKeys {
toBase58(TokenType::TOKEN_NODE_PUBLIC, localKey)};
toBase58(TokenType::NodePublic, localKey)};
cfgKeys.reserve(9);
while (cfgKeys.size() < cfgKeys.capacity())
{
auto const valKey = randomNode();
cfgKeys.push_back (toBase58(
TokenType::TOKEN_NODE_PUBLIC, valKey));
TokenType::NodePublic, valKey));
activeValidators.emplace (valKey);
BEAST_EXPECT(trustedKeys->load (
@@ -950,7 +950,7 @@ private:
jtx::Env env(*this);
auto toStr = [](PublicKey const& publicKey) {
return toBase58(TokenType::TOKEN_NODE_PUBLIC, publicKey);
return toBase58(TokenType::NodePublic, publicKey);
};
// Config listed keys