forked from UNOMP/node-multi-hashing
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsecure_memzero.h
194 lines (163 loc) · 6.16 KB
/
secure_memzero.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// secure_memzero.h version 1 (October 29, 2016)
//
// This code is released into the public domain.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// The secure_memzero macro/function attempts to ensure that an optimizing
// compiler does not remove the intended operation if cleared memory is not
// accessed again by the program. There are several known ways of doing this,
// however no single one is both universally available and absolutely guranteed
// by the standard. The following code defines secure_memzero as a macro or
// function using one of the known alternatives. The choice of implementation
// can be controlled by defining a preprocessor macro of the form SMZ_impl,
// where <impl> is one of the defined implementation names. SMZ_impl should
// expand to an integer indicating the dgeree of preference for the
// implementation, where numerically higher values indicate greater preference.
// Defining SMZ_impl to be 0 disables the implementation even if it is
// available. Not defining any SMZ_impl will result in default (safe) behavior.
//
// The following implementations may be used.
//
// SMZ_SECUREZEROMEMORY
// Uses the SecureZeroMemory macro/function on Windows. Requires a Windows
// environment (_WIN32 must be defined).
//
// SMZ_ASM_BARRIER
// Uses a compiler memory barrier to force the results of a memset to be
// committed to memory. Has been tested to work on:
// - Clang 3.9.0 at all optimization levels.
// - GCC 6.2 at all optimization levels.
//
// SMZ_MEMSET_S
// Uses the C11 function memset_s. Currently not available on many platforms.
// Note that if you want this option, you have to set __STDC_WANT_LIB_EXT1__
// to 1 before including string.h or any file that includes string.h in a
// compilation unit that includes this header.
//
// SMZ_VDATAPTR
// Uses the volatile data pointer technique to zero one byte at a time. This is
// not guaranteed to work by the C standard, which does not require access to
// non-volatile objects via a pointer-to-volatile to be treated as a volatile
// access. However, it is known to work on the following compilers:
// - Clang 3.9.0 at all optimization levels.
// - GCC 6.2 at all optimization levels.
//
// SMZ_VFUNCPTR
// Uses the volatile function pointer technique to call memset. This is not
// guaranteed to work by the C standard, which does not require the pointed-to
// function to be called. However, it is known to work on the following
// compilers:
// - Clang 3.9.0 at all optimization levels.
// - GCC 6.2 at all optimization levels.
// The remainder of this file implements the selection logic using the
// specified compile-time preferences.
#ifndef _SECURE_MEMZERO_H_
#define _SECURE_MEMZERO_H_
// STEP 1. Set default preference for all implementations to 1.
#ifndef SMZ_SECUREZEROMEMORY
#define SMZ_SECUREZEROMEMORY 1
#endif
#ifndef SMZ_MEMSET_S
#define SMZ_MEMSET_S 1
#endif
#ifndef SMZ_ASM_BARRIER
#define SMZ_ASM_BARRIER 1
#endif
#ifndef SMZ_VDATAPTR
#define SMZ_VDATAPTR 1
#endif
#ifndef SMZ_VFUNCPTR
#define SMZ_VFUNCPTR 1
#endif
// STEP 2. Check which implementations are available and include any necessary
// header files.
#if SMZ_SECUREZEROMEMORY > 0
#ifdef _WIN32
#include <windows.h>
#else
#undef SMZ_SECUREZEROMEMORY
#define SMZ_SECUREZEROMEMORY 0
#endif
#endif
#if SMZ_MEMSET_S > 0
#if defined(__STDC_WANT_LIB_EXT1__) && (__STDC_WANT_LIB_EXT1__ != 1)
#undef SMZ_MEMSET_S
#define SMZ_MEMSET_S 0
#endif
#if SMZ_MEMSET_S > 0
#ifndef __STDC_WANT_LIB_EXT1__
// Must come before first include of string.h
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#include <string.h>
#ifndef __STDC_LIB_EXT1__
#undef SMZ_MEMSET_S
#define SMZ_MEMSET_S 0
#endif
#endif
#endif
#if !defined(__GNUC__) && !defined(__clang__)
#undef SMZ_ASM_BARRIER
#define SMZ_ASM_BARRIER 0
#endif
#if SMZ_VFUNCPTR > 0
#include <string.h>
#endif
// STEP 3. Calculate highest preference.
#define SMZ_PREFERENCE 0
#if SMZ_PREFERENCE < SMZ_SECUREZEROMEMORY
#undef SMZ_PREFERENCE
#define SMZ_PREFERENCE SMZ_SECUREZEROMEMORY
#endif
#if SMZ_PREFERENCE < SMZ_MEMSET_S
#undef SMZ_PREFERENCE
#define SMZ_PREFERENCE SMZ_MEMSET_S
#endif
#if SMZ_PREFERENCE < SMZ_ASM_BARRIER
#undef SMZ_PREFERENCE
#define SMZ_PREFERENCE SMZ_ASM_BARRIER
#endif
#if SMZ_PREFERENCE < SMZ_VDATAPTR
#undef SMZ_PREFERENCE
#define SMZ_PREFERENCE SMZ_VDATAPTR
#endif
#if SMZ_PREFERENCE < SMZ_VFUNCPTR
#undef SMZ_PREFERENCE
#define SMZ_PREFERENCE SMZ_VFUNCPTR
#endif
// STEP 4. Make sure we have something chosen.
#if SMZ_PREFERENCE <= 0
#error No secure_memzero implementation available
#endif
// STEP 5. Use implementation with highest preference. Ties are broken in
// favor of implementations appearing first, below.
#if SMZ_PREFERENCE == SMZ_SECUREZEROMEMORY
#define secure_memzero(ptr,len) SecureZeroMemory((ptr),(len))
#elif SMZ_PREFERENCE == SMZ_MEMSET_S
#define secure_memzero(ptr,len) memset_s((ptr),(len),0,(len))
#elif SMZ_PREFERENCE == SMZ_ASM_BARRIER
#define secure_memzero(ptr,len) do { \
memset((ptr),0,(len)); \
__asm__ __volatile__("" ::"r"(ptr): "memory"); \
} while (0)
#elif SMZ_PREFERENCE == SMZ_VDATAPTR
static void secure_memzero(void * ptr, size_t len) {
volatile char * p = ptr;
while (len--) *p++ = 0;
}
#elif SMZ_PREFERENCE == SMZ_VFUNCPTR
static void * (* volatile _smz_memset_fptr)(void*,int,size_t) = &memset;
static void secure_memzero(void * ptr, size_t len) {
_smz_memset_fptr(ptr, 0, len);
}
#endif
#endif // _SECURE_MEMZERO_H_