# # patch "constants.cc" # from [18838196cb64a85337deb2184c7e42c865133868] # to [2258f6165b6db8f8c952f97aaacf0addbbed060f] # # patch "constants.hh" # from [165716b9b2fee13374d0e18d3c4daf940475eb9e] # to [a4741c95ae4faeb5db1f36f6ccf406f732250241] # # patch "netcmd.cc" # from [8043534523eaf442c8599f19092ef0b154c8458b] # to [ac2aee5342c821fd22c0a4fbc9a66c30886d0b00] # # patch "netcmd.hh" # from [bd3f114a0a69c85257ba9692556ae158160d0323] # to [c1b1608f8cc8ad67cf06df57fa26fdf6447fea4f] # # patch "netsync.cc" # from [10e7570b6c2155fa1c88ef167e3fb8e692a4308c] # to [ff9431fc8061edcd03b381fa419799baa53b09a0] # # patch "vocab.cc" # from [b63535f4a650ae9ec89080324f4c8eac4fdf5402] # to [0a568b1d7a988e146671055888136fdff7818916] # # patch "vocab_terms.hh" # from [cf97b245c5684ff606ffbd6fff05032c2893de24] # to [fe3bf7a7700bdde82211ba0be39caf248025e00b] # --- constants.cc +++ constants.cc @@ -161,5 +161,8 @@ size_t const netsync_connection_limit = 1024; size_t const netsync_timeout_seconds = 21600; // 6 hours size_t const netsync_session_key_length_in_bytes = 20; // 160 bits + size_t const netsync_hmac_value_length_in_bytes = 20; // 160 bits + std::string const & netsync_key_initializer = std::string(netsync_session_key_length_in_bytes, 0); + } --- constants.hh +++ constants.hh @@ -7,6 +7,7 @@ // see the file COPYING for details #include +#include #include "numeric_vocab.hh" namespace constants @@ -123,6 +124,12 @@ // netsync HMAC key length extern size_t const netsync_session_key_length_in_bytes; + // netsync HMAC value length + extern size_t const netsync_hmac_value_length_in_bytes; + + // netsync session key and HMAC key default initializer + extern std::string const & netsync_key_initializer; + } #endif // __CONSTANTS_HH__ --- netcmd.cc +++ netcmd.cc @@ -71,7 +71,8 @@ } void -netcmd::write(string & out, netsync_session_key const & key) const +netcmd::write(string & out, netsync_session_key const & key, + netsync_hmac_value & hmac_val) const { size_t oldlen = out.size(); out += static_cast(version); @@ -84,13 +85,21 @@ } else { - CryptoPP::HMAC hmac(reinterpret_cast(key().data()), - key().length()); + I(key().size() == CryptoPP::SHA::DIGESTSIZE); + I(key().size() == hmac_val().size()); + byte keybuf[CryptoPP::SHA::DIGESTSIZE]; + for (size_t i = 0; i < sizeof(keybuf); i++) + { + keybuf[i] = key()[i] ^ hmac_val()[i]; + } + CryptoPP::HMAC hmac(keybuf, sizeof(keybuf)); char digest[CryptoPP::SHA::DIGESTSIZE]; hmac.CalculateDigest(reinterpret_cast(digest), reinterpret_cast(out.data() + oldlen), out.size() - oldlen); - out.append(digest, sizeof(digest)); + string digest_str(digest, sizeof(digest)); + hmac_val = netsync_hmac_value(digest_str); + out.append(digest_str); } } @@ -111,7 +120,8 @@ } bool -netcmd::read(string & inbuf, netsync_session_key const & key) +netcmd::read(string & inbuf, netsync_session_key const & key, + netsync_hmac_value & hmac_val) { size_t pos = 0; @@ -214,9 +224,15 @@ string cmd_digest = extract_substring(inbuf, pos, CryptoPP::SHA::DIGESTSIZE, "netcmd HMAC"); inbuf.erase(0, pos); + I(key().size() == CryptoPP::SHA::DIGESTSIZE); + I(key().size() == hmac_val().size()); + byte keybuf[CryptoPP::SHA::DIGESTSIZE]; + for (size_t i = 0; i < sizeof(keybuf); i++) + { + keybuf[i] = key()[i] ^ hmac_val()[i]; + } + CryptoPP::HMAC hmac(keybuf, sizeof(keybuf)); char digest_buf[CryptoPP::SHA::DIGESTSIZE]; - CryptoPP::HMAC hmac(reinterpret_cast(key().data()), - key().length()); hmac.CalculateDigest(reinterpret_cast(digest_buf), reinterpret_cast(payload.data()), payload.size()); @@ -224,6 +240,7 @@ if (cmd_digest != digest) throw bad_decode(F("bad HMAC %s vs. %s") % encode_hexenc(cmd_digest) % encode_hexenc(digest)); + hmac_val = netsync_hmac_value(digest); payload.erase(0, payload_pos); } --- netcmd.hh +++ netcmd.hh @@ -62,8 +62,12 @@ // basic cmd i/o (including checksums) - void write(std::string & out, netsync_session_key const & key = netsync_session_key()) const; - bool read(std::string & inbuf, netsync_session_key const & key = netsync_session_key()); + void write(std::string & out, + netsync_session_key const & key = netsync_session_key(constants::netsync_key_initializer), + netsync_hmac_value & hmac_val = netsync_hmac_value(constants::netsync_key_initializer)) const; + bool read(std::string & inbuf, + netsync_session_key const & key = netsync_session_key(constants::netsync_key_initializer), + netsync_hmac_value & hmac_val = netsync_hmac_value(constants::netsync_key_initializer)); // i/o functions for each type of command payload void read_error_cmd(std::string & errmsg) const; --- netsync.cc +++ netsync.cc @@ -272,6 +272,8 @@ id remote_peer_key_hash; rsa_keypair_id remote_peer_key_name; netsync_session_key session_key; + netsync_hmac_value read_hmac; + netsync_hmac_value write_hmac; bool authenticated; time_t last_io_time; @@ -485,6 +487,9 @@ pattern(""), remote_peer_key_hash(""), remote_peer_key_name(""), + session_key(constants::netsync_key_initializer), + read_hmac(constants::netsync_key_initializer), + write_hmac(constants::netsync_key_initializer), authenticated(false), last_io_time(::time(NULL)), byte_in_ticker(NULL), @@ -774,7 +779,7 @@ session::write_netcmd_and_try_flush(netcmd const & cmd) { if (!encountered_error) - cmd.write(outbuf, session_key); + cmd.write(outbuf, session_key, write_hmac); else L(F("dropping outgoing netcmd (because we're in error unwind mode)\n")); // FIXME: this helps keep the protocol pipeline full but it seems to @@ -3298,7 +3303,7 @@ { if (!armed) { - if (cmd.read(inbuf, session_key)) + if (cmd.read(inbuf, session_key, read_hmac)) { // inbuf.erase(0, cmd.encoded_size()); armed = true; --- vocab.cc +++ vocab.cc @@ -108,18 +108,37 @@ if (val.ok) return; - if (val().length() == 0) + if (val().size() == 0) { val.s.append(constants::netsync_session_key_length_in_bytes, 0); return; } - N(val().length() == constants::netsync_session_key_length_in_bytes, + N(val().size() == constants::netsync_session_key_length_in_bytes, F("Invalid key length of %d bytes") % val().length()); val.ok = true; } +inline void +verify(netsync_hmac_value & val) +{ + if (val.ok) + return; + + if (val().size() == 0) + { + val.s.append(constants::netsync_hmac_value_length_in_bytes, 0); + return; + } + + N(val().size() == constants::netsync_hmac_value_length_in_bytes, + F("Invalid key length of %d bytes") % val().length()); + + val.ok = true; +} + + inline void verify(local_path & val) { --- vocab_terms.hh +++ vocab_terms.hh @@ -37,6 +37,7 @@ ATOMIC_NOVERIFY(rsa_oaep_sha_data); ATOMIC(netsync_session_key); // key for netsync session HMAC +ATOMIC(netsync_hmac_value); // 160-bit SHA-1 HMAC DECORATE(revision); // thing associated with a revision DECORATE(manifest); // thing associated with a manifest