void FTW_EntropySource::poll(Entropy_Accumulator& accum) { const size_t MAX_FILES_READ_PER_POLL = 2048; if(!dir) dir = new Directory_Walker(path); MemoryRegion<byte>& io_buffer = accum.get_io_buffer(4096); for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { int fd = dir->next_fd(); // If we've exhaused this walk of the directory, halt the poll if(fd == -1) { delete dir; dir = 0; break; } ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size()); ::close(fd); if(got > 0) accum.add(&io_buffer[0], got, .001); if(accum.polling_goal_achieved()) break; } }
void ProcWalking_EntropySource::poll(Entropy_Accumulator& accum) { const size_t MAX_FILES_READ_PER_POLL = 2048; const double ENTROPY_ESTIMATE = 1.0 / (8*1024); std::lock_guard<std::mutex> lock(m_mutex); if(!m_dir) m_dir.reset(new Directory_Walker(m_path)); m_buf.resize(4096); for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { int fd = m_dir->next_fd(); // If we've exhaused this walk of the directory, halt the poll if(fd == -1) { m_dir.reset(); break; } ssize_t got = ::read(fd, m_buf.data(), m_buf.size()); ::close(fd); if(got > 0) accum.add(m_buf.data(), got, ENTROPY_ESTIMATE); if(accum.polling_finished()) break; } }
void UnixProcessInfo_EntropySource::poll(Entropy_Accumulator& accum) { accum.add(::getpid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); accum.add(::getppid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); accum.add(::getuid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); accum.add(::getgid(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); accum.add(::getpgrp(), BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); struct ::rusage usage; ::getrusage(RUSAGE_SELF, &usage); accum.add(usage, BOTAN_ENTROPY_ESTIMATE_STATIC_SYSTEM_DATA); }
/* * Gather Entropy from Win32 CAPI */ void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum) { secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); for(size_t i = 0; i != m_prov_types.size(); ++i) { CSP_Handle csp(m_prov_types[i]); if(size_t got = csp.gen_random(buf.data(), buf.size())) { accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); break; } } }
/** * Gather Entropy from EGD */ void EGD_EntropySource::poll(Entropy_Accumulator& accum) { size_t go_get = std::min<size_t>(accum.desired_remaining_bits() / 8, 32); MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != sockets.size(); ++i) { size_t got = sockets[i].read(&io_buffer[0], io_buffer.size()); if(got) { accum.add(&io_buffer[0], got, 6); break; } } }
void Entropy_Sources::poll(Entropy_Accumulator& accum) { for(size_t i = 0; i != m_srcs.size(); ++i) { m_srcs[i]->poll(accum); if(accum.polling_goal_achieved()) break; } }
/** * Gather entropy from a RNG device */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 48); u32bit read_wait_ms = std::max<u32bit>(go_get, 1000); MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != devices.size(); ++i) { u32bit got = devices[i].get(io_buffer.begin(), io_buffer.size(), read_wait_ms); if(got) { accum.add(io_buffer.begin(), got, 8); break; } } }
/** * Gather Entropy from EGD */ void EGD_EntropySource::poll(Entropy_Accumulator& accum) { const size_t ENTROPY_BITS_PER_BYTE = 8; std::lock_guard<std::mutex> lock(m_mutex); secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); for(size_t i = 0; i != sockets.size(); ++i) { size_t got = sockets[i].read(buf.data(), buf.size()); if(got) { accum.add(buf.data(), got, ENTROPY_BITS_PER_BYTE); break; } } }
/* * Gather Entropy from Win32 CAPI */ void Win32_CAPI_EntropySource::poll(Entropy_Accumulator& accum) { m_buf.resize(32); for(size_t i = 0; i != prov_types.size(); ++i) { CSP_Handle csp(prov_types[i]); if(size_t got = csp.gen_random(m_buf.data(), m_buf.size())) { accum.add(m_buf.data(), got, 6); break; } } }
/** * BeOS entropy poll */ void BeOS_EntropySource::poll(Entropy_Accumulator& accum) { system_info info_sys; get_system_info(&info_sys); accum.add(info_sys, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); key_info info_key; // current state of the keyboard get_key_info(&info_key); accum.add(info_key, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); team_info info_team; int32 cookie_team = 0; while(get_next_team_info(&cookie_team, &info_team) == B_OK) { accum.add(info_team, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); team_id id = info_team.team; int32 cookie = 0; thread_info info_thr; while(get_next_thread_info(id, &cookie, &info_thr) == B_OK) accum.add(info_thr, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); cookie = 0; image_info info_img; while(get_next_image_info(id, &cookie, &info_img) == B_OK) accum.add(info_img, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); cookie = 0; sem_info info_sem; while(get_next_sem_info(id, &cookie, &info_sem) == B_OK) accum.add(info_sem, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); cookie = 0; area_info info_area; while(get_next_area_info(id, &cookie, &info_area) == B_OK) accum.add(info_area, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); if(accum.polling_finished()) break; } }
/** * Gather entropy from a RNG device */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { if(m_devices.empty()) return; const size_t ENTROPY_BITS_PER_BYTE = 8; const size_t MS_WAIT_TIME = 32; const size_t READ_ATTEMPT = 32; int max_fd = m_devices[0]; fd_set read_set; FD_ZERO(&read_set); for(size_t i = 0; i != m_devices.size(); ++i) { FD_SET(m_devices[i], &read_set); max_fd = std::max(m_devices[i], max_fd); } struct ::timeval timeout; timeout.tv_sec = (MS_WAIT_TIME / 1000); timeout.tv_usec = (MS_WAIT_TIME % 1000) * 1000; if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) return; m_buf.resize(READ_ATTEMPT); for(size_t i = 0; i != m_devices.size(); ++i) { if(FD_ISSET(m_devices[i], &read_set)) { const ssize_t got = ::read(m_devices[i], &m_buf[0], m_buf.size()); if(got > 0) accum.add(&m_buf[0], got, ENTROPY_BITS_PER_BYTE); } } }
/** * Win32 poll using stats functions including Tooltip32 */ void Win32_EntropySource::poll(Entropy_Accumulator& accum) { /* First query a bunch of basic statistical stuff, though don't count it for much in terms of contributed entropy. */ accum.add(GetTickCount(), 0); accum.add(GetMessagePos(), 0); accum.add(GetMessageTime(), 0); accum.add(GetInputState(), 0); accum.add(GetCurrentProcessId(), 0); accum.add(GetCurrentThreadId(), 0); SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); accum.add(sys_info, 1); MEMORYSTATUS mem_info; GlobalMemoryStatus(&mem_info); accum.add(mem_info, 1); POINT point; GetCursorPos(&point); accum.add(point, 1); GetCaretPos(&point); accum.add(point, 1); LARGE_INTEGER perf_counter; QueryPerformanceCounter(&perf_counter); accum.add(perf_counter, 0); /* Now use the Tooltip library to iterate throug various objects on the system, including processes, threads, and heap objects. */ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); #define TOOLHELP32_ITER(DATA_TYPE, FUNC_FIRST, FUNC_NEXT) \ if(!accum.polling_finished()) \ { \ DATA_TYPE info; \ info.dwSize = sizeof(DATA_TYPE); \ if(FUNC_FIRST(snapshot, &info)) \ { \ do \ { \ accum.add(info, 1); \ } while(FUNC_NEXT(snapshot, &info)); \ } \ } TOOLHELP32_ITER(MODULEENTRY32, Module32First, Module32Next); TOOLHELP32_ITER(PROCESSENTRY32, Process32First, Process32Next); TOOLHELP32_ITER(THREADENTRY32, Thread32First, Thread32Next); #undef TOOLHELP32_ITER if(!accum.polling_finished()) { size_t heap_lists_found = 0; HEAPLIST32 heap_list; heap_list.dwSize = sizeof(HEAPLIST32); const size_t HEAP_LISTS_MAX = 32; const size_t HEAP_OBJS_PER_LIST = 128; if(Heap32ListFirst(snapshot, &heap_list)) { do { accum.add(heap_list, 1); if(++heap_lists_found > HEAP_LISTS_MAX) break; size_t heap_objs_found = 0; HEAPENTRY32 heap_entry; heap_entry.dwSize = sizeof(HEAPENTRY32); if(Heap32First(&heap_entry, heap_list.th32ProcessID, heap_list.th32HeapID)) { do { if(heap_objs_found++ > HEAP_OBJS_PER_LIST) break; accum.add(heap_entry, 1); } while(Heap32Next(&heap_entry)); } if(accum.polling_finished()) break; } while(Heap32ListNext(snapshot, &heap_list)); } } CloseHandle(snapshot); }
void Unix_EntropySource::poll(Entropy_Accumulator& accum) { // refuse to run setuid or setgid, or as root if((getuid() != geteuid()) || (getgid() != getegid()) || (geteuid() == 0)) return; std::lock_guard<std::mutex> lock(m_mutex); if(m_sources.empty()) { auto sources = get_default_sources(); for(auto src : sources) { const std::string path = find_full_path_if_exists(m_trusted_paths, src[0]); if(path != "") { src[0] = path; m_sources.push_back(src); } } } if(m_sources.empty()) return; // still empty, really nothing to try const size_t MS_WAIT_TIME = 32; m_buf.resize(4096); while(!accum.polling_finished()) { while(m_procs.size() < m_concurrent) m_procs.emplace_back(Unix_Process(next_source())); fd_set read_set; FD_ZERO(&read_set); std::vector<int> fds; for(auto& proc : m_procs) { int fd = proc.fd(); if(fd > 0) { fds.push_back(fd); FD_SET(fd, &read_set); } } if(fds.empty()) break; const int max_fd = *std::max_element(fds.begin(), fds.end()); struct ::timeval timeout; timeout.tv_sec = (MS_WAIT_TIME / 1000); timeout.tv_usec = (MS_WAIT_TIME % 1000) * 1000; if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) return; // or continue? for(auto& proc : m_procs) { int fd = proc.fd(); if(FD_ISSET(fd, &read_set)) { const ssize_t got = ::read(fd, m_buf.data(), m_buf.size()); if(got > 0) accum.add(m_buf.data(), got, BOTAN_ENTROPY_ESTIMATE_SYSTEM_TEXT); else proc.spawn(next_source()); } } } }