1 /*
2 Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 #include "precompiled.hpp"
31
32 #include "macros.hpp"
33 #include "clock.hpp"
34 #include "err.hpp"
35 #include "thread.hpp"
36 #include "atomic_counter.hpp"
37 #include "atomic_ptr.hpp"
38 #include "random.hpp"
39 #include <assert.h>
40 #include <new>
41
42 #if !defined ZMQ_HAVE_WINDOWS
43 #include <unistd.h>
44 #endif
45
46 #if defined(ZMQ_USE_TWEETNACL)
47 #include "tweetnacl.h"
48 #elif defined(ZMQ_USE_LIBSODIUM)
49 #include "sodium.h"
50 #endif
51
zmq_sleep(int seconds_)52 void zmq_sleep (int seconds_)
53 {
54 #if defined ZMQ_HAVE_WINDOWS
55 Sleep (seconds_ * 1000);
56 #else
57 sleep (seconds_);
58 #endif
59 }
60
zmq_stopwatch_start()61 void *zmq_stopwatch_start ()
62 {
63 uint64_t *watch = static_cast<uint64_t *> (malloc (sizeof (uint64_t)));
64 alloc_assert (watch);
65 *watch = zmq::clock_t::now_us ();
66 return static_cast<void *> (watch);
67 }
68
zmq_stopwatch_intermediate(void * watch_)69 unsigned long zmq_stopwatch_intermediate (void *watch_)
70 {
71 const uint64_t end = zmq::clock_t::now_us ();
72 const uint64_t start = *static_cast<uint64_t *> (watch_);
73 return static_cast<unsigned long> (end - start);
74 }
75
zmq_stopwatch_stop(void * watch_)76 unsigned long zmq_stopwatch_stop (void *watch_)
77 {
78 const unsigned long res = zmq_stopwatch_intermediate (watch_);
79 free (watch_);
80 return res;
81 }
82
zmq_threadstart(zmq_thread_fn * func_,void * arg_)83 void *zmq_threadstart (zmq_thread_fn *func_, void *arg_)
84 {
85 zmq::thread_t *thread = new (std::nothrow) zmq::thread_t;
86 alloc_assert (thread);
87 thread->start (func_, arg_, "ZMQapp");
88 return thread;
89 }
90
zmq_threadclose(void * thread_)91 void zmq_threadclose (void *thread_)
92 {
93 zmq::thread_t *p_thread = static_cast<zmq::thread_t *> (thread_);
94 p_thread->stop ();
95 LIBZMQ_DELETE (p_thread);
96 }
97
98 // Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding
99
100 // Maps base 256 to base 85
101 static char encoder[85 + 1] = {"0123456789"
102 "abcdefghij"
103 "klmnopqrst"
104 "uvwxyzABCD"
105 "EFGHIJKLMN"
106 "OPQRSTUVWX"
107 "YZ.-:+=^!/"
108 "*?&<>()[]{"
109 "}@%$#"};
110
111 // Maps base 85 to base 256
112 // We chop off lower 32 and higher 128 ranges
113 // 0xFF denotes invalid characters within this range
114 static uint8_t decoder[96] = {
115 0xFF, 0x44, 0xFF, 0x54, 0x53, 0x52, 0x48, 0xFF, 0x4B, 0x4C, 0x46, 0x41,
116 0xFF, 0x3F, 0x3E, 0x45, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
117 0x08, 0x09, 0x40, 0xFF, 0x49, 0x42, 0x4A, 0x47, 0x51, 0x24, 0x25, 0x26,
118 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
119 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x4D,
120 0xFF, 0x4E, 0x43, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
121 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
122 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x4F, 0xFF, 0x50, 0xFF, 0xFF};
123
124 // --------------------------------------------------------------------------
125 // Encode a binary frame as a string; destination string MUST be at least
126 // size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
127 // dest. Size must be a multiple of 4.
128 // Returns NULL and sets errno = EINVAL for invalid input.
129
zmq_z85_encode(char * dest_,const uint8_t * data_,size_t size_)130 char *zmq_z85_encode (char *dest_, const uint8_t *data_, size_t size_)
131 {
132 if (size_ % 4 != 0) {
133 errno = EINVAL;
134 return NULL;
135 }
136 unsigned int char_nbr = 0;
137 unsigned int byte_nbr = 0;
138 uint32_t value = 0;
139 while (byte_nbr < size_) {
140 // Accumulate value in base 256 (binary)
141 value = value * 256 + data_[byte_nbr++];
142 if (byte_nbr % 4 == 0) {
143 // Output value in base 85
144 unsigned int divisor = 85 * 85 * 85 * 85;
145 while (divisor) {
146 dest_[char_nbr++] = encoder[value / divisor % 85];
147 divisor /= 85;
148 }
149 value = 0;
150 }
151 }
152 assert (char_nbr == size_ * 5 / 4);
153 dest_[char_nbr] = 0;
154 return dest_;
155 }
156
157
158 // --------------------------------------------------------------------------
159 // Decode an encoded string into a binary frame; dest must be at least
160 // strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
161 // must be a multiple of 5.
162 // Returns NULL and sets errno = EINVAL for invalid input.
163
zmq_z85_decode(uint8_t * dest_,const char * string_)164 uint8_t *zmq_z85_decode (uint8_t *dest_, const char *string_)
165 {
166 unsigned int byte_nbr = 0;
167 unsigned int char_nbr = 0;
168 uint32_t value = 0;
169 size_t src_len = strlen (string_);
170
171 if (src_len < 5 || src_len % 5 != 0)
172 goto error_inval;
173
174 while (string_[char_nbr]) {
175 // Accumulate value in base 85
176 if (UINT32_MAX / 85 < value) {
177 // Invalid z85 encoding, represented value exceeds 0xffffffff
178 goto error_inval;
179 }
180 value *= 85;
181 const uint8_t index = string_[char_nbr++] - 32;
182 if (index >= sizeof (decoder)) {
183 // Invalid z85 encoding, character outside range
184 goto error_inval;
185 }
186 const uint32_t summand = decoder[index];
187 if (summand == 0xFF || summand > (UINT32_MAX - value)) {
188 // Invalid z85 encoding, invalid character or represented value exceeds 0xffffffff
189 goto error_inval;
190 }
191 value += summand;
192 if (char_nbr % 5 == 0) {
193 // Output value in base 256
194 unsigned int divisor = 256 * 256 * 256;
195 while (divisor) {
196 dest_[byte_nbr++] = value / divisor % 256;
197 divisor /= 256;
198 }
199 value = 0;
200 }
201 }
202 if (char_nbr % 5 != 0) {
203 goto error_inval;
204 }
205 assert (byte_nbr == strlen (string_) * 4 / 5);
206 return dest_;
207
208 error_inval:
209 errno = EINVAL;
210 return NULL;
211 }
212
213 // --------------------------------------------------------------------------
214 // Generate a public/private keypair with tweetnacl or libsodium.
215 // Generated keys will be 40 byte z85-encoded strings.
216 // Returns 0 on success, -1 on failure, setting errno.
217 // Sets errno = ENOTSUP in the absence of a CURVE library.
218
zmq_curve_keypair(char * z85_public_key_,char * z85_secret_key_)219 int zmq_curve_keypair (char *z85_public_key_, char *z85_secret_key_)
220 {
221 #if defined(ZMQ_HAVE_CURVE)
222 #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32
223 #error "CURVE encryption library not built correctly"
224 #endif
225
226 uint8_t public_key[32];
227 uint8_t secret_key[32];
228
229 zmq::random_open ();
230
231 const int res = crypto_box_keypair (public_key, secret_key);
232 zmq_z85_encode (z85_public_key_, public_key, 32);
233 zmq_z85_encode (z85_secret_key_, secret_key, 32);
234
235 zmq::random_close ();
236
237 return res;
238 #else
239 (void) z85_public_key_, (void) z85_secret_key_;
240 errno = ENOTSUP;
241 return -1;
242 #endif
243 }
244
245 // --------------------------------------------------------------------------
246 // Derive the public key from a private key using tweetnacl or libsodium.
247 // Derived key will be 40 byte z85-encoded string.
248 // Returns 0 on success, -1 on failure, setting errno.
249 // Sets errno = ENOTSUP in the absence of a CURVE library.
250
zmq_curve_public(char * z85_public_key_,const char * z85_secret_key_)251 int zmq_curve_public (char *z85_public_key_, const char *z85_secret_key_)
252 {
253 #if defined(ZMQ_HAVE_CURVE)
254 #if crypto_box_PUBLICKEYBYTES != 32 || crypto_box_SECRETKEYBYTES != 32
255 #error "CURVE encryption library not built correctly"
256 #endif
257
258 uint8_t public_key[32];
259 uint8_t secret_key[32];
260
261 zmq::random_open ();
262
263 if (zmq_z85_decode (secret_key, z85_secret_key_) == NULL)
264 return -1;
265
266 // Return codes are suppressed as none of these can actually fail.
267 crypto_scalarmult_base (public_key, secret_key);
268 zmq_z85_encode (z85_public_key_, public_key, 32);
269
270 zmq::random_close ();
271
272 return 0;
273 #else
274 (void) z85_public_key_, (void) z85_secret_key_;
275 errno = ENOTSUP;
276 return -1;
277 #endif
278 }
279
280
281 // --------------------------------------------------------------------------
282 // Initialize a new atomic counter, which is set to zero
283
zmq_atomic_counter_new(void)284 void *zmq_atomic_counter_new (void)
285 {
286 zmq::atomic_counter_t *counter = new (std::nothrow) zmq::atomic_counter_t;
287 alloc_assert (counter);
288 return counter;
289 }
290
291 // Se the value of the atomic counter
292
zmq_atomic_counter_set(void * counter_,int value_)293 void zmq_atomic_counter_set (void *counter_, int value_)
294 {
295 (static_cast<zmq::atomic_counter_t *> (counter_))->set (value_);
296 }
297
298 // Increment the atomic counter, and return the old value
299
zmq_atomic_counter_inc(void * counter_)300 int zmq_atomic_counter_inc (void *counter_)
301 {
302 return (static_cast<zmq::atomic_counter_t *> (counter_))->add (1);
303 }
304
305 // Decrement the atomic counter and return 1 (if counter >= 1), or
306 // 0 if counter hit zero.
307
zmq_atomic_counter_dec(void * counter_)308 int zmq_atomic_counter_dec (void *counter_)
309 {
310 return (static_cast<zmq::atomic_counter_t *> (counter_))->sub (1) ? 1 : 0;
311 }
312
313 // Return actual value of atomic counter
314
zmq_atomic_counter_value(void * counter_)315 int zmq_atomic_counter_value (void *counter_)
316 {
317 return (static_cast<zmq::atomic_counter_t *> (counter_))->get ();
318 }
319
320 // Destroy atomic counter, and set reference to NULL
321
zmq_atomic_counter_destroy(void ** counter_p_)322 void zmq_atomic_counter_destroy (void **counter_p_)
323 {
324 delete (static_cast<zmq::atomic_counter_t *> (*counter_p_));
325 *counter_p_ = NULL;
326 }
327