Skip to content

Commit

Permalink
[net] Sanitize private keys recevied from SAM proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
dergoegge committed Oct 22, 2023
1 parent 106ab20 commit 9ff405e
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/i2p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ static Binary DecodeI2PBase64(const std::string& i2p_b64)
return std::move(*decoded);
}

static Binary SanitizePrivKey(Binary&& binary)
{
if (binary.size() < 387) {
throw std::runtime_error("Private key too small (size < 387 bytes)");
}

if (binary.size() > (387 + std::numeric_limits<uint16_t>::max())) {
throw std::runtime_error("Private key too large");
}

return binary;
}

/**
* Derive the .b32.i2p address of an I2P destination (binary).
* @param[in] dest I2P destination.
Expand Down Expand Up @@ -327,7 +340,7 @@ void Session::DestGenerate(const Sock& sock)
// If SIGNATURE_TYPE is not specified, then the default one is DSA_SHA1.
const Reply& reply = SendRequestAndGetReply(sock, "DEST GENERATE SIGNATURE_TYPE=7", false);

m_private_key = DecodeI2PBase64(reply.Get("PRIV"));
m_private_key = SanitizePrivKey(DecodeI2PBase64(reply.Get("PRIV")));
}

void Session::GenerateAndSavePrivateKey(const Sock& sock)
Expand Down Expand Up @@ -356,6 +369,10 @@ Binary Session::MyDestination() const

const size_t dest_len = DEST_LEN_BASE + cert_len;

if (dest_len > m_private_key.size()) {
throw std::runtime_error("Certificate length did not match the actual private key length");
}

return Binary{m_private_key.begin(), m_private_key.begin() + dest_len};
}

Expand All @@ -382,13 +399,13 @@ void Session::CreateIfNotCreatedAlready()
"inbound.quantity=1 outbound.quantity=1",
session_id));

m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
m_private_key = SanitizePrivKey(DecodeI2PBase64(reply.Get("DESTINATION")));
} else {
// Read our persistent destination (private key) from disk or generate
// one and save it to disk. Then use it when creating the session.
const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
if (read_ok) {
m_private_key.assign(data.begin(), data.end());
m_private_key = SanitizePrivKey(Binary{data.begin(), data.end()});
} else {
GenerateAndSavePrivateKey(*sock);
}
Expand Down

0 comments on commit 9ff405e

Please sign in to comment.