Botan  2.10.0
Crypto and TLS for C++11
Classes | Functions
Botan::OS Namespace Reference

Classes

class  Echo_Suppression
 
class  Socket
 

Functions

std::vector< void * > allocate_locked_pages (size_t count)
 
void free_locked_pages (const std::vector< void * > &pages)
 
uint64_t BOTAN_TEST_API get_cpu_cycle_counter ()
 
uint64_t BOTAN_TEST_API get_high_resolution_clock ()
 
size_t get_memory_locking_limit ()
 
uint32_t BOTAN_TEST_API get_process_id ()
 
uint64_t BOTAN_TEST_API get_system_timestamp_ns ()
 
std::unique_ptr< Socket > BOTAN_TEST_API open_socket (const std::string &hostname, const std::string &service, std::chrono::milliseconds timeout)
 
void page_allow_access (void *page)
 
void page_prohibit_access (void *page)
 
const char * read_env_variable (const std::string &var_name)
 
size_t read_env_variable_sz (const std::string &var_name, size_t def_value=0)
 
int BOTAN_TEST_API run_cpu_instruction_probe (std::function< int()> probe_fn)
 
bool running_in_privileged_state ()
 
std::unique_ptr< Echo_Suppression > BOTAN_UNSTABLE_API suppress_echo_on_terminal ()
 
size_t system_page_size ()
 

Function Documentation

◆ allocate_locked_pages()

std::vector< void * > Botan::OS::allocate_locked_pages ( size_t  count)

Request @count pages of RAM which are locked into memory using mlock, VirtualLock, or some similar OS specific API. Free it with free_locked_pages.

Returns an empty list on failure. This function is allowed to return fewer than @count pages.

The contents of the allocated pages are undefined.

Each page is preceded by and followed by a page which is marked as noaccess, such that accessing it will cause a crash. This turns out of bound reads/writes into crash events.

Parameters
countrequested number of locked pages

Definition at line 334 of file os_utils.cpp.

