| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 | 
							- /*
 
-  * winmiscs.c: Windows-specific standalone functions. Has the same
 
-  * relationship to winmisc.c that utils.c does to misc.c, but the
 
-  * corresponding name 'winutils.c' was already taken.
 
-  */
 
- #include "putty.h"
 
- #ifndef NO_SECUREZEROMEMORY
 
- /*
 
-  * Windows implementation of smemclr (see misc.c) using SecureZeroMemory.
 
-  */
 
- void smemclr(void *b, size_t n) {
 
-     if (b && n > 0)
 
-         SecureZeroMemory(b, n);
 
- }
 
- #endif
 
- #ifdef MINEFIELD
 
- /*
 
-  * Minefield - a Windows equivalent for Electric Fence
 
-  */
 
- #define PAGESIZE 4096
 
- /*
 
-  * Design:
 
-  * 
 
-  * We start by reserving as much virtual address space as Windows
 
-  * will sensibly (or not sensibly) let us have. We flag it all as
 
-  * invalid memory.
 
-  * 
 
-  * Any allocation attempt is satisfied by committing one or more
 
-  * pages, with an uncommitted page on either side. The returned
 
-  * memory region is jammed up against the _end_ of the pages.
 
-  * 
 
-  * Freeing anything causes instantaneous decommitment of the pages
 
-  * involved, so stale pointers are caught as soon as possible.
 
-  */
 
- static int minefield_initialised = 0;
 
- static void *minefield_region = NULL;
 
- static long minefield_size = 0;
 
- static long minefield_npages = 0;
 
- static long minefield_curpos = 0;
 
- static unsigned short *minefield_admin = NULL;
 
- static void *minefield_pages = NULL;
 
- static void minefield_admin_hide(int hide)
 
- {
 
-     int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
 
-     VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
 
- }
 
- static void minefield_init(void)
 
- {
 
-     int size;
 
-     int admin_size;
 
-     int i;
 
-     for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
 
- 	minefield_region = VirtualAlloc(NULL, size,
 
- 					MEM_RESERVE, PAGE_NOACCESS);
 
- 	if (minefield_region)
 
- 	    break;
 
-     }
 
-     minefield_size = size;
 
-     /*
 
-      * Firstly, allocate a section of that to be the admin block.
 
-      * We'll need a two-byte field for each page.
 
-      */
 
-     minefield_admin = minefield_region;
 
-     minefield_npages = minefield_size / PAGESIZE;
 
-     admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
 
-     minefield_npages = (minefield_size - admin_size) / PAGESIZE;
 
-     minefield_pages = (char *) minefield_region + admin_size;
 
-     /*
 
-      * Commit the admin region.
 
-      */
 
-     VirtualAlloc(minefield_admin, minefield_npages * 2,
 
- 		 MEM_COMMIT, PAGE_READWRITE);
 
-     /*
 
-      * Mark all pages as unused (0xFFFF).
 
-      */
 
-     for (i = 0; i < minefield_npages; i++)
 
- 	minefield_admin[i] = 0xFFFF;
 
-     /*
 
-      * Hide the admin region.
 
-      */
 
-     minefield_admin_hide(1);
 
-     minefield_initialised = 1;
 
- }
 
- static void minefield_bomb(void)
 
- {
 
-     div(1, *(int *) minefield_pages);
 
- }
 
- static void *minefield_alloc(int size)
 
