12 #ifdef ZMQ_USE_LIBSODIUM
15 #if SODIUM_LIBRARY_VERSION_MAJOR > 7 \
16 || (SODIUM_LIBRARY_VERSION_MAJOR == 7 && SODIUM_LIBRARY_VERSION_MINOR >= 4)
17 #define ZMQ_HAVE_CRYPTO_BOX_EASY_FNS 1
21 zmq::curve_mechanism_base_t::curve_mechanism_base_t (
22 session_base_t *session_,
24 const char *encode_nonce_prefix_,
25 const char *decode_nonce_prefix_,
26 const bool downgrade_sub_) :
27 mechanism_base_t (session_,
options_),
29 encode_nonce_prefix_, decode_nonce_prefix_, downgrade_sub_)
33 int zmq::curve_mechanism_base_t::encode (msg_t *msg_)
35 return curve_encoding_t::encode (msg_);
38 int zmq::curve_mechanism_base_t::decode (msg_t *msg_)
40 int rc = check_basic_command_structure (msg_);
45 rc = curve_encoding_t::decode (msg_, &error_event_code);
47 session->get_socket ()->event_handshake_failed_protocol (
48 session->get_endpoint (), error_event_code);
54 zmq::curve_encoding_t::curve_encoding_t (
const char *encode_nonce_prefix_,
55 const char *decode_nonce_prefix_,
56 const bool downgrade_sub_) :
57 _encode_nonce_prefix (encode_nonce_prefix_),
58 _decode_nonce_prefix (decode_nonce_prefix_),
61 _downgrade_sub (downgrade_sub_)
69 static const size_t flags_len = 1;
70 static const size_t nonce_prefix_len = 16;
71 static const char message_command[] =
"\x07MESSAGE";
72 static const size_t message_command_len =
sizeof (message_command) - 1;
73 static const size_t message_header_len =
74 message_command_len +
sizeof (zmq::curve_encoding_t::nonce_t);
76 #ifndef ZMQ_USE_LIBSODIUM
77 static const size_t crypto_box_MACBYTES = 16;
80 int zmq::curve_encoding_t::check_validity (msg_t *msg_,
int *error_event_code_)
82 const size_t size = msg_->size ();
83 const uint8_t *
const message =
static_cast<uint8_t *
> (msg_->data ());
85 if (
size < message_command_len
86 || 0 != memcmp (
message, message_command, message_command_len)) {
92 if (
size < message_header_len + crypto_box_MACBYTES + flags_len) {
100 if (nonce <= _cn_peer_nonce) {
105 set_peer_nonce (nonce);
111 int zmq::curve_encoding_t::encode (msg_t *msg_)
113 size_t sub_cancel_len = 0;
114 uint8_t message_nonce[crypto_box_NONCEBYTES];
115 memcpy (message_nonce, _encode_nonce_prefix, nonce_prefix_len);
116 put_uint64 (message_nonce + nonce_prefix_len, get_and_inc_nonce ());
118 if (msg_->is_subscribe () || msg_->is_cancel ()) {
122 sub_cancel_len = msg_->is_cancel ()
127 #ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
128 const size_t mlen = flags_len + sub_cancel_len + msg_->size ();
129 std::vector<uint8_t> message_plaintext (mlen);
132 crypto_box_ZEROBYTES + flags_len + sub_cancel_len + msg_->size ();
133 std::vector<uint8_t> message_plaintext_with_zerobytes (mlen);
134 uint8_t *
const message_plaintext =
135 &message_plaintext_with_zerobytes[crypto_box_ZEROBYTES];
137 std::fill (message_plaintext_with_zerobytes.begin (),
138 message_plaintext_with_zerobytes.begin () + crypto_box_ZEROBYTES,
142 const uint8_t
flags = msg_->flags () & flag_mask;
143 message_plaintext[0] =
flags;
148 if (sub_cancel_len == 1)
149 message_plaintext[flags_len] = msg_->is_subscribe () ? 1 : 0;
162 if (msg_->size () > 0)
163 memcpy (&message_plaintext[flags_len + sub_cancel_len], msg_->data (),
166 #ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
169 msg_box.init_size (message_header_len + mlen + crypto_box_MACBYTES);
172 rc = crypto_box_easy_afternm (
173 static_cast<uint8_t *
> (msg_box.data ()) + message_header_len,
174 &message_plaintext[0], mlen, message_nonce, _cn_precom);
177 msg_->move (msg_box);
179 uint8_t *
const message =
static_cast<uint8_t *
> (msg_->data ());
181 std::vector<uint8_t> message_box (mlen);
184 crypto_box_afternm (&message_box[0], &message_plaintext_with_zerobytes[0],
185 mlen, message_nonce, _cn_precom);
191 rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES);
194 uint8_t *
const message =
static_cast<uint8_t *
> (msg_->data ());
196 memcpy (
message + message_header_len, &message_box[crypto_box_BOXZEROBYTES],
197 mlen - crypto_box_BOXZEROBYTES);
200 memcpy (
message, message_command, message_command_len);
201 memcpy (
message + message_command_len, message_nonce + nonce_prefix_len,
207 int zmq::curve_encoding_t::decode (msg_t *msg_,
int *error_event_code_)
209 int rc = check_validity (msg_, error_event_code_);
214 uint8_t *
const message =
static_cast<uint8_t *
> (msg_->data ());
216 uint8_t message_nonce[crypto_box_NONCEBYTES];
217 memcpy (message_nonce, _decode_nonce_prefix, nonce_prefix_len);
218 memcpy (message_nonce + nonce_prefix_len,
message + message_command_len,
221 #ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
222 const size_t clen = msg_->size () - message_header_len;
224 uint8_t *
const message_plaintext =
message + message_header_len;
226 rc = crypto_box_open_easy_afternm (message_plaintext,
227 message + message_header_len, clen,
228 message_nonce, _cn_precom);
231 crypto_box_BOXZEROBYTES + msg_->size () - message_header_len;
233 std::vector<uint8_t> message_plaintext_with_zerobytes (clen);
234 std::vector<uint8_t> message_box (clen);
236 std::fill (message_box.begin (),
237 message_box.begin () + crypto_box_BOXZEROBYTES, 0);
238 memcpy (&message_box[crypto_box_BOXZEROBYTES],
message + message_header_len,
239 msg_->size () - message_header_len);
241 rc = crypto_box_open_afternm (&message_plaintext_with_zerobytes[0],
242 &message_box[0], clen, message_nonce,
245 const uint8_t *
const message_plaintext =
246 &message_plaintext_with_zerobytes[crypto_box_ZEROBYTES];
250 const uint8_t
flags = message_plaintext[0];
252 #ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
253 const size_t plaintext_size = clen - flags_len - crypto_box_MACBYTES;
255 if (plaintext_size > 0) {
256 memmove (msg_->data (), &message_plaintext[flags_len],
260 msg_->shrink (plaintext_size);
265 rc = msg_->init_size (clen - flags_len - crypto_box_ZEROBYTES);
270 if (msg_->size () > 0) {
271 memcpy (msg_->data (), &message_plaintext[flags_len],
276 msg_->set_flags (
flags & flag_mask);