335  {
336  std::vector<void*> result;
337  result.reserve(count);
338 
339  const size_t page_size = OS::system_page_size();
340 
341  for(size_t i = 0; i != count; ++i)
342  {
343  void* ptr = nullptr;
344 
345 #if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
346 
347 #if !defined(MAP_NOCORE)
348  #define MAP_NOCORE 0
349 #endif
350 
351  ptr = ::mmap(nullptr, 2*page_size,
352  PROT_READ | PROT_WRITE,
353  MAP_ANONYMOUS | MAP_PRIVATE | MAP_NOCORE,
354  /*fd=*/-1, /*offset=*/0);
355 
356  if(ptr == MAP_FAILED)
357  {
358  continue;
359  }
360 
361  // failed to lock
362  if(::mlock(ptr, page_size) != 0)
363  {
364  ::munmap(ptr, 2*page_size);
365  continue;
366  }
367 
368 #if defined(MADV_DONTDUMP)
369  // we ignore errors here, as DONTDUMP is just a bonus
370  ::madvise(ptr, page_size, MADV_DONTDUMP);
371 #endif
372 
373 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
374  ptr = ::VirtualAlloc(nullptr, 2*page_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
375 
376  if(ptr == nullptr)
377  continue;
378 
379  if(::VirtualLock(ptr, page_size) == 0)
380  {
381  ::VirtualFree(ptr, 0, MEM_RELEASE);
382  continue;
383  }
384 #endif
385 
386  std::memset(ptr, 0, 2*page_size); // zero both data and guard pages
387 
388  // Make guard page following the data page
389  page_prohibit_access(static_cast<uint8_t*>(ptr) + page_size);
390 
391  result.push_back(ptr);
392  }
393 
394  return result;
395  }
void page_prohibit_access(void *page)
Definition: os_utils.cpp:409
size_t system_page_size()
Definition: os_utils.cpp:232

References page_prohibit_access(), and system_page_size().

◆ free_locked_pages()

void Botan::OS::free_locked_pages ( const std::vector< void * > &  pages)

Free memory allocated by allocate_locked_pages

Parameters
pagesa list of pages returned by allocate_locked_pages

Definition at line 421 of file os_utils.cpp.

422  {
423  const size_t page_size = OS::system_page_size();
424 
425  for(size_t i = 0; i != pages.size(); ++i)
426  {
427  void* ptr = pages[i];
428 
429  secure_scrub_memory(ptr, page_size);
430 
431  // ptr points to the data page, guard page follows
432  page_allow_access(static_cast<uint8_t*>(ptr) + page_size);
433 
434 #if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
435  ::munlock(ptr, page_size);
436  ::munmap(ptr, 2*page_size);
437 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
438  ::VirtualUnlock(ptr, page_size);
439  ::VirtualFree(ptr, 0, MEM_RELEASE);
440 #endif
441  }
442  }
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:51
size_t system_page_size()
Definition: os_utils.cpp:232
void page_allow_access(void *page)
Definition: os_utils.cpp:397

References page_allow_access(), Botan::secure_scrub_memory(), and system_page_size().

◆ get_cpu_cycle_counter()

uint64_t Botan::OS::get_cpu_cycle_counter ( )
Returns
CPU processor clock, if available

On Windows, calls QueryPerformanceCounter.

Under GCC or Clang on supported platforms the hardware cycle counter is queried. Currently supported processors are x86, PPC, Alpha, SPARC, IA-64, S/390x, and HP-PA. If no CPU cycle counter is available on this system, returns zero.

Definition at line 105 of file os_utils.cpp.

106  {
107  uint64_t rtc = 0;
108 
109 #if defined(BOTAN_TARGET_OS_HAS_WIN32)
110  LARGE_INTEGER tv;
111  ::QueryPerformanceCounter(&tv);
112  rtc = tv.QuadPart;
113 
114 #elif defined(BOTAN_USE_GCC_INLINE_ASM)
115 
116 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
117 
118  if(CPUID::has_rdtsc())
119  {
120  uint32_t rtc_low = 0, rtc_high = 0;
121  asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
122  rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
123  }
124 
125 #elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
126 
127  for(;;)
128  {
129  uint32_t rtc_low = 0, rtc_high = 0, rtc_high2 = 0;
130  asm volatile("mftbu %0" : "=r" (rtc_high));
131  asm volatile("mftb %0" : "=r" (rtc_low));
132  asm volatile("mftbu %0" : "=r" (rtc_high2));
133 
134  if(rtc_high == rtc_high2)
135  {
136  rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
137  break;
138  }
139  }
140 
141 #elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
142  asm volatile("rpcc %0" : "=r" (rtc));
143 
144  // OpenBSD does not trap access to the %tick register
145 #elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
146  asm volatile("rd %%tick, %0" : "=r" (rtc));
147 
148 #elif defined(BOTAN_TARGET_ARCH_IS_IA64)
149  asm volatile("mov %0=ar.itc" : "=r" (rtc));
150 
151 #elif defined(BOTAN_TARGET_ARCH_IS_S390X)
152  asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc");
153 
154 #elif defined(BOTAN_TARGET_ARCH_IS_HPPA)
155  asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only?
156 
157 #else
158  //#warning "OS::get_cpu_cycle_counter not implemented"
159 #endif
160 
161 #endif
162 
163  return rtc;
164  }

Referenced by get_high_resolution_clock(), Botan::Timer::start(), and Botan::Timer::stop().

◆ get_high_resolution_clock()

uint64_t Botan::OS::get_high_resolution_clock ( )

Definition at line 166 of file os_utils.cpp.

167  {
168  if(uint64_t cpu_clock = OS::get_cpu_cycle_counter())
169  return cpu_clock;
170 
171 #if defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
172  return emscripten_get_now();
173 #endif
174 
175  /*
176  If we got here either we either don't have an asm instruction
177  above, or (for x86) RDTSC is not available at runtime. Try some
178  clock_gettimes and return the first one that works, or otherwise
179  fall back to std::chrono.
180  */
181 
182 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
183 
184  // The ordering here is somewhat arbitrary...
185  const clockid_t clock_types[] = {
186 #if defined(CLOCK_MONOTONIC_HR)
187  CLOCK_MONOTONIC_HR,
188 #endif
189 #if defined(CLOCK_MONOTONIC_RAW)
190  CLOCK_MONOTONIC_RAW,
191 #endif
192 #if defined(CLOCK_MONOTONIC)
193  CLOCK_MONOTONIC,
194 #endif
195 #if defined(CLOCK_PROCESS_CPUTIME_ID)
196  CLOCK_PROCESS_CPUTIME_ID,
197 #endif
198 #if defined(CLOCK_THREAD_CPUTIME_ID)
199  CLOCK_THREAD_CPUTIME_ID,
200 #endif
201  };
202 
203  for(clockid_t clock : clock_types)
204  {
205  struct timespec ts;
206  if(::clock_gettime(clock, &ts) == 0)
207  {
208  return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec);
209  }
210  }
211 #endif
212 
213  // Plain C++11 fallback
214  auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
215  return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
216  }
uint64_t BOTAN_TEST_API get_cpu_cycle_counter()
Definition: os_utils.cpp:105

