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