]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - ports/winnt/libntp/arc4wrap.c
Vendor import ntp 4.2.8p2
[FreeBSD/FreeBSD.git] / ports / winnt / libntp / arc4wrap.c
1 /*
2  * arc4wrap.c - wrapper for libevent's ARCFOUR random number generator
3  *
4  * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
5  * The contents of 'html/copyright.html' apply.
6  * --------------------------------------------------------------------
7  * This is an inclusion wrapper for the ARCFOUR implementation in
8  * libevent. It's main usage is to enable a openSSL-free build on Win32
9  * without a full integration of libevent. This provides Win32 specific
10  * glue to make the PRNG working. Porting to POSIX should be easy, but
11  * on most POSIX systems using openSSL is no problem and falling back to
12  * using ARCFOUR instead of the openSSL PRNG is not necessary. And even
13  * if it is, there's a good chance that ARCFOUR is a system library.
14  */
15 #include <config.h>
16 #ifdef _WIN32
17 # include <wincrypt.h>
18 # include <process.h>
19 #else
20 # error this is currently a pure windows port
21 #endif
22
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "ntp_types.h"
27 #include "ntp_stdlib.h"
28
29 /* ARCFOUR implementation glue */
30 /* export type is empty, since this goes into a static library*/
31 #define ARC4RANDOM_EXPORT
32 /* we use default uint32_t as UINT32 */
33 #define ARC4RANDOM_UINT32 uint32_t
34 /* do not use ARCFOUR's default includes - we gobble it all up here. */
35 #define ARC4RANDOM_NO_INCLUDES
36 /* And the locking. Could probably be left empty. */
37 #define ARC4_LOCK_() private_lock_()
38 #define ARC4_UNLOCK_() private_unlock_()
39
40 /* support code */
41
42 static void
43 evutil_memclear_(
44         void  *buf,
45         size_t len)
46 {
47         memset(buf, 0, len);
48 }
49
50 /* locking uses a manual thread-safe ONCE pattern. There's no static
51  * initialiser pattern that can be used for critical sections, and
52  * we must make sure we do the creation exactly once on the first call.
53  */
54
55 static long             once_ = 0;
56 static CRITICAL_SECTION csec_;
57
58 static void
59 private_lock_(void)
60 {
61 again:
62         switch (InterlockedCompareExchange(&once_, 1, 0)) {
63         case 0:
64                 InitializeCriticalSection(&csec_);
65                 InterlockedExchange(&once_, 2);
66         case 2:
67                 EnterCriticalSection(&csec_);
68                 break;
69
70         default:
71                 YieldProcessor();
72                 goto again;
73         }
74 }
75
76 static void
77 private_unlock_(void)
78 {
79         if (InterlockedExchangeAdd(&once_, 0) == 2)
80                 LeaveCriticalSection(&csec_);
81 }
82
83 #pragma warning(disable : 4244)
84 #include "../../../sntp/libevent/arc4random.c"