References get_cpu_cycle_counter().

◆ get_memory_locking_limit()

size_t Botan::OS::get_memory_locking_limit ( )
Returns
maximum amount of memory (in bytes) Botan could/should hyptothetically allocate for the memory poool. Reads environment variable "BOTAN_MLOCK_POOL_SIZE", set to "0" to disable pool.

Definition at line 251 of file os_utils.cpp.

252  {
253 #if defined(BOTAN_TARGET_OS_HAS_POSIX1) && defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) && defined(RLIMIT_MEMLOCK)
254  /*
255  * If RLIMIT_MEMLOCK is not defined, likely the OS does not support
256  * unprivileged mlock calls.
257  *
258  * Linux defaults to only 64 KiB of mlockable memory per process
259  * (too small) but BSDs offer a small fraction of total RAM (more
260  * than we need). Bound the total mlock size to 512 KiB which is
261  * enough to run the entire test suite without spilling to non-mlock
262  * memory (and thus presumably also enough for many useful
263  * programs), but small enough that we should not cause problems
264  * even if many processes are mlocking on the same machine.
265  */
266  const size_t user_req = read_env_variable_sz("BOTAN_MLOCK_POOL_SIZE", BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB);
267 
268  const size_t mlock_requested = std::min<size_t>(user_req, BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB);
269 
270  if(mlock_requested > 0)
271  {
272  struct ::rlimit limits;
273 
274  ::getrlimit(RLIMIT_MEMLOCK, &limits);
275 
276  if(limits.rlim_cur < limits.rlim_max)
277  {
278  limits.rlim_cur = limits.rlim_max;
279  ::setrlimit(RLIMIT_MEMLOCK, &limits);
280  ::getrlimit(RLIMIT_MEMLOCK, &limits);
281  }
282 
283  return std::min<size_t>(limits.rlim_cur, mlock_requested * 1024);
284  }
285 
286 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
287  SIZE_T working_min = 0, working_max = 0;
288  if(!::GetProcessWorkingSetSize(::GetCurrentProcess(), &working_min, &working_max))
289  {
290  return 0;
291  }
292 
293  // According to Microsoft MSDN:
294  // The maximum number of pages that a process can lock is equal to the number of pages in its minimum working set minus a small overhead
295  // In the book "Windows Internals Part 2": the maximum lockable pages are minimum working set size - 8 pages
296  // But the information in the book seems to be inaccurate/outdated
297  // I've tested this on Windows 8.1 x64, Windows 10 x64 and Windows 7 x86
298  // On all three OS the value is 11 instead of 8
299  const size_t overhead = OS::system_page_size() * 11;
300  if(working_min > overhead)
301  {
302  const size_t lockable_bytes = working_min - overhead;
303  return std::min<size_t>(lockable_bytes, BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024);
304  }
305 #endif
306 
307  // Not supported on this platform
308  return 0;
309  }
size_t read_env_variable_sz(const std::string &var_name, size_t def_value=0)
Definition: os_utils.cpp:319
size_t system_page_size()
Definition: os_utils.cpp:232

References read_env_variable_sz(), and system_page_size().

◆ get_process_id()

uint32_t Botan::OS::get_process_id ( )
Returns
process ID assigned by the operating system. On Unix and Windows systems, this always returns a result On IncludeOS it returns 0 since there is no process ID to speak of in a unikernel.

Definition at line 81 of file os_utils.cpp.

