aboutsummaryrefslogtreecommitdiffstats
path: root/src/pinentry/secmem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pinentry/secmem.cpp')
-rw-r--r--src/pinentry/secmem.cpp375
1 files changed, 0 insertions, 375 deletions
diff --git a/src/pinentry/secmem.cpp b/src/pinentry/secmem.cpp
deleted file mode 100644
index cb4eeb4f..00000000
--- a/src/pinentry/secmem.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/* secmem.c - memory allocation from a secure heap
- * Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
- * Copyright (C) 2015 g10 Code GmbH
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <https://www.gnu.org/licenses/>.
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WINDOWS
-#include <errno.h>
-#endif
-#include <stdarg.h>
-#include <unistd.h>
-#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#endif
-#include <string.h>
-
-#include "secmem.h"
-
-#ifdef ORIGINAL_GPG_VERSION
-#include "types.h"
-#include "util.h"
-#else /* ORIGINAL_GPG_VERSION */
-
-#include "secmem_util.h"
-
-typedef union {
- int a;
- short b;
- char c[1];
- long d;
-#ifdef HAVE_U64_TYPE
- u64 e;
-#endif
- float f;
- double g;
-} PROPERLY_ALIGNED_TYPE;
-
-#define log_error log_info
-#define log_bug log_fatal
-
-void log_info(char *template_, ...) {
- va_list args;
-
- va_start(args, template_);
- vfprintf(stderr, template_, args);
- va_end(args);
-}
-
-void log_fatal(char *template_, ...) {
- va_list args;
-
- va_start(args, template_);
- vfprintf(stderr, template_, args);
- va_end(args);
- exit(EXIT_FAILURE);
-}
-
-#endif /* ORIGINAL_GPG_VERSION */
-
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-#define DEFAULT_POOLSIZE 16384
-
-typedef struct memblock_struct MEMBLOCK;
-struct memblock_struct {
- unsigned size;
- union {
- MEMBLOCK *next;
- PROPERLY_ALIGNED_TYPE aligned;
- } u;
-};
-
-static void *pool;
-static volatile int pool_okay; /* may be checked in an atexit function */
-#if HAVE_MMAP
-static int pool_is_mmapped;
-#endif
-static size_t poolsize; /* allocated length */
-static size_t poollen; /* used length */
-static MEMBLOCK *unused_blocks;
-static unsigned max_alloced;
-static unsigned cur_alloced;
-static unsigned max_blocks;
-static unsigned cur_blocks;
-static int disable_secmem;
-static int show_warning;
-static int no_warning;
-static int suspend_warning;
-
-static void print_warn(void) {
- if (!no_warning) log_info("Warning: using insecure memory!\n");
-}
-
-static void lock_pool(void *p, size_t n) {
-#if defined(HAVE_MLOCK)
- uid_t uid;
- int err;
-
- uid = getuid();
-
-#ifdef HAVE_BROKEN_MLOCK
- if (uid) {
- errno = EPERM;
- err = -1;
- } else {
- err = mlock(p, n);
- }
-#else
- err = mlock(p, n);
-#endif
-
- if (uid && !geteuid()) {
- if (setuid(uid) || getuid() != geteuid())
- log_fatal("failed to reset uid: %s\n", strerror(errno));
- }
-
- if (err) {
- if (errno != EPERM
-#ifdef EAGAIN /* OpenBSD returns this */
- && errno != EAGAIN
-#endif
- )
- log_error("can't lock memory: %s\n", strerror(errno));
- show_warning = 1;
- }
-
-#else
- (void)p;
- (void)n;
- log_info("Please note that you don't have secure memory on this system\n");
-#endif
-}
-
-static void init_pool(size_t n) {
-#if HAVE_MMAP
- size_t pgsize;
-#endif
-
- poolsize = n;
-
- if (disable_secmem) log_bug("secure memory is disabled");
-
-#if HAVE_MMAP
-#ifdef HAVE_GETPAGESIZE
- pgsize = getpagesize();
-#else
- pgsize = 4096;
-#endif
-
- poolsize = (poolsize + pgsize - 1) & ~(pgsize - 1);
-#ifdef MAP_ANONYMOUS
- pool = mmap(0, poolsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
-#else /* map /dev/zero instead */
- {
- int fd;
-
- fd = open("/dev/zero", O_RDWR);
- if (fd == -1) {
- log_error("can't open /dev/zero: %s\n", strerror(errno));
- pool = (void *)-1;
- } else {
- pool = mmap(0, poolsize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- close(fd);
- }
- }
-#endif
- if (pool == (void *)-1)
- log_info("can't mmap pool of %u bytes: %s - using malloc\n",
- (unsigned)poolsize, strerror(errno));
- else {
- pool_is_mmapped = 1;
- pool_okay = 1;
- }
-
-#endif
- if (!pool_okay) {
- pool = malloc(poolsize);
- if (!pool)
- log_fatal("can't allocate memory pool of %u bytes\n", (unsigned)poolsize);
- else
- pool_okay = 1;
- }
- lock_pool(pool, poolsize);
- poollen = 0;
-}
-
-/* concatenate unused blocks */
-static void compress_pool(void) { /* fixme: we really should do this */
-}
-
-void secmem_set_flags(unsigned flags) {
- int was_susp = suspend_warning;
-
- no_warning = flags & 1;
- suspend_warning = flags & 2;
-
- /* and now issue the warning if it is not longer suspended */
- if (was_susp && !suspend_warning && show_warning) {
- show_warning = 0;
- print_warn();
- }
-}
-
-unsigned secmem_get_flags(void) {
- unsigned flags;
-
- flags = no_warning ? 1 : 0;
- flags |= suspend_warning ? 2 : 0;
- return flags;
-}
-
-void secmem_init(size_t n) {
- if (!n) {
-#if !defined(HAVE_DOSISH_SYSTEM)
- uid_t uid;
-
- disable_secmem = 1;
- uid = getuid();
- if (uid != geteuid()) {
- if (setuid(uid) || getuid() != geteuid())
- log_fatal("failed to drop setuid\n");
- }
-#endif
- } else {
- if (n < DEFAULT_POOLSIZE) n = DEFAULT_POOLSIZE;
- if (!pool_okay)
- init_pool(n);
- else
- log_error("Oops, secure memory pool already initialized\n");
- }
-}
-
-void *secmem_malloc(size_t size) {
- MEMBLOCK *mb, *mb2;
- int compressed = 0;
-
- if (!pool_okay) {
- log_info("operation is not possible without initialized secure memory\n");
- log_info("(you may have used the wrong program for this task)\n");
- exit(2);
- }
- if (show_warning && !suspend_warning) {
- show_warning = 0;
- print_warn();
- }
-
- /* blocks are always a multiple of 32 */
- size += sizeof(MEMBLOCK);
- size = ((size + 31) / 32) * 32;
-
-retry:
- /* try to get it from the used blocks */
- for (mb = unused_blocks, mb2 = NULL; mb; mb2 = mb, mb = mb->u.next)
- if (mb->size >= size) {
- if (mb2)
- mb2->u.next = mb->u.next;
- else
- unused_blocks = mb->u.next;
- goto leave;
- }
- /* allocate a new block */
- if ((poollen + size <= poolsize)) {
- mb = (MEMBLOCK *)((char *)pool + poollen);
- poollen += size;
- mb->size = size;
- } else if (!compressed) {
- compressed = 1;
- compress_pool();
- goto retry;
- } else
- return NULL;
-
-leave:
- cur_alloced += mb->size;
- cur_blocks++;
- if (cur_alloced > max_alloced) max_alloced = cur_alloced;
- if (cur_blocks > max_blocks) max_blocks = cur_blocks;
-
- memset(&mb->u.aligned.c, 0,
- size - (size_t) & ((struct memblock_struct *)0)->u.aligned.c);
-
- return &mb->u.aligned.c;
-}
-
-void *secmem_realloc(void *p, size_t newsize) {
- MEMBLOCK *mb;
- size_t size;
- void *a;
-
- if (!p) return secmem_malloc(newsize);
-
- mb = (MEMBLOCK *)(void *)((char *)p - offsetof(MEMBLOCK, u.aligned.c));
-
- size = mb->size;
- if (newsize < size) return p; /* it is easier not to shrink the memory */
- a = secmem_malloc(newsize);
- memcpy(a, p, size);
- memset((char *)a + size, 0, newsize - size);
- secmem_free(p);
- return a;
-}
-
-void secmem_free(void *a) {
- MEMBLOCK *mb;
- size_t size;
-
- if (!a) return;
-
- mb = (MEMBLOCK *)(void *)((char *)a - offsetof(MEMBLOCK, u.aligned.c));
- size = mb->size;
- /* This does not make much sense: probably this memory is held in the
- * cache. We do it anyway: */
- wipememory2(mb, 0xff, size);
- wipememory2(mb, 0xaa, size);
- wipememory2(mb, 0x55, size);
- wipememory2(mb, 0x00, size);
- mb->size = size;
- mb->u.next = unused_blocks;
- unused_blocks = mb;
- cur_blocks--;
- cur_alloced -= size;
-}
-
-int m_is_secure(const void *p) {
- return p >= pool && p < (void *)((char *)pool + poolsize);
-}
-
-void secmem_term(void) {
- if (!pool_okay) return;
-
- wipememory2(pool, 0xff, poolsize);
- wipememory2(pool, 0xaa, poolsize);
- wipememory2(pool, 0x55, poolsize);
- wipememory2(pool, 0x00, poolsize);
-#if HAVE_MMAP
- if (pool_is_mmapped) munmap(pool, poolsize);
-#endif
- pool = NULL;
- pool_okay = 0;
- poolsize = 0;
- poollen = 0;
- unused_blocks = NULL;
-}
-
-void secmem_dump_stats(void) {
- if (disable_secmem) return;
- fprintf(stderr, "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
- cur_alloced, max_alloced, cur_blocks, max_blocks, (ulong)poollen,
- (ulong)poolsize);
-}
-
-size_t secmem_get_max_size(void) { return poolsize; }