SecureVector<byte> DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { rng.add_entropy(msg, msg_len); BigInt i(msg, msg_len); BigInt r = 0, s = 0; while(r == 0 || s == 0) { BigInt k; do k.randomize(rng, q.bits()); while(k >= q); r = mod_q.reduce(powermod_g_p(k)); s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i)); } SecureVector<byte> output(2*q.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; }
SecureVector<byte> ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { rng.add_entropy(msg, msg_len); BigInt m(msg, msg_len); BigInt r = 0, s = 0; while(r == 0 || s == 0) { // This contortion is necessary for the tests BigInt k; k.randomize(rng, order.bits()); while(k >= order) k.randomize(rng, order.bits() - 1); PointGFp k_times_P = base_point * k; r = mod_order.reduce(k_times_P.get_affine_x()); s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m)); } SecureVector<byte> output(2*order.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; }
/** * Gather 256 bytes entropy from getentropy(2). Note that maximum * buffer size is limited to 256 bytes. On OpenBSD this does neither * block nor fail. */ size_t Getentropy::poll(RandomNumberGenerator& rng) { secure_vector<uint8_t> buf(256); if(::getentropy(buf.data(), buf.size()) == 0) { rng.add_entropy(buf.data(), buf.size()); return buf.size() * 8; } return 0; }
/** * Gather entropy from SecRandomCopyBytes */ size_t Darwin_SecRandom::poll(RandomNumberGenerator& rng) { secure_vector<uint8_t> buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); if(0 == SecRandomCopyBytes(kSecRandomDefault, buf.size(), buf.data())) { rng.add_entropy(buf.data(), buf.size()); return buf.size() * 8; } return 0; }
/* * Gather Entropy from Win32 CAPI */ size_t Win32_CAPI_EntropySource::poll(RandomNumberGenerator& rng) { secure_vector<uint8_t> buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); size_t bits = 0; for(size_t i = 0; i != m_csp_provs.size(); ++i) { size_t got = m_csp_provs[i]->gen_random(buf.data(), buf.size()); if(got > 0) { rng.add_entropy(buf.data(), got); bits += got * 8; } } return bits; }
size_t ProcWalking_EntropySource::poll(RandomNumberGenerator& rng) { const size_t MAX_FILES_READ_PER_POLL = 2048; lock_guard_type<mutex_type> lock(m_mutex); if(!m_dir) m_dir.reset(new Directory_Walker(m_path)); m_buf.resize(4096); size_t bits = 0; 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) { rng.add_entropy(m_buf.data(), static_cast<size_t>(got)); // Conservative estimate of 4 bits per file bits += 4; } if(bits > 128) break; } return bits; }
/** * Gather entropy from a RNG device */ size_t Device_EntropySource::poll(RandomNumberGenerator& rng) { size_t bits = 0; if(m_dev_fds.size() > 0) { fd_set read_set; FD_ZERO(&read_set); for(int dev_fd : m_dev_fds) { FD_SET(dev_fd, &read_set); } secure_vector<uint8_t> io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); struct ::timeval timeout; timeout.tv_sec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS / 1000); timeout.tv_usec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS % 1000) * 1000; if(::select(m_max_fd + 1, &read_set, nullptr, nullptr, &timeout) > 0) { for(int dev_fd : m_dev_fds) { if(FD_ISSET(dev_fd, &read_set)) { const ssize_t got = ::read(dev_fd, io_buf.data(), io_buf.size()); if(got > 0) { rng.add_entropy(io_buf.data(), static_cast<size_t>(got)); bits += got * 8; } } } } } return bits; }