82  {
83 #if defined(BOTAN_TARGET_OS_HAS_POSIX1)
84  return ::getpid();
85 #elif defined(BOTAN_TARGET_OS_HAS_WIN32)
86  return ::GetCurrentProcessId();
87 #elif defined(BOTAN_TARGET_OS_IS_INCLUDEOS) || defined(BOTAN_TARGET_OS_IS_LLVM)
88  return 0; // truly no meaningful value
89 #else
90  #error "Missing get_process_id"
91 #endif
92  }

◆ get_system_timestamp_ns()

uint64_t Botan::OS::get_system_timestamp_ns ( )
Returns
system clock (reflecting wall clock) with best resolution available, normalized to nanoseconds resolution.

Definition at line 218 of file os_utils.cpp.

219  {
220 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
221  struct timespec ts;
222  if(::clock_gettime(CLOCK_REALTIME, &ts) == 0)
223  {
224  return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec);
225  }
226 #endif
227 
228  auto now = std::chrono::system_clock::now().time_since_epoch();
229  return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
230  }

Referenced by Botan::Timer::start(), and Botan::Timer::stop().

◆ open_socket()

std::unique_ptr< OS::Socket > Botan::OS::open_socket ( const std::string &  hostname,
const std::string &  service,
std::chrono::milliseconds  timeout 
)

Open up a socket. Will throw on error. Returns null if sockets are not available on this platform.

Definition at line 353 of file socket.cpp.

356  {
357 #if defined(BOTAN_HAS_BOOST_ASIO)
358  return std::unique_ptr<OS::Socket>(new Asio_Socket(hostname, service, timeout));
359 
360 #elif defined(BOTAN_TARGET_OS_HAS_SOCKETS) || defined(BOTAN_TARGET_OS_HAS_WINSOCK2)
361  return std::unique_ptr<OS::Socket>(new BSD_Socket(hostname, service, timeout));
362 
363 #else
364  // No sockets for you
365  return std::unique_ptr<Socket>();
366 #endif
367  }
const char * hostname
Definition: ffi.h:1500

References Botan::hostname.

◆ page_allow_access()

void Botan::OS::page_allow_access ( void *  page)

Set the MMU to allow R/W access to this page

Definition at line 397 of file os_utils.cpp.

398  {
399  const size_t page_size = OS::system_page_size();
400 #if defined(BOTAN_TARGET_OS_HAS_POSIX1)
401  ::mprotect(page, page_size, PROT_READ | PROT_WRITE);
402 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
403  DWORD old_perms = 0;
404  ::VirtualProtect(page, page_size, PAGE_READWRITE, &old_perms);
405  BOTAN_UNUSED(old_perms);
406 #endif
407  }
#define BOTAN_UNUSED(...)
Definition: assert.h:142
size_t system_page_size()
Definition: os_utils.cpp:232

References BOTAN_UNUSED, and system_page_size().

Referenced by Botan::Memory_Pool::allocate(), free_locked_pages(), and Botan::Memory_Pool::~Memory_Pool().

◆ page_prohibit_access()

void Botan::OS::page_prohibit_access ( void *  page)

Set the MMU to prohibit access to this page

Definition at line 409 of file os_utils.cpp.

410  {
411  const size_t page_size = OS::system_page_size();
412 #if defined(BOTAN_TARGET_OS_HAS_POSIX1)
413  ::mprotect(page, page_size, PROT_NONE);
414 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
415  DWORD old_perms = 0;
416  ::VirtualProtect(page, page_size, PAGE_NOACCESS, &old_perms);
417  BOTAN_UNUSED(old_perms);
418 #endif
419  }
#define BOTAN_UNUSED(...)
Definition: assert.h:142
size_t system_page_size()
Definition: os_utils.cpp:232

References BOTAN_UNUSED, and system_page_size().

Referenced by allocate_locked_pages(), and Botan::Memory_Pool::Memory_Pool().

◆ read_env_variable()

const char * Botan::OS::read_env_variable ( const std::string &  var_name)

Read the value of an environment variable. Return nullptr if no such variable is set. If the process seems to be running in a privileged state (such as setuid) then always returns nullptr, similiar to glibc's secure_getenv.

Definition at line 311 of file os_utils.cpp.

312  {
314  return nullptr;
315 
316  return std::getenv(name.c_str());
317  }
char * name
Definition: ffi.h:327
bool running_in_privileged_state()
Definition: os_utils.cpp:94

References name, and running_in_privileged_state().

