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

@@ -29,15 +29,23 @@ namespace ripple {
STValidation::STValidation (SerialIter& sit, bool checkSignature)
: STObject (getFormat (), sit, sfValidation)
{
mNodeID = calcNodeID(
PublicKey(makeSlice (getFieldVL (sfSigningPubKey))));
auto const spk = getFieldVL(sfSigningPubKey);
if (publicKeyType(makeSlice(spk)) != KeyType::secp256k1)
{
JLOG (debugLog().error())
<< "Invalid public key in validation" << getJson (0);
Throw<std::runtime_error> ("Invalid public key in validation");
}
mNodeID = calcNodeID(PublicKey(makeSlice(spk)));
assert (mNodeID.isNonZero ());
if (checkSignature && !isValid ())
{
JLOG (debugLog().error())
<< "Invalid validation" << getJson (0);
Throw<std::runtime_error> ("Invalid validation");
<< "Invalid signature in validation" << getJson (0);
Throw<std::runtime_error> ("Invalid signature in validation");
}
}
@@ -49,11 +57,15 @@ STValidation::STValidation (
: STObject (getFormat (), sfValidation)
, mSeen (signTime)
{
// This is our own public key and it should always be valid.
if (!publicKeyType(publicKey))
LogicError ("Invalid validation public key");
// Does not sign
setFieldH256 (sfLedgerHash, ledgerHash);
setFieldU32 (sfSigningTime, signTime.time_since_epoch().count());
setFieldVL (sfSigningPubKey, publicKey.slice());
mNodeID = calcNodeID(publicKey);
assert (mNodeID.isNonZero ());
@@ -101,6 +113,9 @@ bool STValidation::isValid (uint256 const& signingHash) const
{
try
{
if (publicKeyType(getSignerPublic()) != KeyType::secp256k1)
return false;
return verifyDigest (getSignerPublic(),
signingHash,
makeSlice(getFieldVL (sfSignature)),