- {
 
-     int npages;
 
-     int pos, lim, region_end, region_start;
 
-     int start;
 
-     int i;
 
-     npages = (size + PAGESIZE - 1) / PAGESIZE;
 
-     minefield_admin_hide(0);
 
-     /*
 
-      * Search from current position until we find a contiguous
 
-      * bunch of npages+2 unused pages.
 
-      */
 
-     pos = minefield_curpos;
 
-     lim = minefield_npages;
 
-     while (1) {
 
- 	/* Skip over used pages. */
 
- 	while (pos < lim && minefield_admin[pos] != 0xFFFF)
 
- 	    pos++;
 
- 	/* Count unused pages. */
 
- 	start = pos;
 
- 	while (pos < lim && pos - start < npages + 2 &&
 
- 	       minefield_admin[pos] == 0xFFFF)
 
- 	    pos++;
 
- 	if (pos - start == npages + 2)
 
- 	    break;
 
- 	/* If we've reached the limit, reset the limit or stop. */
 
- 	if (pos >= lim) {
 
- 	    if (lim == minefield_npages) {
 
- 		/* go round and start again at zero */
 
- 		lim = minefield_curpos;
 
- 		pos = 0;
 
- 	    } else {
 
- 		minefield_admin_hide(1);
 
- 		return NULL;
 
- 	    }
 
- 	}
 
-     }
 
-     minefield_curpos = pos - 1;
 
-     /*
 
-      * We have npages+2 unused pages starting at start. We leave
 
-      * the first and last of these alone and use the rest.
 
-      */
 
-     region_end = (start + npages + 1) * PAGESIZE;
 
-     region_start = region_end - size;
 
-     /* FIXME: could align here if we wanted */
 
-     /*
 
-      * Update the admin region.
 
-      */
 
-     for (i = start + 2; i < start + npages + 1; i++)
 
- 	minefield_admin[i] = 0xFFFE;   /* used but no region starts here */
 
-     minefield_admin[start + 1] = region_start % PAGESIZE;
 
-     minefield_admin_hide(1);
 
-     VirtualAlloc((char *) minefield_pages + region_start, size,
 
- 		 MEM_COMMIT, PAGE_READWRITE);
 
-     return (char *) minefield_pages + region_start;
 
- }
 
- static void minefield_free(void *ptr)
 
- {
 
-     int region_start, i, j;
 
-     minefield_admin_hide(0);
 
-     region_start = (char *) ptr - (char *) minefield_pages;
 
-     i = region_start / PAGESIZE;
 
-     if (i < 0 || i >= minefield_npages ||
 
- 	minefield_admin[i] != region_start % PAGESIZE)
 
- 	minefield_bomb();
 
-     for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
 
- 	minefield_admin[j] = 0xFFFF;
 
-     }
 
-     VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
 
-     minefield_admin_hide(1);
 
- }
 
- static int minefield_get_size(void *ptr)
 
- {
 
-     int region_start, i, j;
 
-     minefield_admin_hide(0);
 
-     region_start = (char *) ptr - (char *) minefield_pages;
 
-     i = region_start / PAGESIZE;
 
-     if (i < 0 || i >= minefield_npages ||
 
- 	minefield_admin[i] != region_start % PAGESIZE)
 
- 	minefield_bomb();
 
-     for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
 
-     minefield_admin_hide(1);
 
-     return j * PAGESIZE - region_start;
 
- }
 
- void *minefield_c_malloc(size_t size)
 
- {
 
-     if (!minefield_initialised)
 
- 	minefield_init();
 
-     return minefield_alloc(size);
 
- }
 
- void minefield_c_free(void *p)
 
- {
 
-     if (!minefield_initialised)
 
- 	minefield_init();
 
-     minefield_free(p);
 
- }
 
- /*
 
-  * realloc _always_ moves the chunk, for rapid detection of code
 
-  * that assumes it won't.
 
-  */
 
- void *minefield_c_realloc(void *p, size_t size)
 
- {
 
-     size_t oldsize;
 
-     void *q;
 
-     if (!minefield_initialised)
 
- 	minefield_init();
 
-     q = minefield_alloc(size);
 
-     oldsize = minefield_get_size(p);
 
-     memcpy(q, p, (oldsize < size ? oldsize : size));
 
-     minefield_free(p);
 
-     return q;
 
- }
 
- #endif				/* MINEFIELD */
 
- #if defined _MSC_VER && _MSC_VER < 1800
 
- /*
 
-  * Work around lack of strtoumax in older MSVC libraries
 
-  */
 
- uintmax_t strtoumax(const char *nptr, char **endptr, int base)
 
- {
 
-     return _strtoui64(nptr, endptr, base);
 
- }
 
- #endif
 
- #if defined _M_ARM || defined _M_ARM64
 
- bool platform_aes_hw_available(void)
 
- {
 
-     return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
 
- }
 
- bool platform_sha256_hw_available(void)
 
- {
 
-     return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
 
- }
 
- bool platform_sha1_hw_available(void)
 
- {
 
-     return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
 
- }
 
- #endif
 
 
  |