Referenced by Botan_FFI::ffi_error_exception_thrown(), and read_env_variable_sz().

◆ read_env_variable_sz()

size_t Botan::OS::read_env_variable_sz ( const std::string &  var_name,
size_t  def_value = 0 
)

Read the value of an environment variable and convert it to an integer. If not set or conversion fails, returns the default value.

If the process seems to be running in a privileged state (such as setuid) then always returns nullptr, similiar to glibc's secure_getenv.

Definition at line 319 of file os_utils.cpp.

320  {
321  if(const char* env = read_env_variable(name))
322  {
323  try
324  {
325  const size_t val = std::stoul(env, nullptr);
326  return val;
327  }
328  catch(std::exception&) { /* ignore it */ }
329  }
330 
331  return def;
332  }
char * name
Definition: ffi.h:327
uint32_t * val
Definition: ffi.h:794
const char * read_env_variable(const std::string &var_name)
Definition: os_utils.cpp:311

References name, read_env_variable(), and val.

Referenced by get_memory_locking_limit(), and Botan::Thread_Pool::global_instance().

◆ run_cpu_instruction_probe()

int Botan::OS::run_cpu_instruction_probe ( std::function< int()>  probe_fn)

Run a probe instruction to test for support for a CPU instruction. Runs in system-specific env that catches illegal instructions; this function always fails if the OS doesn't provide this. Returns value of probe_fn, if it could run. If error occurs, returns negative number. This allows probe_fn to indicate errors of its own, if it wants. For example the instruction might not only be only available on some CPUs, but also buggy on some subset of these - the probe function can test to make sure the instruction works properly before indicating that the instruction is available.

Warning
on Unix systems uses signal handling in a way that is not thread safe. It should only be called in a single-threaded context (ie, at static init time).

If probe_fn throws an exception the result is undefined.

Return codes: -1 illegal instruction detected

Definition at line 459 of file os_utils.cpp.

