int zmq_curve_public (char *z85_public_key, const char *z85_secret_key) { #if defined (ZMQ_HAVE_CURVE) # if crypto_box_PUBLICKEYBYTES != 32 \ || crypto_box_SECRETKEYBYTES != 32 # error "CURVE encryption library not built correctly" # endif uint8_t public_key[32]; uint8_t secret_key[32]; if (zmq_z85_decode (secret_key, z85_secret_key) == NULL) return -1; // Return codes are suppressed as none of these can actually fail. crypto_scalarmult_base (public_key, secret_key); zmq_z85_encode (z85_public_key, public_key, 32); return 0; #else (void) z85_public_key, (void) z85_secret_key; errno = ENOTSUP; return -1; #endif }
void test__zmq_z85_decode__invalid__failure (const char (&encoded_)[SIZE]) { uint8_t decoded[SIZE * 4 / 5 + 1]; errno = 0; assert (zmq_z85_decode (decoded, encoded_) == NULL); assert (zmq_errno () == EINVAL); }
zcert_t * zcert_load (char *format, ...) { #if (ZMQ_VERSION_MAJOR == 4) assert (format); va_list argptr; va_start (argptr, format); char *filename = zsys_vprintf (format, argptr); va_end (argptr); // Try first to load secret certificate, which has both keys // Then fallback to loading public certificate char filename_secret [256]; snprintf (filename_secret, 256, "%s_secret", filename); zconfig_t *root = zconfig_load (filename_secret); if (!root) root = zconfig_load (filename); zcert_t *self = NULL; if (root) { char *public_text = zconfig_resolve (root, "/curve/public-key", NULL); char *secret_text = zconfig_resolve (root, "/curve/secret-key", NULL); if (public_text && strlen (public_text) == 40) { byte public_key [32] = { 0 }; byte secret_key [32] = { 0 }; zmq_z85_decode (public_key, public_text); if (secret_text && strlen (secret_text) == 40) zmq_z85_decode (secret_key, secret_text); // Load metadata into certificate self = zcert_new_from (public_key, secret_key); zconfig_t *metadata = zconfig_locate (root, "/metadata"); zconfig_t *item = metadata? zconfig_child (metadata): NULL; while (item) { zcert_set_meta (self, zconfig_name (item), zconfig_value (item)); item = zconfig_next (item); } } } zconfig_destroy (&root); zstr_free (&filename); return self; #else return NULL; #endif }
zcert_t * zcert_new (void) { byte public_key [32] = { 0 }; byte secret_key [32] = { 0 }; #if (ZMQ_VERSION_MAJOR == 4) if (zsys_has_curve ()) { char public_txt [41]; char secret_txt [41]; int rc = zmq_curve_keypair (public_txt, secret_txt); if (rc != 0) return NULL; zmq_z85_decode (public_key, public_txt); zmq_z85_decode (secret_key, secret_txt); } #endif return zcert_new_from (public_key, secret_key); }
zcert_t * zcert_new (void) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); assert (self); // Initialize metadata, even if keys aren't working self->metadata = zhash_new (); zhash_autofree (self->metadata); #if (ZMQ_VERSION_MAJOR == 4) int rc = zmq_curve_keypair (self->public_txt, self->secret_txt); assert (rc == 0); zmq_z85_decode (self->public_key, self->public_txt); zmq_z85_decode (self->secret_key, self->secret_txt); #else strcpy (self->public_txt, "0000000000000000000000000000000000000000"); strcpy (self->secret_txt, "0000000000000000000000000000000000000000"); #endif return self; }
// Test vector: rfc.zeromq.org/spec:32/Z85 void test__zmq_z85_decode__valid__success () { static const size_t size = 10 * 4 / 5; static const uint8_t expected[size] = {0x86, 0x4F, 0xD2, 0x6F, 0xB5, 0x59, 0xF7, 0x5B}; static const char *encoded = "HelloWorld"; uint8_t out_decoded[size] = {0}; errno = 0; assert (zmq_z85_decode (out_decoded, encoded) != NULL); assert (zmq_errno () == 0); assert (memcmp (out_decoded, expected, size) == 0); }
void test__zmq_z85_encode__zmq_z85_decode__roundtrip ( const uint8_t (&test_data_)[SIZE]) { char test_data_z85[SIZE * 5 / 4 + 1]; char *res1 = zmq_z85_encode (test_data_z85, test_data_, SIZE); assert (res1 != NULL); uint8_t test_data_decoded[SIZE]; uint8_t *res2 = zmq_z85_decode (test_data_decoded, test_data_z85); assert (res2 != NULL); int res3 = memcmp (test_data_, test_data_decoded, SIZE); assert (res3 == 0); }
void test__zmq_z85_decode__zmq_z85_encode__roundtrip ( const char (&test_data_)[SIZE]) { const size_t decoded_size = (SIZE - 1) * 4 / 5; uint8_t test_data_decoded[decoded_size]; uint8_t *res1 = zmq_z85_decode (test_data_decoded, test_data_); assert (res1 != NULL); char test_data_z85[SIZE]; char *res2 = zmq_z85_encode (test_data_z85, test_data_decoded, decoded_size); assert (res2 != NULL); int res3 = memcmp (test_data_, test_data_z85, SIZE); assert (res3 == 0); }
int main (void) { void *context = zmq_ctx_new (); void *responder = zmq_socket (context, ZMQ_REP); int i=1; char skeystr[] = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6"; uint8_t server_key [32]; zmq_z85_decode (server_key, skeystr); zmq_setsockopt(responder, ZMQ_CURVE_SERVER, &i, sizeof(i)); zmq_setsockopt(responder, ZMQ_CURVE_SECRETKEY, &server_key, sizeof(server_key)); int rc = zmq_bind (responder, "tcp://*:55555"); assert (rc == 0); while (1) { char buffer [10]; zmq_recv (responder, buffer, 10, 0); printf ("Received Hello\n"); sleep (1); zmq_send (responder, "World", 5, 0); } return 0; }
JNIEXPORT jbyteArray JNICALL Java_org_zeromq_ZMQ_00024Curve_z85Decode(JNIEnv *env, jclass cls, jstring key) { #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4,0,0) const char *in_key = env->GetStringUTFChars (key, NULL); assert (in_key); uint8_t out_key [32]; if (NULL == zmq_z85_decode (out_key, in_key)) { env->ReleaseStringUTFChars (key, in_key); return NULL; } env->ReleaseStringUTFChars (key, in_key); jbyteArray result = env->NewByteArray (32); env->SetByteArrayRegion (result, 0 , 32, reinterpret_cast<jbyte*>(out_key)); return result; #else raise_exception (env, ENOTSUP); return NULL; #endif }
int zmq::options_t::setsockopt (int option_, const void *optval_, size_t optvallen_) { bool is_int = (optvallen_ == sizeof (int)); int value = is_int? *((int *) optval_): 0; #if defined (ZMQ_ACT_MILITANT) bool malformed = true; // Did caller pass a bad option value? #endif switch (option_) { case ZMQ_SNDHWM: if (is_int && value >= 0) { sndhwm = value; return 0; } break; case ZMQ_RCVHWM: if (is_int && value >= 0) { rcvhwm = value; return 0; } break; case ZMQ_AFFINITY: if (optvallen_ == sizeof (uint64_t)) { affinity = *((uint64_t*) optval_); return 0; } break; case ZMQ_IDENTITY: // Identity is any binary string from 1 to 255 octets if (optvallen_ > 0 && optvallen_ < 256) { identity_size = optvallen_; memcpy (identity, optval_, identity_size); return 0; } break; case ZMQ_RATE: if (is_int && value > 0) { rate = value; return 0; } break; case ZMQ_RECOVERY_IVL: if (is_int && value >= 0) { recovery_ivl = value; return 0; } break; case ZMQ_SNDBUF: if (is_int && value >= 0) { sndbuf = value; return 0; } break; case ZMQ_RCVBUF: if (is_int && value >= 0) { rcvbuf = value; return 0; } break; case ZMQ_TOS: if (is_int && value >= 0) { tos = value; return 0; } break; case ZMQ_LINGER: if (is_int && value >= -1) { linger = value; return 0; } break; case ZMQ_RECONNECT_IVL: if (is_int && value >= -1) { reconnect_ivl = value; return 0; } break; case ZMQ_RECONNECT_IVL_MAX: if (is_int && value >= 0) { reconnect_ivl_max = value; return 0; } break; case ZMQ_BACKLOG: if (is_int && value >= 0) { backlog = value; return 0; } break; case ZMQ_MAXMSGSIZE: if (optvallen_ == sizeof (int64_t)) { maxmsgsize = *((int64_t *) optval_); return 0; } break; case ZMQ_MULTICAST_HOPS: if (is_int && value > 0) { multicast_hops = value; return 0; } break; case ZMQ_RCVTIMEO: if (is_int && value >= -1) { rcvtimeo = value; return 0; } break; case ZMQ_SNDTIMEO: if (is_int && value >= -1) { sndtimeo = value; return 0; } break; /* Deprecated in favor of ZMQ_IPV6 */ case ZMQ_IPV4ONLY: if (is_int && (value == 0 || value == 1)) { ipv6 = (value == 0); return 0; } break; /* To replace the somewhat surprising IPV4ONLY */ case ZMQ_IPV6: if (is_int && (value == 0 || value == 1)) { ipv6 = (value != 0); return 0; } break; case ZMQ_SOCKS_PROXY: if (optval_ == NULL && optvallen_ == 0) { socks_proxy_address.clear (); return 0; } else if (optval_ != NULL && optvallen_ > 0 ) { socks_proxy_address = std::string ((const char *) optval_, optvallen_); return 0; } break; case ZMQ_TCP_KEEPALIVE: if (is_int && (value == -1 || value == 0 || value == 1)) { tcp_keepalive = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_CNT: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_cnt = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_IDLE: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_idle = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_INTVL: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_intvl = value; return 0; } break; case ZMQ_IMMEDIATE: if (is_int && (value == 0 || value == 1)) { immediate = value; return 0; } break; case ZMQ_TCP_ACCEPT_FILTER: if (optvallen_ == 0 && optval_ == NULL) { tcp_accept_filters.clear (); return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) { std::string filter_str ((const char *) optval_, optvallen_); tcp_address_mask_t mask; int rc = mask.resolve (filter_str.c_str (), ipv6); if (rc == 0) { tcp_accept_filters.push_back (mask); return 0; } } break; # if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED case ZMQ_IPC_FILTER_UID: if (optvallen_ == 0 && optval_ == NULL) { ipc_uid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (uid_t) && optval_ != NULL) { ipc_uid_accept_filters.insert (*((uid_t *) optval_)); return 0; } break; case ZMQ_IPC_FILTER_GID: if (optvallen_ == 0 && optval_ == NULL) { ipc_gid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (gid_t) && optval_ != NULL) { ipc_gid_accept_filters.insert (*((gid_t *) optval_)); return 0; } break; # endif # if defined ZMQ_HAVE_SO_PEERCRED case ZMQ_IPC_FILTER_PID: if (optvallen_ == 0 && optval_ == NULL) { ipc_pid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (pid_t) && optval_ != NULL) { ipc_pid_accept_filters.insert (*((pid_t *) optval_)); return 0; } break; # endif case ZMQ_PLAIN_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; mechanism = value? ZMQ_PLAIN: ZMQ_NULL; return 0; } break; case ZMQ_PLAIN_USERNAME: if (optvallen_ == 0 && optval_ == NULL) { mechanism = ZMQ_NULL; return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { plain_username.assign ((const char *) optval_, optvallen_); as_server = 0; mechanism = ZMQ_PLAIN; return 0; } break; case ZMQ_PLAIN_PASSWORD: if (optvallen_ == 0 && optval_ == NULL) { mechanism = ZMQ_NULL; return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { plain_password.assign ((const char *) optval_, optvallen_); as_server = 0; mechanism = ZMQ_PLAIN; return 0; } break; case ZMQ_ZAP_DOMAIN: if (optvallen_ < 256) { zap_domain.assign ((const char *) optval_, optvallen_); return 0; } break; // If libsodium isn't installed, these options provoke EINVAL # ifdef HAVE_LIBSODIUM case ZMQ_CURVE_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; mechanism = value? ZMQ_CURVE: ZMQ_NULL; return 0; } break; case ZMQ_CURVE_PUBLICKEY: // TODO: refactor repeated code for these three options // into set_curve_key (destination, optval, optlen) method // ==> set_curve_key (curve_public_key, optval_, optvallen_); if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_public_key, optval_, CURVE_KEYSIZE); mechanism = ZMQ_CURVE; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_decode (curve_public_key, (char *) optval_); mechanism = ZMQ_CURVE; return 0; } else // Deprecated, not symmetrical with zmq_getsockopt if (optvallen_ == CURVE_KEYSIZE_Z85) { char z85_key [41]; memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85); z85_key [CURVE_KEYSIZE_Z85] = 0; zmq_z85_decode (curve_public_key, z85_key); mechanism = ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_SECRETKEY: if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_secret_key, optval_, CURVE_KEYSIZE); mechanism = ZMQ_CURVE; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_decode (curve_secret_key, (char *) optval_); mechanism = ZMQ_CURVE; return 0; } else // Deprecated, not symmetrical with zmq_getsockopt if (optvallen_ == CURVE_KEYSIZE_Z85) { char z85_key [41]; memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85); z85_key [CURVE_KEYSIZE_Z85] = 0; zmq_z85_decode (curve_secret_key, z85_key); mechanism = ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_SERVERKEY: if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_server_key, optval_, CURVE_KEYSIZE); mechanism = ZMQ_CURVE; as_server = 0; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85 + 1) { zmq_z85_decode (curve_server_key, (char *) optval_); mechanism = ZMQ_CURVE; as_server = 0; return 0; } else // Deprecated, not symmetrical with zmq_getsockopt if (optvallen_ == CURVE_KEYSIZE_Z85) { char z85_key [41]; memcpy (z85_key, (char *) optval_, CURVE_KEYSIZE_Z85); z85_key [CURVE_KEYSIZE_Z85] = 0; zmq_z85_decode (curve_server_key, z85_key); mechanism = ZMQ_CURVE; as_server = 0; return 0; } break; # endif case ZMQ_CONFLATE: if (is_int && (value == 0 || value == 1)) { conflate = (value != 0); return 0; } break; // If libgssapi isn't installed, these options provoke EINVAL # ifdef HAVE_LIBGSSAPI_KRB5 case ZMQ_GSSAPI_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; mechanism = ZMQ_GSSAPI; return 0; } break; case ZMQ_GSSAPI_PRINCIPAL: if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { gss_principal.assign ((const char *) optval_, optvallen_); mechanism = ZMQ_GSSAPI; return 0; } break; case ZMQ_GSSAPI_SERVICE_PRINCIPAL: if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { gss_service_principal.assign ((const char *) optval_, optvallen_); mechanism = ZMQ_GSSAPI; as_server = 0; return 0; } break; case ZMQ_GSSAPI_PLAINTEXT: if (is_int && (value == 0 || value == 1)) { gss_plaintext = (value != 0); return 0; } break; # endif case ZMQ_HANDSHAKE_IVL: if (is_int && value >= 0) { handshake_ivl = value; return 0; } break; default: #if defined (ZMQ_ACT_MILITANT) // There are valid scenarios for probing with unknown socket option // values, e.g. to check if security is enabled or not. This will not // provoke a militant assert. However, passing bad values to a valid // socket option will, if ZMQ_ACT_MILITANT is defined. malformed = false; #endif break; } #if defined (ZMQ_ACT_MILITANT) // There is no valid use case for passing an error back to the application // when it sent malformed arguments to a socket option. Use ./configure // --with-militant to enable this checking. if (malformed) zmq_assert (false); #endif errno = EINVAL; return -1; }
int zmq::options_t::setsockopt (int option_, const void *optval_, size_t optvallen_) { bool is_int = (optvallen_ == sizeof (int)); int value = is_int? *((int *) optval_): 0; switch (option_) { case ZMQ_SNDHWM: if (is_int && value >= 0) { sndhwm = value; return 0; } break; case ZMQ_RCVHWM: if (is_int && value >= 0) { rcvhwm = value; return 0; } break; case ZMQ_AFFINITY: if (optvallen_ == sizeof (uint64_t)) { affinity = *((uint64_t*) optval_); return 0; } break; case ZMQ_IDENTITY: // Empty identity is invalid as well as identity longer than // 255 bytes. Identity starting with binary zero is invalid // as these are used for auto-generated identities. if (optvallen_ > 0 && optvallen_ < 256 && *((const unsigned char *) optval_) != 0) { identity_size = optvallen_; memcpy (identity, optval_, identity_size); return 0; } break; case ZMQ_RATE: if (is_int && value > 0) { rate = value; return 0; } break; case ZMQ_RECOVERY_IVL: if (is_int && value >= 0) { recovery_ivl = value; return 0; } break; case ZMQ_SNDBUF: if (is_int && value >= 0) { sndbuf = value; return 0; } break; case ZMQ_RCVBUF: if (is_int && value >= 0) { rcvbuf = value; return 0; } break; case ZMQ_TOS: if (is_int && value >= 0) { tos = value; return 0; } break; case ZMQ_LINGER: if (is_int && value >= -1) { linger = value; return 0; } break; case ZMQ_RECONNECT_IVL: if (is_int && value >= -1) { reconnect_ivl = value; return 0; } break; case ZMQ_RECONNECT_IVL_MAX: if (is_int && value >= 0) { reconnect_ivl_max = value; return 0; } break; case ZMQ_BACKLOG: if (is_int && value >= 0) { backlog = value; return 0; } break; case ZMQ_MAXMSGSIZE: if (optvallen_ == sizeof (int64_t)) { maxmsgsize = *((int64_t *) optval_); return 0; } break; case ZMQ_MULTICAST_HOPS: if (is_int && value > 0) { multicast_hops = value; return 0; } break; case ZMQ_RCVTIMEO: if (is_int && value >= -1) { rcvtimeo = value; return 0; } break; case ZMQ_SNDTIMEO: if (is_int && value >= -1) { sndtimeo = value; return 0; } break; /* Deprecated in favor of ZMQ_IPV6 */ case ZMQ_IPV4ONLY: if (is_int && (value == 0 || value == 1)) { ipv6 = (value == 0); return 0; } break; /* To replace the somewhat surprising IPV4ONLY */ case ZMQ_IPV6: if (is_int && (value == 0 || value == 1)) { ipv6 = (value != 0); return 0; } break; case ZMQ_TCP_KEEPALIVE: if (is_int && (value >= -1 || value <= 1)) { tcp_keepalive = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_CNT: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_cnt = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_IDLE: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_idle = value; return 0; } break; case ZMQ_TCP_KEEPALIVE_INTVL: if (is_int && (value == -1 || value >= 0)) { tcp_keepalive_intvl = value; return 0; } break; case ZMQ_IMMEDIATE: if (is_int && (value == 0 || value == 1)) { immediate = value; return 0; } break; case ZMQ_TCP_ACCEPT_FILTER: if (optvallen_ == 0 && optval_ == NULL) { tcp_accept_filters.clear (); return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL && *((const char*) optval_) != 0) { std::string filter_str ((const char *) optval_, optvallen_); tcp_address_mask_t mask; int rc = mask.resolve (filter_str.c_str (), ipv6); if (rc == 0) { tcp_accept_filters.push_back (mask); return 0; } } break; # if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED case ZMQ_ZAP_IPC_CREDS: if (is_int && (value == 0 || value == 1)) { zap_ipc_creds = (value != 0); return 0; } break; case ZMQ_IPC_FILTER_UID: if (optvallen_ == 0 && optval_ == NULL) { ipc_uid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (uid_t) && optval_ != NULL) { ipc_uid_accept_filters.insert (*((uid_t *) optval_)); return 0; } break; case ZMQ_IPC_FILTER_GID: if (optvallen_ == 0 && optval_ == NULL) { ipc_gid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (gid_t) && optval_ != NULL) { ipc_gid_accept_filters.insert (*((gid_t *) optval_)); return 0; } break; # endif # if defined ZMQ_HAVE_SO_PEERCRED case ZMQ_IPC_FILTER_PID: if (optvallen_ == 0 && optval_ == NULL) { ipc_pid_accept_filters.clear (); return 0; } else if (optvallen_ == sizeof (pid_t) && optval_ != NULL) { ipc_pid_accept_filters.insert (*((pid_t *) optval_)); return 0; } break; # endif case ZMQ_PLAIN_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; mechanism = value? ZMQ_PLAIN: ZMQ_NULL; return 0; } break; case ZMQ_PLAIN_USERNAME: if (optvallen_ == 0 && optval_ == NULL) { mechanism = ZMQ_NULL; return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { plain_username.assign ((const char *) optval_, optvallen_); as_server = 0; mechanism = ZMQ_PLAIN; return 0; } break; case ZMQ_PLAIN_PASSWORD: if (optvallen_ == 0 && optval_ == NULL) { mechanism = ZMQ_NULL; return 0; } else if (optvallen_ > 0 && optvallen_ < 256 && optval_ != NULL) { plain_password.assign ((const char *) optval_, optvallen_); as_server = 0; mechanism = ZMQ_PLAIN; return 0; } break; case ZMQ_ZAP_DOMAIN: if (optvallen_ < 256) { zap_domain.assign ((const char *) optval_, optvallen_); return 0; } break; // If libsodium isn't installed, these options provoke EINVAL # ifdef HAVE_LIBSODIUM case ZMQ_CURVE_SERVER: if (is_int && (value == 0 || value == 1)) { as_server = value; mechanism = value? ZMQ_CURVE: ZMQ_NULL; return 0; } break; case ZMQ_CURVE_PUBLICKEY: if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_public_key, optval_, CURVE_KEYSIZE); mechanism = ZMQ_CURVE; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85) { zmq_z85_decode (curve_public_key, (char *) optval_); mechanism = ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_SECRETKEY: if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_secret_key, optval_, CURVE_KEYSIZE); mechanism = ZMQ_CURVE; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85) { zmq_z85_decode (curve_secret_key, (char *) optval_); mechanism = ZMQ_CURVE; return 0; } break; case ZMQ_CURVE_SERVERKEY: if (optvallen_ == CURVE_KEYSIZE) { memcpy (curve_server_key, optval_, CURVE_KEYSIZE); as_server = 0; mechanism = ZMQ_CURVE; return 0; } else if (optvallen_ == CURVE_KEYSIZE_Z85) { zmq_z85_decode (curve_server_key, (char *) optval_); as_server = 0; mechanism = ZMQ_CURVE; return 0; } break; # endif case ZMQ_CONFLATE: if (is_int && (value == 0 || value == 1)) { conflate = (value != 0); return 0; } break; default: break; } errno = EINVAL; return -1; }