diff --git a/src/core/router/info.cc b/src/core/router/info.cc index f1365181..5d5026b3 100644 --- a/src/core/router/info.cc +++ b/src/core/router/info.cc @@ -178,16 +178,7 @@ void RouterInfo::ReadFromBuffer(bool verify_signature) // Verify signature if (verify_signature) { - // Note: signature length is guaranteed to be no less than buffer length - std::uint16_t len = m_BufferLen - m_RouterIdentity.GetSignatureLen(); - if (!m_RouterIdentity.Verify( - reinterpret_cast(m_Buffer.get()), - len, - reinterpret_cast(m_Buffer.get() + len))) - { - LOG(error) << "RouterInfo: signature verification failed"; - m_IsUnreachable = true; - } + Verify(); m_RouterIdentity.DropVerifier(); } } @@ -723,6 +714,31 @@ void RouterInfo::CreateBuffer(const PrivateKeys& private_keys) if (!m_Buffer) m_Buffer = std::make_unique(Size::MaxBuffer); std::memcpy(m_Buffer.get(), router_info.Str().c_str(), m_BufferLen); + + // Verify signature + Verify(); + } + catch (...) + { + m_Exception.Dispatch(__func__); + throw; + } +} + +void RouterInfo::Verify() +{ + try + { + if (!m_Buffer) + throw std::runtime_error("RouterInfo: null buffer"); + std::size_t const len = m_BufferLen - m_RouterIdentity.GetSignatureLen(); + if (len < Size::MinUnsignedBuffer) + throw std::length_error("RouterInfo: invalid RouterInfo size"); + if (!m_RouterIdentity.Verify(m_Buffer.get(), len, m_Buffer.get() + len)) + { + m_IsUnreachable = true; + throw std::runtime_error("RouterInfo: signature verification failed"); + } } catch (...) { diff --git a/src/core/router/info.h b/src/core/router/info.h index 7178e886..18e94768 100644 --- a/src/core/router/info.h +++ b/src/core/router/info.h @@ -68,6 +68,7 @@ struct RouterInfoTraits { MinBuffer = core::DSA_SIGNATURE_LENGTH, // TODO(unassigned): see #498 MaxBuffer = 2048, // TODO(anonimal): review if arbitrary + MinUnsignedBuffer = 399, // Minimum RouterInfo length w/o signature, see spec // TODO(unassigned): algorithm to dynamically determine cost NTCPCost = 10, // NTCP *should* have priority over SSU SSUCost = 5, @@ -522,6 +523,11 @@ class RouterInfo : public RouterInfoTraits, public RoutingDestination /// (and subsequently sign the RI with) void CreateBuffer(const PrivateKeys& private_keys); + /// @brief Verify RI signature + /// @throws std::length_error if unsigned buffer length is below minimum + /// @throws std::runtime_error if signature verification fails + void Verify(); + /// @brief Save RI to file /// @param path Full RI path of file to save to void SaveToFile(const std::string& path);