460  {
461  volatile int probe_result = -3;
462 
463 #if defined(BOTAN_TARGET_OS_HAS_POSIX1) && !defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
464  struct sigaction old_sigaction;
465  struct sigaction sigaction;
466 
467  sigaction.sa_handler = botan_sigill_handler;
468  sigemptyset(&sigaction.sa_mask);
469  sigaction.sa_flags = 0;
470 
471  int rc = ::sigaction(SIGILL, &sigaction, &old_sigaction);
472 
473  if(rc != 0)
474  throw System_Error("run_cpu_instruction_probe sigaction failed", errno);
475 
476  rc = sigsetjmp(g_sigill_jmp_buf, /*save sigs*/1);
477 
478  if(rc == 0)
479  {
480  // first call to sigsetjmp
481  probe_result = probe_fn();
482  }
483  else if(rc == 1)
484  {
485  // non-local return from siglongjmp in signal handler: return error
486  probe_result = -1;
487  }
488 
489  // Restore old SIGILL handler, if any
490  rc = ::sigaction(SIGILL, &old_sigaction, nullptr);
491  if(rc != 0)
492  throw System_Error("run_cpu_instruction_probe sigaction restore failed", errno);
493 
494 #elif defined(BOTAN_TARGET_OS_IS_WINDOWS) && defined(BOTAN_TARGET_COMPILER_IS_MSVC)
495 
496  // Windows SEH
497  __try
498  {
499  probe_result = probe_fn();
500  }
501  __except(::GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ?
502  EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
503  {
504  probe_result = -1;
505  }
506 
507 #else
508  BOTAN_UNUSED(probe_fn);
509 #endif
510 
511  return probe_result;
512  }
#define BOTAN_UNUSED(...)
Definition: assert.h:142

References BOTAN_UNUSED.

◆ running_in_privileged_state()

bool Botan::OS::running_in_privileged_state ( )

Test if we are currently running with elevated permissions eg setuid, setgid, or with POSIX caps set.

Definition at line 94 of file os_utils.cpp.

95  {
96 #if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) && defined(AT_SECURE)
97  return ::getauxval(AT_SECURE) != 0;
98 #elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
99  return (::getuid() != ::geteuid()) || (::getgid() != ::getegid());
100 #else
101  return false;
102 #endif
103  }

Referenced by read_env_variable().

◆ suppress_echo_on_terminal()

std::unique_ptr< OS::Echo_Suppression > Botan::OS::suppress_echo_on_terminal ( )

Suppress echo on the terminal Returns null if this operation is not supported on the current system.

Definition at line 514 of file os_utils.cpp.

515  {
516 #if defined(BOTAN_TARGET_OS_HAS_POSIX1)
517  class POSIX_Echo_Suppression : public Echo_Suppression
518  {
519  public:
520  POSIX_Echo_Suppression()
521  {
522  m_stdin_fd = fileno(stdin);
523  if(::tcgetattr(m_stdin_fd, &m_old_termios) != 0)
524  throw System_Error("Getting terminal status failed", errno);
525 
526  struct termios noecho_flags = m_old_termios;
527  noecho_flags.c_lflag &= ~ECHO;
528  noecho_flags.c_lflag |= ECHONL;
529 
530  if(::tcsetattr(m_stdin_fd, TCSANOW, &noecho_flags) != 0)
531  throw System_Error("Clearing terminal echo bit failed", errno);
532  }
533 
534  void reenable_echo() override
535  {
536  if(m_stdin_fd > 0)
537  {
538  if(::tcsetattr(m_stdin_fd, TCSANOW, &m_old_termios) != 0)
539  throw System_Error("Restoring terminal echo bit failed", errno);
540  m_stdin_fd = -1;
541  }
542  }
543 
544  ~POSIX_Echo_Suppression()
545  {
546  try
547  {
548  reenable_echo();
549  }
550  catch(...)
551  {
552  }
553  }
554 
555  private:
556  int m_stdin_fd;
557  struct termios m_old_termios;
558  };
559 
560  return std::unique_ptr<Echo_Suppression>(new POSIX_Echo_Suppression);
561 
562 #elif defined(BOTAN_TARGET_OS_HAS_WIN32)
563 
564  class Win32_Echo_Suppression : public Echo_Suppression
565  {
566  public:
567  Win32_Echo_Suppression()
568  {
569  m_input_handle = ::GetStdHandle(STD_INPUT_HANDLE);
570  if(::GetConsoleMode(m_input_handle, &m_console_state) == 0)
571  throw System_Error("Getting console mode failed", ::GetLastError());
572 
573  DWORD new_mode = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
574  if(::SetConsoleMode(m_input_handle, new_mode) == 0)
575  throw System_Error("Setting console mode failed", ::GetLastError());
576  }
577 
578  void reenable_echo() override
579  {
580  if(m_input_handle != INVALID_HANDLE_VALUE)
581  {
582  if(::SetConsoleMode(m_input_handle, m_console_state) == 0)
583  throw System_Error("Setting console mode failed", ::GetLastError());
584  m_input_handle = INVALID_HANDLE_VALUE;
585  }
586  }
587 
588  ~Win32_Echo_Suppression()
589  {
590  try
591  {
592  reenable_echo();
593  }
594  catch(...)
595  {
596  }
597  }
598 
599  private:
600  HANDLE m_input_handle;
601  DWORD m_console_state;
602  };
603 
604  return std::unique_ptr<Echo_Suppression>(new Win32_Echo_Suppression);
605 
606 #else
607 
608  // Not supported on this platform, return null
609  return std::unique_ptr<Echo_Suppression>();
610 #endif
611  }

◆ system_page_size()

size_t Botan::OS::system_page_size ( )

Return the size of a memory page, if that can be derived on the current system. Otherwise returns some default value (eg 4096)

Definition at line 232 of file os_utils.cpp.

233  {
234  const size_t default_page_size = 4096;
235 
236 #if defined(BOTAN_TARGET_OS_HAS_POSIX1)
237  long p = ::sysconf(_SC_PAGESIZE);
238  if(p > 1)
239  return static_cast<size_t>(p);
240  else
241  return default_page_size;
242 #elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK)
243  SYSTEM_INFO sys_info;
244  ::GetSystemInfo(&sys_info);
245  return sys_info.dwPageSize;
246 #else
247  return default_page_size;
248 #endif
249  }
size_t const char const uint8_t size_t size_t size_t size_t p
Definition: ffi.h:624

References Botan::p.

Referenced by allocate_locked_pages(), free_locked_pages(), get_memory_locking_limit(), page_allow_access(), and page_prohibit_access().