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

@@ -37,22 +37,15 @@ operator<<(std::ostream& os, PublicKey const& pk)
return os;
}
using uint264 = boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<
264, 264, boost::multiprecision::signed_magnitude,
boost::multiprecision::unchecked, void>>;
template<>
boost::optional<PublicKey>
parseBase58 (TokenType type, std::string const& s)
{
auto const result =
decodeBase58Token(s, type);
if (result.empty())
auto const result = decodeBase58Token(s, type);
auto const pks = makeSlice(result);
if (!publicKeyType(pks))
return boost::none;
if (result.size() != 33)
return boost::none;
return PublicKey(makeSlice(result));
return PublicKey(pks);
}
//------------------------------------------------------------------------------
@@ -81,8 +74,7 @@ sigPart (Slice& buf)
if ((buf[1] & 0x80) == 0)
return boost::none;
}
boost::optional<Slice> number =
Slice(buf.data(), len);
boost::optional<Slice> number = Slice(buf.data(), len);
buf += len;
return number;
}
@@ -125,6 +117,11 @@ sliceToHex (Slice const& slice)
boost::optional<ECDSACanonicality>
ecdsaCanonicality (Slice const& sig)
{
using uint264 = boost::multiprecision::number<
boost::multiprecision::cpp_int_backend<
264, 264, boost::multiprecision::signed_magnitude,
boost::multiprecision::unchecked, void>>;
static uint264 const G(
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
@@ -141,12 +138,13 @@ ecdsaCanonicality (Slice const& sig)
return boost::none;
uint264 R(sliceToHex(*r));
uint264 S(sliceToHex(*s));
if (R >= G)
return boost::none;
uint264 S(sliceToHex(*s));
if (S >= G)
return boost::none;
// (R,S) and (R,G-S) are canonical,
// but is fully canonical when S <= G-S
auto const Sp = G - S;
@@ -186,7 +184,7 @@ PublicKey::PublicKey (Slice const& slice)
if(! publicKeyType(slice))
LogicError("PublicKey::PublicKey invalid type");
size_ = slice.size();
std::memcpy(buf_, slice.data(), slice.size());
std::memcpy(buf_, slice.data(), size_);
}
PublicKey::PublicKey (PublicKey const& other)
@@ -196,8 +194,7 @@ PublicKey::PublicKey (PublicKey const& other)
};
PublicKey&
PublicKey::operator=(
PublicKey const& other)
PublicKey::operator=(PublicKey const& other)
{
size_ = other.size_;
std::memcpy(buf_, other.buf_, size_);
@@ -209,13 +206,15 @@ PublicKey::operator=(
boost::optional<KeyType>
publicKeyType (Slice const& slice)
{
if (slice.size() == 33 &&
slice[0] == 0xED)
return KeyType::ed25519;
if (slice.size() == 33 &&
(slice[0] == 0x02 ||
slice[0] == 0x03))
return KeyType::secp256k1;
if (slice.size() == 33)
{
if (slice[0] == 0xED)
return KeyType::ed25519;
if (slice[0] == 0x02 || slice[0] == 0x03)
return KeyType::secp256k1;
}
return boost::none;
}