test_security_curve.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
  3. This file is part of libzmq, the ZeroMQ core engine in C++.
  4. libzmq is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU Lesser General Public License (LGPL) as published
  6. by the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. As a special exception, the Contributors give you permission to link
  9. this library with independent modules to produce an executable,
  10. regardless of the license terms of these independent modules, and to
  11. copy and distribute the resulting executable under terms of your choice,
  12. provided that you also meet, for each linked independent module, the
  13. terms and conditions of the license of that module. An independent
  14. module is a module which is not derived from or based on this library.
  15. If you modify this library, you must extend this exception to your
  16. version of the library.
  17. libzmq is distributed in the hope that it will be useful, but WITHOUT
  18. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  20. License for more details.
  21. You should have received a copy of the GNU Lesser General Public License
  22. along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. // TODO remove this workaround for handling libsodium/tweetnacl
  25. // To define SIZE_MAX with older compilers
  26. #define __STDC_LIMIT_MACROS
  27. #if defined ZMQ_CUSTOM_PLATFORM_HPP
  28. #include "platform.hpp"
  29. #else
  30. #include "../src/platform.hpp"
  31. #endif
  32. #ifndef ZMQ_USE_TWEETNACL
  33. #define ZMQ_USE_TWEETNACL
  34. #endif
  35. #ifdef ZMQ_USE_LIBSODIUM
  36. #undef ZMQ_USE_LIBSODIUM
  37. #endif
  38. #include "testutil.hpp"
  39. #include "testutil_security.hpp"
  40. #include <unity.h>
  41. #include "../src/tweetnacl.h"
  42. #include "../src/curve_client_tools.hpp"
  43. #include "../src/random.hpp"
  44. char error_message_buffer[256];
  45. void *handler;
  46. void *zap_thread;
  47. void *server;
  48. void *server_mon;
  49. char my_endpoint[MAX_SOCKET_STRING];
  50. void setUp ()
  51. {
  52. setup_test_context ();
  53. setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
  54. my_endpoint);
  55. }
  56. void tearDown ()
  57. {
  58. shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
  59. teardown_test_context ();
  60. }
  61. const int timeout = 250;
  62. const char large_routing_id[] = "0123456789012345678901234567890123456789"
  63. "0123456789012345678901234567890123456789"
  64. "0123456789012345678901234567890123456789"
  65. "0123456789012345678901234567890123456789"
  66. "0123456789012345678901234567890123456789"
  67. "0123456789012345678901234567890123456789"
  68. "012345678901234";
  69. static void zap_handler_large_routing_id (void * /*unused_*/)
  70. {
  71. zap_handler_generic (zap_ok, large_routing_id);
  72. }
  73. void expect_new_client_curve_bounce_fail (const char *server_public_,
  74. const char *client_public_,
  75. const char *client_secret_,
  76. char *my_endpoint_,
  77. void *server_,
  78. void **client_mon_ = NULL,
  79. int expected_client_event_ = 0,
  80. int expected_client_value_ = 0)
  81. {
  82. curve_client_data_t curve_client_data = {server_public_, client_public_,
  83. client_secret_};
  84. expect_new_client_bounce_fail (
  85. my_endpoint_, server_, socket_config_curve_client, &curve_client_data,
  86. client_mon_, expected_client_event_, expected_client_value_);
  87. }
  88. void test_null_key (void *server_,
  89. void *server_mon_,
  90. char *my_endpoint_,
  91. char *server_public_,
  92. char *client_public_,
  93. char *client_secret_)
  94. {
  95. expect_new_client_curve_bounce_fail (server_public_, client_public_,
  96. client_secret_, my_endpoint_, server_);
  97. int handshake_failed_encryption_event_count =
  98. expect_monitor_event_multiple (server_mon_,
  99. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  100. ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
  101. // handshake_failed_encryption_event_count should be at least two because
  102. // expect_bounce_fail involves two exchanges
  103. // however, with valgrind we see only one event (maybe the next one takes
  104. // very long, or does not happen at all because something else takes very
  105. // long)
  106. fprintf (stderr,
  107. "count of "
  108. "ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL/"
  109. "ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC events: %i\n",
  110. handshake_failed_encryption_event_count);
  111. }
  112. void test_curve_security_with_valid_credentials ()
  113. {
  114. curve_client_data_t curve_client_data = {
  115. valid_server_public, valid_client_public, valid_client_secret};
  116. void *client_mon;
  117. void *client = create_and_connect_client (
  118. my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
  119. bounce (server, client);
  120. test_context_socket_close (client);
  121. int event = get_monitor_event_with_timeout (server_mon, NULL, NULL, -1);
  122. assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  123. assert_no_more_monitor_events_with_timeout (server_mon, timeout);
  124. event = get_monitor_event_with_timeout (client_mon, NULL, NULL, -1);
  125. assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  126. assert_no_more_monitor_events_with_timeout (client_mon, timeout);
  127. test_context_socket_close (client_mon);
  128. }
  129. void test_curve_security_with_bogus_client_credentials ()
  130. {
  131. // This must be caught by the ZAP handler
  132. char bogus_public[41];
  133. char bogus_secret[41];
  134. zmq_curve_keypair (bogus_public, bogus_secret);
  135. expect_new_client_curve_bounce_fail (
  136. valid_server_public, bogus_public, bogus_secret, my_endpoint, server,
  137. NULL, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
  138. int server_event_count = 0;
  139. server_event_count = expect_monitor_event_multiple (
  140. server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
  141. TEST_ASSERT_LESS_OR_EQUAL_INT (1, server_event_count);
  142. // there may be more than one ZAP request due to repeated attempts by the client
  143. TEST_ASSERT (0 == server_event_count
  144. || 1 <= zmq_atomic_counter_value (zap_requests_handled));
  145. }
  146. void expect_zmtp_mechanism_mismatch (void *client_,
  147. char *my_endpoint_,
  148. void *server_,
  149. void *server_mon_)
  150. {
  151. // This must be caught by the curve_server class, not passed to ZAP
  152. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_, my_endpoint_));
  153. expect_bounce_fail (server_, client_);
  154. test_context_socket_close_zero_linger (client_);
  155. expect_monitor_event_multiple (server_mon_,
  156. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  157. ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH);
  158. TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_value (zap_requests_handled));
  159. }
  160. void test_curve_security_with_null_client_credentials ()
  161. {
  162. void *client = test_context_socket (ZMQ_DEALER);
  163. expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
  164. }
  165. void test_curve_security_with_plain_client_credentials ()
  166. {
  167. void *client = test_context_socket (ZMQ_DEALER);
  168. TEST_ASSERT_SUCCESS_ERRNO (
  169. zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5));
  170. TEST_ASSERT_SUCCESS_ERRNO (
  171. zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8));
  172. expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
  173. }
  174. void test_curve_security_unauthenticated_message ()
  175. {
  176. // Unauthenticated messages from a vanilla socket shouldn't be received
  177. fd_t s = connect_socket (my_endpoint);
  178. // send anonymous ZMTP/1.0 greeting
  179. send (s, "\x01\x00", 2, 0);
  180. // send sneaky message that shouldn't be received
  181. send (s, "\x08\x00sneaky\0", 9, 0);
  182. zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
  183. char *buf = s_recv (server);
  184. TEST_ASSERT_NULL_MESSAGE (buf, "Received unauthenticated message");
  185. close (s);
  186. }
  187. void send_all (fd_t fd_, const char *data_, socket_size_t size_)
  188. {
  189. while (size_ > 0) {
  190. int res = send (fd_, data_, size_, 0);
  191. TEST_ASSERT_GREATER_THAN_INT (0, res);
  192. size_ -= res;
  193. data_ += res;
  194. }
  195. }
  196. template <size_t N> void send (fd_t fd_, const char (&data_)[N])
  197. {
  198. send_all (fd_, data_, N - 1);
  199. }
  200. template <size_t N> void send (fd_t fd_, const uint8_t (&data_)[N])
  201. {
  202. send_all (fd_, reinterpret_cast<const char *> (&data_), N);
  203. }
  204. void test_curve_security_invalid_hello_wrong_length ()
  205. {
  206. fd_t s = connect_socket (my_endpoint);
  207. send (s, zmtp_greeting_curve);
  208. // send CURVE HELLO of wrong size
  209. send (s, "\x04\x06\x05HELLO");
  210. expect_monitor_event_multiple (
  211. server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  212. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
  213. close (s);
  214. }
  215. const size_t hello_length = 200;
  216. const size_t welcome_length = 168;
  217. zmq::curve_client_tools_t make_curve_client_tools ()
  218. {
  219. uint8_t valid_client_secret_decoded[32];
  220. uint8_t valid_client_public_decoded[32];
  221. zmq_z85_decode (valid_client_public_decoded, valid_client_public);
  222. zmq_z85_decode (valid_client_secret_decoded, valid_client_secret);
  223. uint8_t valid_server_public_decoded[32];
  224. zmq_z85_decode (valid_server_public_decoded, valid_server_public);
  225. return zmq::curve_client_tools_t (valid_client_public_decoded,
  226. valid_client_secret_decoded,
  227. valid_server_public_decoded);
  228. }
  229. // same as htonll, which is only available on few platforms (recent Windows, but not on Linux, e.g.(
  230. static uint64_t host_to_network (uint64_t value_)
  231. {
  232. // The answer is 42
  233. static const int num = 42;
  234. // Check the endianness
  235. if (*reinterpret_cast<const char *> (&num) == num) {
  236. const uint32_t high_part = htonl (static_cast<uint32_t> (value_ >> 32));
  237. const uint32_t low_part =
  238. htonl (static_cast<uint32_t> (value_ & 0xFFFFFFFFLL));
  239. return (static_cast<uint64_t> (low_part) << 32) | high_part;
  240. }
  241. return value_;
  242. }
  243. template <size_t N> void send_command (fd_t s_, char (&command_)[N])
  244. {
  245. if (N < 256) {
  246. send (s_, "\x04");
  247. char len = (char) N;
  248. send_all (s_, &len, 1);
  249. } else {
  250. send (s_, "\x06");
  251. uint64_t len = host_to_network (N);
  252. send_all (s_, reinterpret_cast<char *> (&len), 8);
  253. }
  254. send_all (s_, command_, N);
  255. }
  256. void test_curve_security_invalid_hello_command_name ()
  257. {
  258. fd_t s = connect_socket (my_endpoint);
  259. send (s, zmtp_greeting_curve);
  260. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  261. // send CURVE HELLO with a misspelled command name (but otherwise correct)
  262. char hello[hello_length];
  263. TEST_ASSERT_SUCCESS_ERRNO (tools.produce_hello (hello, 0));
  264. hello[5] = 'X';
  265. send_command (s, hello);
  266. expect_monitor_event_multiple (server_mon,
  267. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  268. ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
  269. close (s);
  270. }
  271. void test_curve_security_invalid_hello_version ()
  272. {
  273. fd_t s = connect_socket (my_endpoint);
  274. send (s, zmtp_greeting_curve);
  275. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  276. // send CURVE HELLO with a wrong version number (but otherwise correct)
  277. char hello[hello_length];
  278. TEST_ASSERT_SUCCESS_ERRNO (tools.produce_hello (hello, 0));
  279. hello[6] = 2;
  280. send_command (s, hello);
  281. expect_monitor_event_multiple (
  282. server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  283. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
  284. close (s);
  285. }
  286. void flush_read (fd_t fd_)
  287. {
  288. int res;
  289. char buf[256];
  290. while ((res = recv (fd_, buf, 256, 0)) == 256) {
  291. }
  292. TEST_ASSERT_NOT_EQUAL (-1, res);
  293. }
  294. void recv_all (fd_t fd_, uint8_t *data_, socket_size_t len_)
  295. {
  296. socket_size_t received = 0;
  297. while (received < len_) {
  298. int res = recv (fd_, reinterpret_cast<char *> (data_), len_, 0);
  299. TEST_ASSERT_GREATER_THAN_INT (0, res);
  300. data_ += res;
  301. received += res;
  302. }
  303. }
  304. void recv_greeting (fd_t fd_)
  305. {
  306. uint8_t greeting[64];
  307. recv_all (fd_, greeting, 64);
  308. // TODO assert anything about the greeting received from the server?
  309. }
  310. fd_t connect_exchange_greeting_and_send_hello (
  311. char *my_endpoint_, zmq::curve_client_tools_t &tools_)
  312. {
  313. fd_t s = connect_socket (my_endpoint_);
  314. send (s, zmtp_greeting_curve);
  315. recv_greeting (s);
  316. // send valid CURVE HELLO
  317. char hello[hello_length];
  318. TEST_ASSERT_SUCCESS_ERRNO (tools_.produce_hello (hello, 0));
  319. send_command (s, hello);
  320. return s;
  321. }
  322. void test_curve_security_invalid_initiate_wrong_length ()
  323. {
  324. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  325. fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint, tools);
  326. // receive but ignore WELCOME
  327. flush_read (s);
  328. int res = get_monitor_event_with_timeout (server_mon, NULL, NULL, timeout);
  329. TEST_ASSERT_EQUAL_INT (-1, res);
  330. send (s, "\x04\x09\x08INITIATE");
  331. expect_monitor_event_multiple (
  332. server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  333. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE);
  334. close (s);
  335. }
  336. fd_t connect_exchange_greeting_and_hello_welcome (
  337. char *my_endpoint_,
  338. void *server_mon_,
  339. int timeout_,
  340. zmq::curve_client_tools_t &tools_)
  341. {
  342. fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint_, tools_);
  343. // receive but ignore WELCOME
  344. uint8_t welcome[welcome_length + 2];
  345. recv_all (s, welcome, welcome_length + 2);
  346. uint8_t cn_precom[crypto_box_BEFORENMBYTES];
  347. TEST_ASSERT_SUCCESS_ERRNO (
  348. tools_.process_welcome (welcome + 2, welcome_length, cn_precom));
  349. const int res =
  350. get_monitor_event_with_timeout (server_mon_, NULL, NULL, timeout_);
  351. TEST_ASSERT_EQUAL_INT (-1, res);
  352. return s;
  353. }
  354. void test_curve_security_invalid_initiate_command_name ()
  355. {
  356. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  357. fd_t s = connect_exchange_greeting_and_hello_welcome (
  358. my_endpoint, server_mon, timeout, tools);
  359. char initiate[257];
  360. tools.produce_initiate (initiate, 257, 1, NULL, 0);
  361. // modify command name
  362. initiate[5] = 'X';
  363. send_command (s, initiate);
  364. expect_monitor_event_multiple (server_mon,
  365. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  366. ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
  367. close (s);
  368. }
  369. void test_curve_security_invalid_initiate_command_encrypted_cookie ()
  370. {
  371. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  372. fd_t s = connect_exchange_greeting_and_hello_welcome (
  373. my_endpoint, server_mon, timeout, tools);
  374. char initiate[257];
  375. tools.produce_initiate (initiate, 257, 1, NULL, 0);
  376. // make garbage from encrypted cookie
  377. initiate[30] = !initiate[30];
  378. send_command (s, initiate);
  379. expect_monitor_event_multiple (server_mon,
  380. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  381. ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
  382. close (s);
  383. }
  384. void test_curve_security_invalid_initiate_command_encrypted_content ()
  385. {
  386. zmq::curve_client_tools_t tools = make_curve_client_tools ();
  387. fd_t s = connect_exchange_greeting_and_hello_welcome (
  388. my_endpoint, server_mon, timeout, tools);
  389. char initiate[257];
  390. tools.produce_initiate (initiate, 257, 1, NULL, 0);
  391. // make garbage from encrypted content
  392. initiate[150] = !initiate[150];
  393. send_command (s, initiate);
  394. expect_monitor_event_multiple (server_mon,
  395. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
  396. ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
  397. close (s);
  398. }
  399. void test_curve_security_invalid_keysize (void *ctx_)
  400. {
  401. // Check return codes for invalid buffer sizes
  402. void *client = zmq_socket (ctx_, ZMQ_DEALER);
  403. TEST_ASSERT_NOT_NULL (client);
  404. errno = 0;
  405. int rc =
  406. zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, valid_server_public, 123);
  407. assert (rc == -1 && errno == EINVAL);
  408. errno = 0;
  409. rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, valid_client_public, 123);
  410. assert (rc == -1 && errno == EINVAL);
  411. errno = 0;
  412. rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, valid_client_secret, 123);
  413. assert (rc == -1 && errno == EINVAL);
  414. TEST_ASSERT_SUCCESS_ERRNO (zmq_close (client));
  415. }
  416. // TODO why isn't this const?
  417. char null_key[] = "0000000000000000000000000000000000000000";
  418. void test_null_server_key ()
  419. {
  420. // Check CURVE security with a null server key
  421. // This will be caught by the curve_server class, not passed to ZAP
  422. test_null_key (server, server_mon, my_endpoint, null_key,
  423. valid_client_public, valid_client_secret);
  424. }
  425. void test_null_client_public_key ()
  426. {
  427. // Check CURVE security with a null client public key
  428. // This will be caught by the curve_server class, not passed to ZAP
  429. test_null_key (server, server_mon, my_endpoint, valid_server_public,
  430. null_key, valid_client_secret);
  431. }
  432. void test_null_client_secret_key ()
  433. {
  434. // Check CURVE security with a null client public key
  435. // This will be caught by the curve_server class, not passed to ZAP
  436. test_null_key (server, server_mon, my_endpoint, valid_server_public,
  437. valid_client_public, null_key);
  438. }
  439. int main (void)
  440. {
  441. if (!zmq_has ("curve")) {
  442. printf ("CURVE encryption not installed, skipping test\n");
  443. return 0;
  444. }
  445. zmq::random_open ();
  446. setup_testutil_security_curve ();
  447. setup_test_environment ();
  448. UNITY_BEGIN ();
  449. RUN_TEST (test_curve_security_with_valid_credentials);
  450. RUN_TEST (test_null_server_key);
  451. RUN_TEST (test_null_client_public_key);
  452. RUN_TEST (test_null_client_secret_key);
  453. RUN_TEST (test_curve_security_with_bogus_client_credentials);
  454. RUN_TEST (test_curve_security_with_null_client_credentials);
  455. RUN_TEST (test_curve_security_with_plain_client_credentials);
  456. RUN_TEST (test_curve_security_unauthenticated_message);
  457. // tests with misbehaving CURVE client
  458. RUN_TEST (test_curve_security_invalid_hello_wrong_length);
  459. RUN_TEST (test_curve_security_invalid_hello_command_name);
  460. RUN_TEST (test_curve_security_invalid_hello_version);
  461. RUN_TEST (test_curve_security_invalid_initiate_wrong_length);
  462. RUN_TEST (test_curve_security_invalid_initiate_command_name);
  463. RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_cookie);
  464. RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_content);
  465. // TODO this requires a deviating test setup, must be moved to a separate executable/fixture
  466. // test with a large routing id (resulting in large metadata)
  467. fprintf (stderr,
  468. "test_curve_security_with_valid_credentials (large routing id)\n");
  469. setup_test_context ();
  470. setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
  471. my_endpoint, &zap_handler_large_routing_id,
  472. &socket_config_curve_server,
  473. &valid_server_secret, large_routing_id);
  474. test_curve_security_with_valid_credentials ();
  475. shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
  476. teardown_test_context ();
  477. void *ctx = zmq_ctx_new ();
  478. test_curve_security_invalid_keysize (ctx);
  479. TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
  480. zmq::random_close ();
  481. return UNITY_END ();
  482. }