1 |
werner |
36 |
/* wptSecmem.cpp - W32 ``Secure`` memory handling |
2 |
|
|
* Copyright (C) 2001, 2002 Timo Schulz <[email protected]> |
3 |
|
|
* |
4 |
|
|
* This file is part of WinPT. |
5 |
|
|
* |
6 |
|
|
* WinPT is free software; you can redistribute it and/or |
7 |
|
|
* modify it under the terms of the GNU General Public License |
8 |
|
|
* as published by the Free Software Foundation; either version 2 |
9 |
|
|
* of the License, or (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* WinPT is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 |
|
|
* General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with WinPT; if not, write to the Free Software Foundation, |
18 |
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
|
|
* |
20 |
|
|
* This is the notice from the original author: |
21 |
|
|
* |
22 |
|
|
* win32vmSafe - a 'no write to disk' volatile buffer |
23 |
|
|
* implemented via standard win32 api calls. |
24 |
|
|
* |
25 |
|
|
* Copyright (C) 2001 John J. Kane <[email protected]> |
26 |
|
|
* Brief notice: This code is released under the terms of |
27 |
|
|
* the GNU Lesser General Public License (LGPL) Version 2.1; |
28 |
|
|
* refer to www.gnu.org if you're clueless. |
29 |
|
|
* |
30 |
|
|
* WARNING: |
31 |
|
|
* This is win32vmSafe ALPHA v0.2.1. No security analysis has |
32 |
|
|
* been done on this version; do not use in production code. |
33 |
|
|
* It demonstrates basic functionality only. |
34 |
|
|
* This version should be considered deprecated after 2001-09-01. |
35 |
|
|
* Contact John Kane for information on the current status |
36 |
|
|
* of this package. |
37 |
|
|
* |
38 |
|
|
* Heavily modified for the use with WinPT by Timo Schulz. |
39 |
|
|
*/ |
40 |
|
|
|
41 |
|
|
#if 0 |
42 |
|
|
#ifdef HAVE_CONFIG_H |
43 |
|
|
#include <config.h> |
44 |
twoaday |
2 |
#endif |
45 |
werner |
36 |
|
46 |
|
|
#include <windows.h> |
47 |
|
|
|
48 |
|
|
/* CONTEXT: |
49 |
|
|
Under Windows, a user process cannot lock pages in memory. |
50 |
|
|
Normally, critical data will be flushed to the system VMM swap |
51 |
|
|
file at unpredictable intervals. Only a kernel-level VXD/DLL |
52 |
|
|
can lock physical pages, and we do not have a GPL page-locker. |
53 |
|
|
*HOWEVER: |
54 |
|
|
Please note the following distinction: |
55 |
|
|
(1) A page can be locked IN memory to guarantee that it is |
56 |
|
|
always accessible and never triggers a page fault. |
57 |
|
|
(2) A page can be protected to ensure that its contents |
58 |
|
|
are never copied OUT of memory into permanent storage. |
59 |
|
|
It turns out that there is a way to implement (2) without |
60 |
|
|
the work required to ensure (1). Win32 memory-mapped files |
61 |
|
|
allow you to map the first N bytes of any file into a page. |
62 |
|
|
The remaining 4096-N bytes of that page become a VOLATILE |
63 |
|
|
BUFFER area which is not written back to the mapped file even |
64 |
|
|
if the process is swapped out. The data is DISCARDED without |
65 |
|
|
being written; when the process is swapped back in, the former |
66 |
|
|
contents of the unmapped area are not preserved. |
67 |
|
|
A 'magic number', sentinel, or any other integrity check |
68 |
|
|
scheme can be used to detect the loss of the contents of |
69 |
|
|
the volatile buffer. |
70 |
|
|
The application can respond by aborting the interrupted |
71 |
|
|
action with an error message, or by retrying. |
72 |
|
|
*SUMMARY: |
73 |
|
|
This approach DOES satisfy a security constraint of not |
74 |
|
|
allowing critical key data to be written to disk. It does |
75 |
|
|
not attempt to prevent the process from being swapped, and |
76 |
|
|
does not preserve the volatile buffer across swap-outs. |
77 |
|
|
This behavior (although safe) is non-intuitive; it may be |
78 |
|
|
best to make it a non-default option if implemented. |
79 |
|
|
*COMPLEXITY IMPLICATIONS FOR NON-WINDOWS PORTS: |
80 |
|
|
None. |
81 |
|
|
*COMPLEXITY IMPLICATIONS FOR WINDOWS PORTS: |
82 |
|
|
The code footprint is small. No VXD; it's compiled |
83 |
|
|
right into the main executable. No end-user installation |
84 |
|
|
step. Data in excess of 4k requires multiple buffers. |
85 |
|
|
May allow the elimination of certain previously-implemented |
86 |
|
|
win32 security workarounds. The parent routine must detect |
87 |
|
|
and handle the (rare) loss-of-data event. |
88 |
|
|
*PORTABILITY: |
89 |
|
|
There are reasons why this method is likely to be portable |
90 |
|
|
across all flavors of win32 systems, even in environments |
91 |
|
|
where the user lacks NT Administrator rights. It relies |
92 |
|
|
only on core win32 primitives which are supported on |
93 |
|
|
everything since Win95 (possibly Win3.1). |
94 |
|
|
*/ |
95 |
|
|
|
96 |
|
|
struct secmem_s { |
97 |
|
|
HANDLE fh; |
98 |
|
|
HANDLE mh; |
99 |
|
|
char *ptr; |
100 |
|
|
int mapsize; |
101 |
|
|
}; |
102 |
|
|
|
103 |
|
|
static secmem_s mem; |
104 |
|
|
static char fname[128]; |
105 |
|
|
static int fname_set = 0; |
106 |
|
|
|
107 |
|
|
int |
108 |
|
|
vm_safe_init(int mapsize) |
109 |
|
|
{ |
110 |
|
|
if ( !fname_set ) |
111 |
|
|
return 1; |
112 |
|
|
|
113 |
|
|
mem.fh = CreateFile( |
114 |
|
|
fname, |
115 |
|
|
GENERIC_READ | GENERIC_WRITE, |
116 |
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, |
117 |
|
|
NULL, |
118 |
|
|
OPEN_ALWAYS, |
119 |
|
|
FILE_ATTRIBUTE_TEMPORARY, |
120 |
|
|
NULL ); |
121 |
|
|
if ( mem.fh == INVALID_HANDLE_VALUE ) |
122 |
|
|
return 1; |
123 |
|
|
|
124 |
|
|
mem.mh = CreateFileMapping( mem.fh, NULL, PAGE_READWRITE, 0, mapsize, |
125 |
|
|
NULL ); |
126 |
|
|
mem.ptr = (char *)MapViewOfFile( mem.mh, FILE_MAP_READ | FILE_MAP_WRITE, |
127 |
|
|
0, 0, 0 ); |
128 |
|
|
if ( mem.ptr == NULL ) { |
129 |
|
|
CloseHandle( mem.fh ); |
130 |
|
|
CloseHandle( mem.mh ); |
131 |
|
|
return 1; |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
VirtualLock( mem.ptr, mapsize ); |
135 |
|
|
mem.mapsize = mapsize; |
136 |
|
|
|
137 |
|
|
return 0; |
138 |
|
|
} /* vm_safe_init */ |
139 |
|
|
|
140 |
|
|
int |
141 |
|
|
vm_safe_init_noswap(void) |
142 |
|
|
{ |
143 |
|
|
int rc; |
144 |
|
|
|
145 |
|
|
rc = vm_safe_init( 512 ); |
146 |
|
|
if ( rc ) |
147 |
|
|
return 1; |
148 |
|
|
mem.ptr += 512; |
149 |
|
|
return 0; |
150 |
|
|
} /* vm_safe_init_noswap */ |
151 |
|
|
|
152 |
|
|
void |
153 |
|
|
vm_safe_free( void ) |
154 |
|
|
{ |
155 |
|
|
memset( mem.ptr, 0, mem.mapsize ); |
156 |
|
|
mem.ptr = NULL; |
157 |
|
|
mem.mapsize = 0; |
158 |
|
|
|
159 |
|
|
CloseHandle( mem.mh ); |
160 |
|
|
mem.mh = NULL; |
161 |
|
|
CloseHandle( mem.fh ); |
162 |
|
|
mem.fh = INVALID_HANDLE_VALUE; |
163 |
|
|
} /* vm_safe_init */ |
164 |
|
|
|
165 |
|
|
void* |
166 |
|
|
vm_safe_get( void ) |
167 |
|
|
{ |
168 |
|
|
return mem.ptr; |
169 |
|
|
} /* vm_safe_get */ |
170 |
|
|
|
171 |
|
|
void |
172 |
|
|
vm_safe_set_swapfile( const char *swapname ) |
173 |
|
|
{ |
174 |
|
|
if ( swapname ) { |
175 |
|
|
strcpy( fname, swapname ); |
176 |
|
|
fname_set = 1; |
177 |
|
|
} |
178 |
|
|
} /* vm_safe_set_swapfile */ |
179 |
|
|
|
180 |
|
|
int |
181 |
|
|
vm_safe_create_swapfile( const char *swapname, int size ) |
182 |
|
|
{ |
183 |
|
|
HANDLE fd; |
184 |
|
|
char *buf = NULL; |
185 |
|
|
DWORD nwritten; |
186 |
|
|
|
187 |
|
|
if ( !size ) |
188 |
|
|
return 1; |
189 |
|
|
|
190 |
|
|
fd = CreateFile( swapname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, |
191 |
|
|
CREATE_ALWAYS, 0, NULL ); |
192 |
|
|
if ( fd == INVALID_HANDLE_VALUE ) |
193 |
|
|
return 1; |
194 |
|
|
|
195 |
|
|
buf = new char[size+1]; |
196 |
|
|
if( !buf ) |
197 |
|
|
BUG( NULL ); |
198 |
|
|
memset( buf, 0, size ); |
199 |
|
|
WriteFile( fd, buf, size, &nwritten, NULL ); |
200 |
|
|
|
201 |
|
|
CloseHandle( fd ); |
202 |
|
|
free_if_alloc( buf ); |
203 |
|
|
return 0; |
204 |
|
|
} /* vm_safe_create_swapfile */ |
205 |
|
|
#endif |