diff --git a/CMakeLists.txt b/CMakeLists.txt index c3eadb21..9af932d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -484,6 +484,7 @@ set (cxx-sources client.cpp clock.cpp ctx.cpp + curve_mechanism_base.cpp curve_client.cpp curve_server.cpp dealer.cpp @@ -504,6 +505,7 @@ set (cxx-sources mailbox.cpp mailbox_safe.cpp mechanism.cpp + mechanism_base.cpp metadata.cpp msg.cpp mtrie.cpp diff --git a/Makefile.am b/Makefile.am index 671640f3..bd971d49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,8 @@ src_libzmq_la_SOURCES = \ src/curve_client.cpp \ src/curve_client.hpp \ src/curve_client_tools.hpp \ + src/curve_mechanism_base.cpp \ + src/curve_mechanism_base.hpp \ src/curve_server.cpp \ src/curve_server.hpp \ src/dbuffer.hpp \ @@ -97,6 +99,8 @@ src_libzmq_la_SOURCES = \ src/mailbox_safe.hpp \ src/mechanism.cpp \ src/mechanism.hpp \ + src/mechanism_base.cpp \ + src/mechanism_base.hpp \ src/metadata.cpp \ src/metadata.hpp \ src/msg.cpp \ diff --git a/builds/gyp/project.gyp b/builds/gyp/project.gyp index 73fa3bbb..a89366c0 100644 --- a/builds/gyp/project.gyp +++ b/builds/gyp/project.gyp @@ -80,6 +80,9 @@ '../../src/ctx.hpp', '../../src/curve_client.cpp', '../../src/curve_client.hpp', + '../../src/curve_client_tools.hpp', + '../../src/curve_mechanism_base.cpp', + '../../src/curve_mechanism_base.hpp', '../../src/curve_server.cpp', '../../src/curve_server.hpp', '../../src/dbuffer.hpp', @@ -136,6 +139,8 @@ '../../src/mailbox_safe.hpp', '../../src/mechanism.cpp', '../../src/mechanism.hpp ', + '../../src/mechanism_base.cpp', + '../../src/mechanism_base.hpp ', '../../src/metadata.cpp', '../../src/metadata.hpp', '../../src/msg.cpp', diff --git a/builds/msvc/vs2008/libzmq/libzmq.vcproj b/builds/msvc/vs2008/libzmq/libzmq.vcproj index 2077bbce..18c5521e 100644 --- a/builds/msvc/vs2008/libzmq/libzmq.vcproj +++ b/builds/msvc/vs2008/libzmq/libzmq.vcproj @@ -121,6 +121,7 @@ + @@ -173,6 +174,7 @@ + diff --git a/builds/msvc/vs2010/libzmq/libzmq.vcxproj b/builds/msvc/vs2010/libzmq/libzmq.vcxproj index 603dec3a..bc07be2b 100644 --- a/builds/msvc/vs2010/libzmq/libzmq.vcxproj +++ b/builds/msvc/vs2010/libzmq/libzmq.vcxproj @@ -180,6 +180,7 @@ + @@ -205,6 +206,7 @@ + @@ -266,6 +268,7 @@ + diff --git a/builds/msvc/vs2012/libzmq/libzmq.vcxproj b/builds/msvc/vs2012/libzmq/libzmq.vcxproj index c5c52f5c..cc0d84fd 100644 --- a/builds/msvc/vs2012/libzmq/libzmq.vcxproj +++ b/builds/msvc/vs2012/libzmq/libzmq.vcxproj @@ -1,4 +1,4 @@ - + {641C5F36-32EE-4323-B740-992B651CF9D6} @@ -180,6 +180,7 @@ + @@ -205,6 +206,7 @@ + @@ -266,6 +268,7 @@ + diff --git a/builds/msvc/vs2013/libzmq/libzmq.vcxproj b/builds/msvc/vs2013/libzmq/libzmq.vcxproj index 6957c364..3d42eaa6 100644 --- a/builds/msvc/vs2013/libzmq/libzmq.vcxproj +++ b/builds/msvc/vs2013/libzmq/libzmq.vcxproj @@ -1,4 +1,4 @@ - + {641C5F36-32EE-4323-B740-992B651CF9D6} @@ -180,6 +180,7 @@ + @@ -205,6 +206,7 @@ + @@ -266,6 +268,7 @@ + diff --git a/builds/msvc/vs2015/libzmq/libzmq.vcxproj b/builds/msvc/vs2015/libzmq/libzmq.vcxproj index 14070e0a..1b56266d 100644 --- a/builds/msvc/vs2015/libzmq/libzmq.vcxproj +++ b/builds/msvc/vs2015/libzmq/libzmq.vcxproj @@ -1,4 +1,4 @@ - + {641C5F36-32EE-4323-B740-992B651CF9D6} @@ -180,6 +180,7 @@ + @@ -205,6 +206,7 @@ + @@ -266,6 +268,7 @@ + diff --git a/builds/msvc/vs2015_xp/libzmq.vcxproj b/builds/msvc/vs2015_xp/libzmq.vcxproj index 36ee6431..69623b5a 100644 --- a/builds/msvc/vs2015_xp/libzmq.vcxproj +++ b/builds/msvc/vs2015_xp/libzmq.vcxproj @@ -1,4 +1,4 @@ - + @@ -152,6 +152,7 @@ + @@ -177,6 +178,7 @@ + @@ -242,6 +244,7 @@ + diff --git a/builds/msvc/vs2017/libzmq/libzmq.vcxproj b/builds/msvc/vs2017/libzmq/libzmq.vcxproj index 23491d12..8f3eee8d 100644 --- a/builds/msvc/vs2017/libzmq/libzmq.vcxproj +++ b/builds/msvc/vs2017/libzmq/libzmq.vcxproj @@ -1,4 +1,4 @@ - + {641C5F36-32EE-4323-B740-992B651CF9D6} @@ -180,6 +180,7 @@ + @@ -205,6 +206,7 @@ + @@ -266,6 +268,7 @@ + diff --git a/src/curve_client.cpp b/src/curve_client.cpp index 49e7c471..e1012e7c 100644 --- a/src/curve_client.cpp +++ b/src/curve_client.cpp @@ -42,12 +42,12 @@ zmq::curve_client_t::curve_client_t (session_base_t *session_, const options_t &options_) : mechanism_base_t (session_, options_), + curve_mechanism_base_t ( + session_, options_, "CurveZMQMESSAGEC", "CurveZMQMESSAGES"), state (send_hello), tools (options_.curve_public_key, options_.curve_secret_key, - options_.curve_server_key), - cn_nonce (1), - cn_peer_nonce (1) + options_.curve_server_key) { } @@ -113,134 +113,13 @@ int zmq::curve_client_t::process_handshake_command (msg_t *msg_) int zmq::curve_client_t::encode (msg_t *msg_) { zmq_assert (state == connected); - - uint8_t flags = 0; - if (msg_->flags () & msg_t::more) - flags |= 0x01; - if (msg_->flags () & msg_t::command) - flags |= 0x02; - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGEC", 16); - put_uint64 (message_nonce + 16, cn_nonce); - - const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size (); - - uint8_t *message_plaintext = static_cast (malloc (mlen)); - alloc_assert (message_plaintext); - - memset (message_plaintext, 0, crypto_box_ZEROBYTES); - message_plaintext [crypto_box_ZEROBYTES] = flags; - memcpy (message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->data (), msg_->size ()); - - uint8_t *message_box = static_cast (malloc (mlen)); - alloc_assert (message_box); - - int rc = crypto_box_afternm (message_box, message_plaintext, mlen, - message_nonce, tools.cn_precom); - zmq_assert (rc == 0); - - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); - zmq_assert (rc == 0); - - uint8_t *message = static_cast (msg_->data ()); - - memcpy (message, "\x07MESSAGE", 8); - memcpy (message + 8, message_nonce + 16, 8); - memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - - free (message_plaintext); - free (message_box); - - cn_nonce++; - - return 0; + return curve_mechanism_base_t::encode (msg_); } int zmq::curve_client_t::decode (msg_t *msg_) { zmq_assert (state == connected); - int rc = check_basic_command_structure (msg_); - if (rc == -1) - return rc; - - const uint8_t *message = static_cast (msg_->data ()); - if (msg_->size() < 8 || memcmp (message, "\x07MESSAGE", 8)) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND); - errno = EPROTO; - return -1; - } - - if (msg_->size () < 33) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE); - errno = EPROTO; - return -1; - } - - 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) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE); - errno = EPROTO; - return -1; - } - cn_peer_nonce = nonce; - - const size_t clen = crypto_box_BOXZEROBYTES + (msg_->size () - 16); - - uint8_t *message_plaintext = static_cast (malloc (clen)); - alloc_assert (message_plaintext); - - uint8_t *message_box = static_cast (malloc (clen)); - alloc_assert (message_box); - - memset (message_box, 0, crypto_box_BOXZEROBYTES); - memcpy (message_box + crypto_box_BOXZEROBYTES, - message + 16, msg_->size () - 16); - - rc = crypto_box_open_afternm (message_plaintext, message_box, clen, - message_nonce, tools.cn_precom); - if (rc == 0) { - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); - zmq_assert (rc == 0); - - const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; - if (flags & 0x01) - msg_->set_flags (msg_t::more); - if (flags & 0x02) - msg_->set_flags (msg_t::command); - - memcpy (msg_->data (), - message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->size ()); - } - else { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); - errno = EPROTO; - } - - free (message_plaintext); - free (message_box); - - return rc; + return curve_mechanism_base_t::decode (msg_); } zmq::mechanism_t::status_t zmq::curve_client_t::status () const @@ -281,7 +160,7 @@ int zmq::curve_client_t::produce_hello (msg_t *msg_) int zmq::curve_client_t::process_welcome (const uint8_t *msg_data, size_t msg_size) { - int rc = tools.process_welcome (msg_data, msg_size); + int rc = tools.process_welcome (msg_data, msg_size, cn_precom); if (rc == -1) { session->get_socket ()->event_handshake_failed_protocol ( @@ -358,7 +237,7 @@ int zmq::curve_client_t::process_ready ( cn_peer_nonce = get_uint64(msg_data + 6); int rc = crypto_box_open_afternm (ready_plaintext, ready_box, - clen, ready_nonce, tools.cn_precom); + clen, ready_nonce, cn_precom); free (ready_box); if (rc != 0) { diff --git a/src/curve_client.hpp b/src/curve_client.hpp index f5be67e7..7693ac64 100644 --- a/src/curve_client.hpp +++ b/src/curve_client.hpp @@ -32,7 +32,7 @@ #ifdef ZMQ_HAVE_CURVE -#include "mechanism.hpp" +#include "curve_mechanism_base.hpp" #include "options.hpp" #include "curve_client_tools.hpp" @@ -42,7 +42,7 @@ namespace zmq class msg_t; class session_base_t; - class curve_client_t : public mechanism_base_t + class curve_client_t : public curve_mechanism_base_t { public: @@ -72,11 +72,7 @@ namespace zmq // CURVE protocol tools curve_client_tools_t tools; - - // 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); int produce_initiate (msg_t *msg_); diff --git a/src/curve_client_tools.hpp b/src/curve_client_tools.hpp index 7ce35270..cb162115 100644 --- a/src/curve_client_tools.hpp +++ b/src/curve_client_tools.hpp @@ -251,7 +251,9 @@ struct curve_client_tools_t return produce_hello (data, server_key, cn_nonce, cn_public, cn_secret); } - int process_welcome (const uint8_t *msg_data, size_t msg_size) + int process_welcome (const uint8_t *msg_data, + size_t msg_size, + uint8_t *cn_precom) { return process_welcome (msg_data, msg_size, server_key, cn_secret, cn_server, cn_cookie, cn_precom); @@ -289,10 +291,6 @@ struct curve_client_tools_t // Cookie received from server uint8_t cn_cookie[16 + 80]; - // Intermediary buffer used to speed up boxing and unboxing. - uint8_t cn_precom[crypto_box_BEFORENMBYTES]; - - private: template static bool is_handshake_command (const uint8_t *msg_data, diff --git a/src/curve_mechanism_base.cpp b/src/curve_mechanism_base.cpp new file mode 100644 index 00000000..b61edd2e --- /dev/null +++ b/src/curve_mechanism_base.cpp @@ -0,0 +1,181 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +#include "precompiled.hpp" +#include "curve_mechanism_base.hpp" +#include "msg.hpp" +#include "wire.hpp" +#include "session_base.hpp" + +#ifdef ZMQ_HAVE_CURVE + +zmq::curve_mechanism_base_t::curve_mechanism_base_t ( + session_base_t *session_, + const options_t &options_, + const char *encode_nonce_prefix_, + const char *decode_nonce_prefix_) : + mechanism_base_t (session_, options_), + encode_nonce_prefix (encode_nonce_prefix_), + decode_nonce_prefix (decode_nonce_prefix_), + cn_nonce (1), + cn_peer_nonce (1) +{ +} + +int zmq::curve_mechanism_base_t::encode (msg_t *msg_) +{ + const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size (); + + uint8_t message_nonce [crypto_box_NONCEBYTES]; + memcpy (message_nonce, encode_nonce_prefix, 16); + put_uint64 (message_nonce + 16, cn_nonce); + + uint8_t flags = 0; + if (msg_->flags () & msg_t::more) + flags |= 0x01; + if (msg_->flags () & msg_t::command) + flags |= 0x02; + + uint8_t *message_plaintext = static_cast (malloc (mlen)); + alloc_assert (message_plaintext); + + memset (message_plaintext, 0, crypto_box_ZEROBYTES); + message_plaintext [crypto_box_ZEROBYTES] = flags; + memcpy (message_plaintext + crypto_box_ZEROBYTES + 1, + msg_->data (), msg_->size ()); + + uint8_t *message_box = static_cast (malloc (mlen)); + alloc_assert (message_box); + + int rc = crypto_box_afternm (message_box, message_plaintext, + mlen, message_nonce, cn_precom); + zmq_assert (rc == 0); + + rc = msg_->close (); + zmq_assert (rc == 0); + + rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); + zmq_assert (rc == 0); + + uint8_t *message = static_cast (msg_->data ()); + + memcpy (message, "\x07MESSAGE", 8); + memcpy (message + 8, message_nonce + 16, 8); + memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, + mlen - crypto_box_BOXZEROBYTES); + + free (message_plaintext); + free (message_box); + + cn_nonce++; + + return 0; +} + +int zmq::curve_mechanism_base_t::decode (msg_t *msg_) +{ + int rc = check_basic_command_structure (msg_); + if (rc == -1) + return -1; + + const size_t size = msg_->size (); + const uint8_t *message = static_cast (msg_->data ()); + + if (size < 8 || memcmp (message, "\x07MESSAGE", 8)) { + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND); + errno = EPROTO; + return -1; + } + + if (size < 33) { + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), + ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE); + errno = EPROTO; + return -1; + } + + uint8_t message_nonce [crypto_box_NONCEBYTES]; + memcpy (message_nonce, decode_nonce_prefix, 16); + memcpy (message_nonce + 16, message + 8, 8); + uint64_t nonce = get_uint64(message + 8); + if (nonce <= cn_peer_nonce) { + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE); + errno = EPROTO; + return -1; + } + cn_peer_nonce = nonce; + + const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16; + + uint8_t *message_plaintext = static_cast (malloc (clen)); + alloc_assert (message_plaintext); + + uint8_t *message_box = static_cast (malloc (clen)); + alloc_assert (message_box); + + memset (message_box, 0, crypto_box_BOXZEROBYTES); + memcpy (message_box + crypto_box_BOXZEROBYTES, + message + 16, msg_->size () - 16); + + rc = crypto_box_open_afternm (message_plaintext, message_box, clen, + message_nonce, cn_precom); + if (rc == 0) { + rc = msg_->close (); + zmq_assert (rc == 0); + + rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); + zmq_assert (rc == 0); + + const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; + if (flags & 0x01) + msg_->set_flags (msg_t::more); + if (flags & 0x02) + msg_->set_flags (msg_t::command); + + memcpy (msg_->data (), + message_plaintext + crypto_box_ZEROBYTES + 1, + msg_->size ()); + } + else { + // CURVE I : connection key used for MESSAGE is wrong + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); + errno = EPROTO; + } + free (message_plaintext); + free (message_box); + + return rc; +} + +#endif diff --git a/src/curve_mechanism_base.hpp b/src/curve_mechanism_base.hpp new file mode 100644 index 00000000..98cfd03d --- /dev/null +++ b/src/curve_mechanism_base.hpp @@ -0,0 +1,79 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef __ZMQ_CURVE_MECHANISM_BASE_HPP_INCLUDED__ +#define __ZMQ_CURVE_MECHANISM_BASE_HPP_INCLUDED__ + +#ifdef ZMQ_HAVE_CURVE + +#if defined(ZMQ_USE_TWEETNACL) +#include "tweetnacl.h" +#elif defined(ZMQ_USE_LIBSODIUM) +#include "sodium.h" +#endif + +#if crypto_box_NONCEBYTES != 24 || crypto_box_PUBLICKEYBYTES != 32 \ + || crypto_box_SECRETKEYBYTES != 32 || crypto_box_ZEROBYTES != 32 \ + || crypto_box_BOXZEROBYTES != 16 || crypto_secretbox_NONCEBYTES != 24 \ + || crypto_secretbox_ZEROBYTES != 32 || crypto_secretbox_BOXZEROBYTES != 16 +#error "CURVE library not built properly" +#endif + +#include "mechanism_base.hpp" +#include "options.hpp" + +namespace zmq +{ +class curve_mechanism_base_t : public virtual mechanism_base_t +{ + public: + curve_mechanism_base_t (session_base_t *session_, + const options_t &options_, + const char *encode_nonce_prefix_, + const char *decode_nonce_prefix_); + + // mechanism implementation + virtual int encode (msg_t *msg_); + virtual int decode (msg_t *msg_); + + protected: + const char *encode_nonce_prefix; + const char *decode_nonce_prefix; + + uint64_t cn_nonce; + uint64_t cn_peer_nonce; + + // Intermediary buffer used to speed up boxing and unboxing. + uint8_t cn_precom [crypto_box_BEFORENMBYTES]; +}; +} + +#endif + +#endif diff --git a/src/curve_server.cpp b/src/curve_server.cpp index aa9f5425..bbcec99b 100644 --- a/src/curve_server.cpp +++ b/src/curve_server.cpp @@ -44,8 +44,8 @@ zmq::curve_server_t::curve_server_t (session_base_t *session_, mechanism_base_t (session_, options_), zap_client_common_handshake_t ( session_, peer_address_, options_, sending_ready), - cn_nonce (1), - cn_peer_nonce (1) + curve_mechanism_base_t ( + session_, options_, "CurveZMQMESSAGES", "CurveZMQMESSAGEC") { int rc; // Fetch our secret key from socket options @@ -125,134 +125,13 @@ int zmq::curve_server_t::process_handshake_command (msg_t *msg_) int zmq::curve_server_t::encode (msg_t *msg_) { zmq_assert (state == ready); - - const size_t mlen = crypto_box_ZEROBYTES + 1 + msg_->size (); - - uint8_t message_nonce [crypto_box_NONCEBYTES]; - memcpy (message_nonce, "CurveZMQMESSAGES", 16); - put_uint64 (message_nonce + 16, cn_nonce); - - uint8_t flags = 0; - if (msg_->flags () & msg_t::more) - flags |= 0x01; - if (msg_->flags () & msg_t::command) - flags |= 0x02; - - uint8_t *message_plaintext = static_cast (malloc (mlen)); - alloc_assert (message_plaintext); - - memset (message_plaintext, 0, crypto_box_ZEROBYTES); - message_plaintext [crypto_box_ZEROBYTES] = flags; - memcpy (message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->data (), msg_->size ()); - - uint8_t *message_box = static_cast (malloc (mlen)); - alloc_assert (message_box); - - int rc = crypto_box_afternm (message_box, message_plaintext, - mlen, message_nonce, cn_precom); - zmq_assert (rc == 0); - - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES); - zmq_assert (rc == 0); - - uint8_t *message = static_cast (msg_->data ()); - - memcpy (message, "\x07MESSAGE", 8); - memcpy (message + 8, message_nonce + 16, 8); - memcpy (message + 16, message_box + crypto_box_BOXZEROBYTES, - mlen - crypto_box_BOXZEROBYTES); - - free (message_plaintext); - free (message_box); - - cn_nonce++; - - return 0; + return curve_mechanism_base_t::encode (msg_); } int zmq::curve_server_t::decode (msg_t *msg_) { zmq_assert (state == ready); - - int rc = check_basic_command_structure (msg_); - if (rc == -1) - return -1; - - const size_t size = msg_->size (); - const uint8_t *message = static_cast (msg_->data ()); - - if (size < 8 || memcmp (message, "\x07MESSAGE", 8)) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND); - errno = EPROTO; - return -1; - } - - if (size < 33) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE); - errno = EPROTO; - return -1; - } - - 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) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE); - errno = EPROTO; - return -1; - } - cn_peer_nonce = nonce; - - const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16; - - uint8_t *message_plaintext = static_cast (malloc (clen)); - alloc_assert (message_plaintext); - - uint8_t *message_box = static_cast (malloc (clen)); - alloc_assert (message_box); - - memset (message_box, 0, crypto_box_BOXZEROBYTES); - memcpy (message_box + crypto_box_BOXZEROBYTES, - message + 16, msg_->size () - 16); - - rc = crypto_box_open_afternm (message_plaintext, message_box, clen, - message_nonce, cn_precom); - if (rc == 0) { - rc = msg_->close (); - zmq_assert (rc == 0); - - rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); - zmq_assert (rc == 0); - - const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; - if (flags & 0x01) - msg_->set_flags (msg_t::more); - if (flags & 0x02) - msg_->set_flags (msg_t::command); - - memcpy (msg_->data (), - message_plaintext + crypto_box_ZEROBYTES + 1, - msg_->size ()); - } - else { - // CURVE I : connection key used for MESSAGE is wrong - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); - errno = EPROTO; - } - free (message_plaintext); - free (message_box); - - return rc; + return curve_mechanism_base_t::decode (msg_); } int zmq::curve_server_t::process_hello (msg_t *msg_) diff --git a/src/curve_server.hpp b/src/curve_server.hpp index 44562716..30efda5d 100644 --- a/src/curve_server.hpp +++ b/src/curve_server.hpp @@ -32,34 +32,18 @@ #ifdef ZMQ_HAVE_CURVE -#if defined (ZMQ_USE_TWEETNACL) -# include "tweetnacl.h" -#elif defined (ZMQ_USE_LIBSODIUM) -# include "sodium.h" -#endif - -#if crypto_box_NONCEBYTES != 24 \ -|| crypto_box_PUBLICKEYBYTES != 32 \ -|| crypto_box_SECRETKEYBYTES != 32 \ -|| crypto_box_ZEROBYTES != 32 \ -|| crypto_box_BOXZEROBYTES != 16 \ -|| crypto_secretbox_NONCEBYTES != 24 \ -|| crypto_secretbox_ZEROBYTES != 32 \ -|| crypto_secretbox_BOXZEROBYTES != 16 -# error "CURVE library not built properly" -#endif - -#include "mechanism.hpp" +#include "curve_mechanism_base.hpp" #include "options.hpp" #include "zap_client.hpp" namespace zmq { - - class msg_t; - class session_base_t; - - class curve_server_t : public zap_client_common_handshake_t +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable: 4250) +#endif + class curve_server_t : public zap_client_common_handshake_t, + public curve_mechanism_base_t { public: @@ -76,9 +60,6 @@ namespace zmq private: - uint64_t cn_nonce; - uint64_t cn_peer_nonce; - // Our secret key (s) uint8_t secret_key [crypto_box_SECRETKEYBYTES]; @@ -94,9 +75,6 @@ namespace zmq // Key used to produce cookie uint8_t cookie_key [crypto_secretbox_KEYBYTES]; - // Intermediary buffer used to speed up boxing and unboxing. - uint8_t cn_precom [crypto_box_BEFORENMBYTES]; - int process_hello (msg_t *msg_); int produce_welcome (msg_t *msg_); int process_initiate (msg_t *msg_); @@ -105,6 +83,9 @@ namespace zmq void send_zap_request (const uint8_t *key); }; +#ifdef _MSC_VER +#pragma warning (pop) +#endif } diff --git a/src/mechanism.cpp b/src/mechanism.cpp index 39117359..54c36bc3 100644 --- a/src/mechanism.cpp +++ b/src/mechanism.cpp @@ -282,24 +282,3 @@ bool zmq::mechanism_t::check_socket_type (const std::string& type_) const } return false; } - -zmq::mechanism_base_t::mechanism_base_t (session_base_t *const session_, - const options_t &options_) : - mechanism_t (options_), - session (session_) -{ - -} - -int zmq::mechanism_base_t::check_basic_command_structure (msg_t *msg_) -{ - if (msg_->size () <= 1 || msg_->size () <= ((uint8_t *) msg_->data ())[0]) { - session->get_socket ()->event_handshake_failed_protocol ( - session->get_endpoint (), - ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED); - errno = EPROTO; - return -1; - } - return 0; -} - diff --git a/src/mechanism.hpp b/src/mechanism.hpp index e07ce567..f8c05b66 100644 --- a/src/mechanism.hpp +++ b/src/mechanism.hpp @@ -147,16 +147,6 @@ namespace zmq bool check_socket_type (const std::string& type_) const; }; - class mechanism_base_t : public mechanism_t - { - protected: - mechanism_base_t (session_base_t *const session_, - const options_t &options_); - - session_base_t *const session; - - int check_basic_command_structure (msg_t *msg_); - }; - } +} #endif diff --git a/src/mechanism_base.cpp b/src/mechanism_base.cpp new file mode 100644 index 00000000..e255cb01 --- /dev/null +++ b/src/mechanism_base.cpp @@ -0,0 +1,54 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "precompiled.hpp" + +#include "mechanism_base.hpp" +#include "session_base.hpp" + +zmq::mechanism_base_t::mechanism_base_t (session_base_t *const session_, + const options_t &options_) : + mechanism_t (options_), + session (session_) +{ + +} + +int zmq::mechanism_base_t::check_basic_command_structure (msg_t *msg_) +{ + if (msg_->size () <= 1 || msg_->size () <= ((uint8_t *) msg_->data ())[0]) { + session->get_socket ()->event_handshake_failed_protocol ( + session->get_endpoint (), + ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED); + errno = EPROTO; + return -1; + } + return 0; +} + diff --git a/src/mechanism_base.hpp b/src/mechanism_base.hpp new file mode 100644 index 00000000..e98a7f7e --- /dev/null +++ b/src/mechanism_base.hpp @@ -0,0 +1,49 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef __ZMQ_MECHANISM_BASE_HPP_INCLUDED__ +#define __ZMQ_MECHANISM_BASE_HPP_INCLUDED__ + +#include "mechanism.hpp" + +namespace zmq +{ +class mechanism_base_t : public mechanism_t +{ + protected: + mechanism_base_t (session_base_t *const session_, + const options_t &options_); + + session_base_t *const session; + + int check_basic_command_structure (msg_t *msg_); +}; +} + +#endif diff --git a/src/plain_client.hpp b/src/plain_client.hpp index 6e5b5586..76789e09 100644 --- a/src/plain_client.hpp +++ b/src/plain_client.hpp @@ -30,7 +30,7 @@ #ifndef __ZMQ_PLAIN_CLIENT_HPP_INCLUDED__ #define __ZMQ_PLAIN_CLIENT_HPP_INCLUDED__ -#include "mechanism.hpp" +#include "mechanism_base.hpp" #include "options.hpp" namespace zmq diff --git a/src/zap_client.hpp b/src/zap_client.hpp index c2652bb8..557cab60 100644 --- a/src/zap_client.hpp +++ b/src/zap_client.hpp @@ -30,7 +30,7 @@ #ifndef __ZMQ_ZAP_CLIENT_HPP_INCLUDED__ #define __ZMQ_ZAP_CLIENT_HPP_INCLUDED__ -#include "mechanism.hpp" +#include "mechanism_base.hpp" namespace zmq { diff --git a/tests/test_security_curve.cpp b/tests/test_security_curve.cpp index 04ed9bfd..89bc3f05 100644 --- a/tests/test_security_curve.cpp +++ b/tests/test_security_curve.cpp @@ -491,7 +491,8 @@ int connect_exchange_greeting_and_hello_welcome ( uint8_t welcome[welcome_length + 2]; recv_all (s, welcome, welcome_length + 2); - int res = tools.process_welcome (welcome + 2, welcome_length); + uint8_t cn_precom [crypto_box_BEFORENMBYTES]; + int res = tools.process_welcome (welcome + 2, welcome_length, cn_precom); assert (res == 0); #ifdef ZMQ_BUILD_DRAFT_API