Commit e40d4b23 authored by Pieter Hintjens's avatar Pieter Hintjens

Merge pull request #1189 from steamraven/master

Problem: curve messages can be replayed
parents fe4396c5 0900a489
......@@ -34,6 +34,8 @@
zmq::curve_client_t::curve_client_t (const options_t &options_) :
mechanism_t (options_),
state (send_hello),
cn_nonce(1),
cn_peer_nonce(1),
sync()
{
memcpy (public_key, options_.curve_public_key, crypto_box_PUBLICKEYBYTES);
......@@ -120,7 +122,7 @@ int zmq::curve_client_t::encode (msg_t *msg_)
uint8_t message_nonce [crypto_box_NONCEBYTES];
memcpy (message_nonce, "CurveZMQMESSAGEC", 16);
memcpy (message_nonce + 16, &cn_nonce, 8);
put_uint64 (message_nonce + 16, cn_nonce);
const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size ();
......@@ -148,7 +150,7 @@ int zmq::curve_client_t::encode (msg_t *msg_)
uint8_t *message = static_cast <uint8_t *> (msg_->data ());
memcpy (message, "\x07MESSAGE", 8);
memcpy (message + 8, &cn_nonce, 8);
memcpy (message + 8, message_nonce + 16, 8);
memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
......@@ -178,6 +180,13 @@ int zmq::curve_client_t::decode (msg_t *msg_)
uint8_t message_nonce [crypto_box_NONCEBYTES];
memcpy (message_nonce, "CurveZMQMESSAGES", 16);
memcpy (message_nonce + 16, message + 8, 8);
uint64_t nonce = get_uint64(message + 8);
if (nonce <= cn_peer_nonce) {
errno = EPROTO;
return -1;
}
cn_peer_nonce = nonce;
const size_t clen = crypto_box_BOXZEROBYTES + (msg_->size () - 16);
......@@ -236,7 +245,7 @@ int zmq::curve_client_t::produce_hello (msg_t *msg_)
// Prepare the full nonce
memcpy (hello_nonce, "CurveZMQHELLO---", 16);
memcpy (hello_nonce + 16, &cn_nonce, 8);
put_uint64 (hello_nonce + 16, cn_nonce);
// Create Box [64 * %x0](C'->S)
memset (hello_plaintext, 0, sizeof hello_plaintext);
......@@ -355,7 +364,7 @@ int zmq::curve_client_t::produce_initiate (msg_t *msg_)
const size_t mlen = ptr - initiate_plaintext;
memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
memcpy (initiate_nonce + 16, &cn_nonce, 8);
put_uint64 (initiate_nonce + 16, cn_nonce);
rc = crypto_box (initiate_box, initiate_plaintext,
mlen, initiate_nonce, cn_server, cn_secret);
......@@ -370,7 +379,7 @@ int zmq::curve_client_t::produce_initiate (msg_t *msg_)
// Cookie provided by the server in the WELCOME command
memcpy (initiate + 9, cn_cookie, 96);
// Short nonce, prefixed by "CurveZMQINITIATE"
memcpy (initiate + 105, &cn_nonce, 8);
memcpy (initiate + 105, initiate_nonce + 16, 8);
// Box [C + vouch + metadata](C'->S')
memcpy (initiate + 113, initiate_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
......@@ -399,6 +408,7 @@ int zmq::curve_client_t::process_ready (
memcpy (ready_nonce, "CurveZMQREADY---", 16);
memcpy (ready_nonce + 16, msg_data + 6, 8);
cn_peer_nonce = get_uint64(msg_data + 6);
int rc = crypto_box_open_afternm (ready_plaintext, ready_box,
clen, ready_nonce, cn_precom);
......
......@@ -102,6 +102,7 @@ namespace zmq
// Nonce
uint64_t cn_nonce;
uint64_t cn_peer_nonce;
int produce_hello (msg_t *msg_);
int process_welcome (const uint8_t *cmd_data, size_t data_size);
......
......@@ -39,6 +39,7 @@ zmq::curve_server_t::curve_server_t (session_base_t *session_,
peer_address (peer_address_),
state (expect_hello),
cn_nonce (1),
cn_peer_nonce(1),
sync()
{
// Fetch our secret key from socket options
......@@ -125,7 +126,7 @@ int zmq::curve_server_t::encode (msg_t *msg_)
uint8_t message_nonce [crypto_box_NONCEBYTES];
memcpy (message_nonce, "CurveZMQMESSAGES", 16);
memcpy (message_nonce + 16, &cn_nonce, 8);
put_uint64 (message_nonce + 16, cn_nonce);
uint8_t flags = 0;
if (msg_->flags () & msg_t::more)
......@@ -155,7 +156,7 @@ int zmq::curve_server_t::encode (msg_t *msg_)
uint8_t *message = static_cast <uint8_t *> (msg_->data ());
memcpy (message, "\x07MESSAGE", 8);
memcpy (message + 8, &cn_nonce, 8);
memcpy (message + 8, message_nonce + 16, 8);
memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
......@@ -189,6 +190,12 @@ int zmq::curve_server_t::decode (msg_t *msg_)
uint8_t message_nonce [crypto_box_NONCEBYTES];
memcpy (message_nonce, "CurveZMQMESSAGEC", 16);
memcpy (message_nonce + 16, message + 8, 8);
uint64_t nonce = get_uint64(message + 8);
if (nonce <= cn_peer_nonce) {
errno = EPROTO;
return -1;
}
cn_peer_nonce = nonce;
const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16;
......@@ -291,6 +298,7 @@ int zmq::curve_server_t::process_hello (msg_t *msg_)
memcpy (hello_nonce, "CurveZMQHELLO---", 16);
memcpy (hello_nonce + 16, hello + 112, 8);
cn_peer_nonce = get_uint64(hello + 112);
memset (hello_box, 0, crypto_box_BOXZEROBYTES);
memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80);
......@@ -430,6 +438,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
memcpy (initiate_nonce + 16, initiate + 105, 8);
cn_peer_nonce = get_uint64(initiate + 105);
rc = crypto_box_open (initiate_plaintext, initiate_box,
clen, initiate_nonce, cn_client, cn_secret);
......@@ -522,7 +531,7 @@ int zmq::curve_server_t::produce_ready (msg_t *msg_)
const size_t mlen = ptr - ready_plaintext;
memcpy (ready_nonce, "CurveZMQREADY---", 16);
memcpy (ready_nonce + 16, &cn_nonce, 8);
put_uint64 (ready_nonce + 16, cn_nonce);
int rc = crypto_box_afternm (ready_box, ready_plaintext,
mlen, ready_nonce, cn_precom);
......@@ -535,7 +544,7 @@ int zmq::curve_server_t::produce_ready (msg_t *msg_)
memcpy (ready, "\x05READY", 6);
// Short nonce, prefixed by "CurveZMQREADY---"
memcpy (ready + 6, &cn_nonce, 8);
memcpy (ready + 6, ready_nonce + 16, 8);
// Box [metadata](S'->C')
memcpy (ready + 14, ready_box + crypto_box_BOXZEROBYTES,
mlen - crypto_box_BOXZEROBYTES);
......
......@@ -90,6 +90,7 @@ namespace zmq
std::string status_code;
uint64_t cn_nonce;
uint64_t cn_peer_nonce;
// Our secret key (s)
uint8_t secret_key [crypto_box_SECRETKEYBYTES];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment