pax_global_header00006660000000000000000000000064130516352200014507gustar00rootroot0000000000000052 comment=8df6fa4a458b4905f70e7da76e7dfc6cdaa2b1da entropybroker-2.9/000077500000000000000000000000001305163522000142665ustar00rootroot00000000000000entropybroker-2.9/ComScire_R2000KU/000077500000000000000000000000001305163522000170155ustar00rootroot00000000000000entropybroker-2.9/ComScire_R2000KU/LICENSE000066400000000000000000000044651305163522000200330ustar00rootroot00000000000000libqwqng is covered by the LGPL: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. A copy of the GNU Library General Public License (LGPL) is included in this distribution, in the file COPYING.LIB. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---- Alternatively, the file qwqng.hpp may be licensed under the BSD license: Copyright (c) 2012 Quantum World Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. entropybroker-2.9/ComScire_R2000KU/qwqng.cpp000066400000000000000000000562471305163522000206740ustar00rootroot00000000000000/* QWQNG_Linux Library Copyright (c) 2012, The Quantum World Corporation. All rights reserved. New BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "qwqng.hpp" /*************************************************** QWQNG Class *******************************************/ /* Class Initialization pointer */ QWQNG* QWQNG::_instance = 0; /* Private Constructor */ QWQNG* QWQNG::Instance() { _instance = new QWQNG(); return _instance; } /* Private Constructor */ QWQNG::QWQNG() : pDevice(NULL) { // pDevice instance pDevice = (IDevice*)new FtdiDevice(); // create new instance }; QWQNG::~QWQNG() { delete [] devId_; // delallocate memory delete [] statusString_; // deallocate memory delete pDevice; // release instance }; /* STATUS HANDLING: Property to return Status String */ char* QWQNG::StatusString() { // read status string std::string statusString = QngStatus::Instance().GetStatusString(); statusString_ = new char [statusString.size()]; strcpy(statusString_, statusString.c_str()); return statusString_; } /* Method to attempt to restart the hardware */ char* QWQNG::DeviceID() { // read from device std::string deviceId = pDevice->GetDeviceId(); devId_ = new char [deviceId.size()]; strcpy(devId_, deviceId.c_str()); return devId_; } /* Property to return a 32 bit random number */ int QWQNG::RandInt32(long* pVal) { // read from device pDevice->GetInt32((int32_t*)pVal); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Property to return a uniform number [0,1) */ int QWQNG::RandUniform(double* pVal) { // read from device pDevice->GetUniform(pVal); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Property to return a normal number */ int QWQNG::RandNormal(double *pVal) { // read from device pDevice->GetNormal(pVal); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Property to read byte */ int QWQNG::RandBytes(char* pval, long length) { // Check if valid length <= 8192 if(length>8192) { QngStatus::Instance().SetStatus(QNG_E_IO_ARRAY_OVERSIZED); return QNG_E_IO_ARRAY_OVERSIZED; } if(length==0) return S_OK; // read from device pDevice->GetBytes(pval, length); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Method to clear all buffers */ int QWQNG::Clear() { // read from device pDevice->Clear(); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Method to attempt to restart the hardware */ int QWQNG::Reset() { // read from device pDevice->Reset(); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /* Property to return internal stats */ int QWQNG::RuntimeInfo(float* pVal) { // read from device pDevice->GetRuntimeInfo(pVal); // Check status message if (QngStatus::Instance().GetStatus() == QNG_S_OK) return S_OK; else return QngStatus::Instance().GetStatus(); } /*************************************************** FtdiDevice Class *******************************************/ FtdiDevice::FtdiDevice() { QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); Open(); } FtdiDevice::~FtdiDevice() { Close(); } // opens the next FTDI QNG device, if available void FtdiDevice::Open() { FindOpen(); // Finds QNG device, opens handle Initialize(); // Check internal stats, start RNG if (QngStatus::Instance().GetStatus() != QNG_S_OK) { Close(); QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); } } void FtdiDevice::Close() { // Stop Device FtdiSendCommand(FTDIDEVICE_STOP_COMMAND_); FtdiClearReceiveBuffer(); // Clears the write buffer on the chip. FtdiClose(); // close libftdi context QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); } void FtdiDevice::Clear() { FtdiClearReceiveBuffer(); // Clears the write buffer on the chip. } void FtdiDevice::Reset() { // Stop Device FtdiSendCommand(FTDIDEVICE_STOP_COMMAND_); FtdiClearReceiveBuffer(); // Clears the write buffer on the chip. // Reset Device if ((ftdiStatus = ftdi_usb_reset(&ftdic)) < 0 ) { //fprintf(stderr, "ftdi_usb_reset failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // Open Device if ((ftdiStatus = ftdi_usb_open_desc(&ftdic, devVID, devPID, descInfo, serialInfo)) < 0 ) { //fprintf(stderr, "ftdi_usb_open_desc failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // Set DeviceId for public use IDevice::SetDeviceId(serialInfo); FtdiClearBuffers(); // clear RX/TX buffers on chip // Initialize Device Initialize(); if (QngStatus::Instance().GetStatus() != QNG_S_OK) { Close(); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } } void FtdiDevice::GetBytes(char* bytes, int bytesRequested) { if (bytesRequested>FTDIDEVICE_MAX_ARRAY_SIZE_ || bytesRequested<0) { QngStatus::Instance().SetStatus(QNG_E_IO_ARRAY_OVERSIZED); return; } FtdiRead(bytes, bytesRequested); } void FtdiDevice::GetInt32(int32_t* int32) { FtdiRead(int32, 4); } void FtdiDevice::GetUniform(double* uniform) { uint64_t uint48 = 0; FtdiRead(&uint48, 6); *uniform = Uint48ToUniform(uint48); } void FtdiDevice::GetNormal(double* normal) { if (haveNormU1_ == true) { // create normU2 uint64_t uint48 = 0; FtdiRead(&uint48, 6); double normU2 = Uint48ToUniform(uint48); normU2 += FTDIDEVICE_HALF_OF_UNIFORM_LSB_; // n1 = cos(2PI * u2) * sqrt(-2 * ln(u1)) // n2 = sin(2PI * u2) * sqrt(-2 * ln(u1)) double sqrtTerm = sqrt(-2.0 * log(normU1_)); *normal = cos(FTDIDEVICE_2_PI_ * normU2) * sqrtTerm; normalConjugate_ = sin(FTDIDEVICE_2_PI_ * normU2) * sqrtTerm; haveNormU1_ = false; } else { // do not have uniform 1, fill conjugate; // create normU1 uint64_t uint48 = 0; FtdiRead(&uint48, 6); normU1_ = Uint48ToUniform(uint48); normU1_ += FTDIDEVICE_HALF_OF_UNIFORM_LSB_; haveNormU1_ = true; *normal = normalConjugate_; } } void FtdiDevice::GetRuntimeInfo(float* runtimeInfo) { // initialize to failure condition runtimeInfo[0] = 1.0; for (int i=0; i<=3; ++i) { runtimeInfo[4*i+1] = 0.0; runtimeInfo[4*i+2] = 0.0; runtimeInfo[4*i+3] = 0.0; runtimeInfo[4*i+4] = 1.0; } // Stop Device FtdiSendCommand(FTDIDEVICE_STOP_COMMAND_); // look for the internal serial number (this is used as a delimiter) - try this 4 times int attempt = 4; uint8_t serialNumCheck[6]; while (attempt > 0) { FtdiClearReceiveBuffer(); // Clears the write buffer on the chip. FtdiSendCommand(FTDIDEVICE_READ_SERIAL_COMMAND_); FtdiUncheckedRead(serialNumCheck, 6); if (memcmp(serialNumCheck, internalSerialNum_, 6) == 0) break; attempt--; } if (attempt <= 0) return; // get test stats status uint32_t rngStatus = 0; FtdiSendCommand(FTDIDEVICE_TEST_STATUS_COMMAND_); FtdiUncheckedRead(&rngStatus, 4); if (rngStatus & FTDIDEVICE_TEST_BAD_STATS_MASK_) runtimeInfo[0] = -1.0; else runtimeInfo[0] = 0.0; // request final out stats FtdiSendCommand(FTDIDEVICE_TEST_FINAL_BASE_ + 1); FtdiUncheckedRead(&runtimeInfo[3], 4); FtdiSendCommand(FTDIDEVICE_TEST_FINAL_BASE_ + 2); FtdiUncheckedRead(&runtimeInfo[4], 4); FtdiSendCommand(FTDIDEVICE_TEST_FINAL_BASE_ + 3); FtdiUncheckedRead(&runtimeInfo[2], 4); runtimeInfo[1] = CalcEntropy(runtimeInfo[2]); // request channel stats for (int j=0; j<3; j++) { FtdiSendCommand(FTDIDEVICE_TEST_CHANNELS_BASE_ + j*0x10 + 1); FtdiUncheckedRead(&runtimeInfo[j*4 + 4 + 3], 4); FtdiSendCommand(FTDIDEVICE_TEST_CHANNELS_BASE_ + j*0x10 + 2); FtdiUncheckedRead(&runtimeInfo[j*4 + 4 + 4], 4); FtdiSendCommand(FTDIDEVICE_TEST_CHANNELS_BASE_ + j*0x10 + 3); FtdiUncheckedRead(&runtimeInfo[j*4 + 4 + 2], 4); runtimeInfo[j*4 + 4 + 1] = CalcEntropy(runtimeInfo[j*4 + 4 + 2]); } // if request not due to bad stats, restart the device if ((rngStatus & FTDIDEVICE_TEST_BAD_STATS_MASK_) != FTDIDEVICE_TEST_BAD_STATS_MASK_) { FtdiSendCommand(FTDIDEVICE_START_COMMAND_); } } void FtdiDevice::FtdiClose() { // close libftdi USB device if( (ftdiStatus = ftdi_usb_close(&ftdic)) < 0 ) { //fprintf(stderr, "ftdi_usb_close failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // Free libftdi USB device lists ftdi_list_free(&Buffer[0].devlist); ftdi_list_free(&Buffer[1].devlist); // deinitialize ftdi_context ftdi_deinit(&ftdic); QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); } void FtdiDevice::FindOpen() { QngStatus::Instance().SetStatus(QNG_S_OK); // Set Status to OK int ret=0; // # of devices returned status int num_devs=0; // number of FTDI devices found int i=0; // iterator for number of devices ftdiStatus = 0; // libftdi return value status // Set VID/PID Parameters for search Buffer[0].VID = 0x0403; // QNG Model R2000KU VendorID (VID) Buffer[0].PID = 0x6001; // QNG Model R2000KU ProductID (PID) Buffer[1].VID = 0x0403; // Other QNG Device VID Buffer[1].PID = 0x6014; // Other QNG Device PID // Initialize Main context structure for all libftdi functions if (ftdi_init(&ftdic) < 0) { //fprintf(stderr, "ftdi_init failed\n"); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // Find all connected QNG devices with PIDs 6001 and 6014 for (int j=0; j<2; j++) { if ((ret = ftdi_usb_find_all(&ftdic, &Buffer[j].devlist, Buffer[j].VID, Buffer[j].PID)) < 0) { //fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } num_devs = num_devs + ret; // increment device count } if (num_devs == 0) { // if no devices found, quit QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); return; } struct QNGparam QNG[num_devs]; // Init QNGparam structure i = 0; // initialize iterator // get devices' parameters for (int k=0; k<2; k++) { for (Buffer[k].curdev = Buffer[k].devlist; Buffer[k].curdev != NULL; i++) { //printf("Checking device: %d\n", i+1); // testing purposes if ((ftdiStatus = ftdi_usb_get_strings(&ftdic, Buffer[k].curdev->dev, QNG[i].manufacturer, 128, QNG[i].description, 128, QNG[i].serialnumber, 9)) < 0) { //fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } Buffer[k].curdev = Buffer[k].curdev->next; // increment next device list } } // Open First available QNG Model R2000KU with Prefix "QWR2" for (int j=0; j 0) { // Clears the write buffer on the chip. if ((ftdiStatus = ftdi_usb_purge_tx_buffer(&ftdic)) < 0 ) { //fprintf(stderr, "ftdi_usb_purge_tx_buffer failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } FtdiSendCommand(FTDIDEVICE_READ_SERIAL_COMMAND_); // Send Read Delimiter Command internalSerialNum_[1] = serialNumCheck[1] + 1; FtdiUncheckedRead(internalSerialNum_, 6); if (memcmp(serialNumCheck, internalSerialNum_, 6) == 0) break; memcpy(serialNumCheck, internalSerialNum_, 6); attempt--; } if (attempt <= 0) { QngStatus::Instance().SetStatus(QNG_E_DEVICE_NOT_OPENED); return; } // write out start word to physically start device FtdiSendCommand(FTDIDEVICE_START_COMMAND_); FtdiSendCommand(FTDIDEVICE_TEST_CLEAR_STATS_FLAG_); // clear internal Bad Stats flag usleep(10*1000); // first 4-5 bits produced from device are invalid (always zero); discard first byte uint8_t discardByte; FtdiRead(&discardByte, 1); // fill normU1, so immediate calls to GetNormal will be correct uint64_t uint48 = 0; FtdiRead(&uint48, 6); normU1_ = Uint48ToUniform(uint48); normU1_ += FTDIDEVICE_HALF_OF_UNIFORM_LSB_; haveNormU1_ = true; } void FtdiDevice::FtdiRead(void* receiveBuffer, int bytesRequested) { QngStatus::Instance().SetStatus(QNG_S_OK); // Set Status to OK // Read random bytes Requested. Bytes are stored as unsigned character ftdiStatus = ftdi_read_data(&ftdic, (unsigned char*)receiveBuffer, bytesRequested); if (ftdiStatus < 0) { //fprintf(stderr, "ftdi_read_data failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); } else if (ftdiStatus != bytesRequested) { QngStatus::Instance().SetStatus(QNG_E_IO_TIMEOUT); CheckTestStatsStatus(); } } // use FtdiRead, this read does not check test status on failure // only the test status function uses this to prevent an infinite callback loop void FtdiDevice::FtdiUncheckedRead(void* receiveBuffer, int bytesRequested) { QngStatus::Instance().SetStatus(QNG_S_OK); // Set Status to OK // Read random bytes Requested. Bytes are stored as unsigned character ftdiStatus = ftdi_read_data(&ftdic, (unsigned char*)receiveBuffer, bytesRequested); if (ftdiStatus < 0) { //fprintf(stderr, "ftdi_read_data failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); } else if (ftdiStatus != bytesRequested) { QngStatus::Instance().SetStatus(QNG_E_IO_TIMEOUT); } } void FtdiDevice::FtdiWrite(void* transmitBuffer, int bytesToTransmit) { QngStatus::Instance().SetStatus(QNG_S_OK); // Set Status to OK // Send Data to Device ftdiStatus = ftdi_write_data(&ftdic, (unsigned char*)transmitBuffer, bytesToTransmit); if (ftdiStatus < 0) { //fprintf(stderr, "ftdi_write_data failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); } else if (ftdiStatus != bytesToTransmit) { QngStatus::Instance().SetStatus(QNG_E_IO_TIMEOUT); } } void FtdiDevice::FtdiSendCommand(unsigned char command) { FtdiWrite(&command, 1); } void FtdiDevice::FtdiClearReceiveBuffer() { // Clears the write buffer on the chip. if ((ftdiStatus = ftdi_usb_purge_tx_buffer(&ftdic)) < 0 ) { //fprintf(stderr, "ftdi_usb_purge_tx_buffer failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // read data in queue unsigned char* purgeBuffer = new unsigned char[txchunksize]; FtdiUncheckedRead(purgeBuffer, txchunksize); delete [] purgeBuffer; } void FtdiDevice::FtdiClearBuffers() { // Purge RX/TX Buffers on the chip if ((ftdiStatus = ftdi_usb_purge_buffers(&ftdic)) < 0 ) { //fprintf(stderr, "ftdi_usb_purge_buffers failed: %d (%s)\n", ftdiStatus, ftdi_get_error_string(&ftdic)); QngStatus::Instance().SetStatus(QNG_E_IO_ERROR); return; } // read data in queue unsigned char* purgeBuffer = new unsigned char[txchunksize]; FtdiUncheckedRead(purgeBuffer, txchunksize); delete [] purgeBuffer; } void FtdiDevice::CheckTestStatsStatus() { // Stop Device FtdiSendCommand(FTDIDEVICE_STOP_COMMAND_); // look for the internal serial number (this is used as a delimiter) - try this 4 times int attempt = 4; unsigned char serialNumCheck[6]; while (attempt > 0) { FtdiClearReceiveBuffer(); // Clears the write buffer on the chip. FtdiSendCommand(FTDIDEVICE_READ_SERIAL_COMMAND_); // Send Read Delimiter Command FtdiUncheckedRead(serialNumCheck, 6); if (memcmp(serialNumCheck, internalSerialNum_, 6) == 0) break; attempt--; } if (attempt <= 0) { return; } // get test stats status uint32_t rngStatus = 0; FtdiSendCommand(FTDIDEVICE_TEST_STATUS_COMMAND_); FtdiUncheckedRead(&rngStatus, 4); if (rngStatus & FTDIDEVICE_TEST_BAD_STATS_MASK_) QngStatus::Instance().SetStatus(QNG_E_STATS_EXCEPTION); } double FtdiDevice::Uint48ToUniform(uint64_t uint48) { // copy 6 bytes into mantissa double uniform = (double)uint48; uniform /= 281474976710656.0; // 2^(6*8) return uniform; } float FtdiDevice::CalcEntropy(double p) { return (float)(-(p*log(p) + (1.0-p)*log(1.0-p)) / log(2.0)); } /*************************************************** QngStatus Class *******************************************/ /* Instance */ QngStatus& QngStatus::Instance() { static QngStatus instance; return instance; } /* Constructor */ QngStatus::QngStatus() : status_(QNG_E_DEVICE_NOT_OPENED) , statusString_("QNG device not found or already in use.") { } /* Destructor */ QngStatus::~QngStatus() { } long QngStatus::GetStatus() { return status_; } std::string& QngStatus::GetStatusString() { return statusString_; } long QngStatus::SetStatus(long newStatus) { if (status_ != QNG_S_OK) { if ((newStatus != QNG_S_OK) && (newStatus != QNG_E_STATS_EXCEPTION) && (newStatus != QNG_E_DEVICE_NOT_OPENED)) return status_; } status_ = newStatus; switch (status_) { case QNG_S_OK: statusString_ = "QNG device reports success."; break; case QNG_E_GENERAL_FAILURE: statusString_ = "QNG general error."; break; case QNG_E_IO_ERROR: statusString_ = "QNG I/O error."; break; case QNG_E_IO_TIMEOUT: statusString_ = "QNG I/O request has timed out."; break; case QNG_E_IO_ARRAY_OVERSIZED: statusString_ = "QNG read array size exceeds max size."; break; case QNG_E_DEVICE_NOT_OPENED: statusString_ = "QNG device not found or already in use."; break; case QNG_E_STATS_EXCEPTION: statusString_ = "QNG test statistics exception."; break; case QNG_E_STATS_UNSUPPORTED: statusString_ = "QNG stats not supported with this device."; break; default: status_ = QNG_E_GENERAL_FAILURE; statusString_ = "QNG general error."; } return status_; } entropybroker-2.9/ComScire_R2000KU/qwqng.hpp000066400000000000000000000173161305163522000206730ustar00rootroot00000000000000/* QWQNG_Linux Library Copyright (c) 2012, The Quantum World Corporation. All rights reserved. New BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __qwqng_hpp__ #define __qwqng_hpp__ #define FTDIDEVICE_ID_PREFIX_ "QWR" #define FTDIDEVICE_ID_DEVELOPMENT_ "D" #define FTDIDEVICE_TX_TIMEOUT_MILLIS_ 5000 #define FTDIDEVICE_READ_FRAME_SIZE_ 1024 #define FTDIDEVICE_START_COMMAND_ 0x96 #define FTDIDEVICE_STOP_COMMAND_ 0xE0 #define FTDIDEVICE_READ_SERIAL_COMMAND_ 0x60 #define FTDIDEVICE_TEST_STATUS_COMMAND_ 0xB0 #define FTDIDEVICE_TEST_FINAL_BASE_ 0xA0 #define FTDIDEVICE_TEST_CHANNELS_BASE_ 0x70 #define FTDIDEVICE_TEST_CLEAR_STATS_FLAG_ 0xC0 #define FTDIDEVICE_RNG_OUTPUT_ENABLED_MASK_ 0X0001 #define FTDIDEVICE_USB_STREAMING_MASK_ 0X0002 #define FTDIDEVICE_TEST_BAD_STATS_MASK_ 0x0004 #define FTDIDEVICE_CLIENT_CONNECTED_MASK_ 0X0008 #define FTDIDEVICE_MAX_ARRAY_SIZE_ 8192 #define FTDIDEVICE_HALF_OF_UNIFORM_LSB_ 1.7763568394002505e-15 #define FTDIDEVICE_2_PI_ 6.283185307179586 // Custom QNG Status messages // // MessageId: QNG_S_OK // MessageText: QNG device reports success. // #define QNG_S_OK 0x00044400L // // MessageId: QNG_E_GENERAL_FAILURE // MessageText: QNG general error. // #define QNG_E_GENERAL_FAILURE 0x80044401L // // MessageId: QNG_E_IO_ERROR // MessageText: QNG I/O error. // #define QNG_E_IO_ERROR 0x80044402L // // MessageId: QNG_E_IO_TIMEOUT // MessageText: QNG I/O request has timed out. // #define QNG_E_IO_TIMEOUT 0x80044403L // // MessageId: QNG_E_IO_ARRAY_OVERSIZED // MessageText: QNG read array size exceeds max size. // #define QNG_E_IO_ARRAY_OVERSIZED 0x80044404L // // MessageId: QNG_E_STATS_EXCEPTION // MessageText: QNG test statistics exception. // #define QNG_E_STATS_EXCEPTION 0x80044406L // // MessageId: QNG_E_STATS_UNSUPPORTED // MessageText: QNG stats not supported this device. // #define QNG_E_STATS_UNSUPPORTED 0x80044407L // // MessageId: QNG_E_DEVICE_NOT_OPENED // MessageText: QNG device not found or already in use. // #define QNG_E_DEVICE_NOT_OPENED 0x8004440AL // // MessageId: S_OK // MessageText: No error occurred. // #define S_OK 0x00000000L #include "stdint.h" #include #include #include #include #include #include #include /* Forward Declaration */ class FtdiDevice; class IDevice; class QngStatus; class QWQNG { public: /* Construct Indirectly */ static QWQNG* Instance(); /* Public Destructor */ ~QWQNG(); protected: /* Pointer to Class IDevice */ IDevice* pDevice; public: /* Properties */ char* statusString_; char* devId_; /* Device Manipulators */ char* StatusString(); char* DeviceID(); int RandInt32(long* pVal); int RandUniform(double* pVal); int RandNormal(double *pVal); int RandBytes(char* pval, long length); int Clear(); int Reset(); int RuntimeInfo(float* pVal); private: /* Private Constructor */ QWQNG(); /* Copy constructor is private */ QWQNG(QWQNG const&){}; /* Assignment operator is private */ QWQNG& operator=(QWQNG const&){}; /* Instance private constructor variable */ static QWQNG* _instance; }; class IDevice { private: /* property */ std::string deviceId_; public: /* Functions */ virtual void Open() = 0; virtual void Close() = 0; virtual void Clear() = 0; virtual void Reset() = 0; virtual void GetBytes(char* bytes, int bytesRequested) = 0; virtual void GetInt32(int32_t* int32) = 0; virtual void GetUniform(double* uniform) = 0; virtual void GetNormal(double* normal) = 0; virtual void GetRuntimeInfo(float* testData) = 0; virtual std::string& GetDeviceId() { return deviceId_; } virtual void SetDeviceId(std::string deviceId) { deviceId_ = deviceId; } }; class FtdiDevice : IDevice { private: /* Main context structure for all libftdi functions */ struct ftdi_context ftdic; /* Structure for Finding Multiple FTDI Devices */ struct QNGdev { struct ftdi_device_list *devlist, *curdev; int VID; int PID; }; struct QNGdev Buffer[2]; // Init QNGdev Structure /* Structure for Connected FTDI Devices' Parameters ( Initialize in FindOpen() ) */ struct QNGparam { char manufacturer[128], description[128], serialnumber[9]; }; /* Properties */ char serialInfo[9]; char descInfo[128]; char manuInfo[128]; int devPID; int devVID; int txchunksize; int rxchunksize; int ftdiStatus; unsigned char internalSerialNum_[6]; bool haveNormU1_; double normU1_; double normalConjugate_; public: /* Constructor, Destructor */ FtdiDevice(); ~FtdiDevice(); /* Functions */ virtual void Open(); virtual void Close(); virtual void Clear(); virtual void Reset(); virtual void GetBytes(char* bytes, int bytesRequested); virtual void GetInt32(int32_t* int32); virtual void GetUniform(double* uniform); virtual void GetNormal(double* normal); virtual void GetRuntimeInfo(float* runtimeInfo); private: /* Functions */ void FtdiClose(); void FindOpen(); void Initialize(); void FtdiRead(void* receiveBuffer, int bytesRequested); void FtdiUncheckedRead(void* receiveBuffer, int bytesRequested); void FtdiWrite(void* transmitBuffer, int bytesToTransmit); void FtdiSendCommand(unsigned char command); void FtdiClearReceiveBuffer(); void FtdiClearBuffers(); void CheckTestStatsStatus(); double Uint48ToUniform(uint64_t uint48); float CalcEntropy(double p); }; class QngStatus { public: /* Construct Indirectly */ static QngStatus& Instance(); /* Functions */ long GetStatus(); std::string& GetStatusString(); long SetStatus(long newStatus); private: /* Private Constructor */ QngStatus(); /* Copy constructor is private */ QngStatus(QngStatus const&) {}; /* Assignment operator is private */ QngStatus& operator=(QngStatus const&) {}; /* Private Destructor */ ~QngStatus(); private: /* properties */ long status_; std::string statusString_; }; #endif entropybroker-2.9/Makefile000066400000000000000000000345001305163522000157300ustar00rootroot00000000000000include version -include makefile.inc PREFIX=/usr/local/entropybroker BIN=$(PREFIX)/bin ETC=$(PREFIX)/etc VAR=$(PREFIX)/var CACHE=$(VAR)/cache PID=$(VAR)/run MAN=$(PREFIX)/share/man WEB=$(PREFIX)/share/eb/web DOC=$(PREFIX)/doc FONT=/usr/share/fonts/truetype/freefont/FreeMono.ttf CXX=g++ DEBUG= # -pg #-DHELGRIND #-DCRYPTO_DEBUG #-D_DEBUG #-fprofile-arcs -ftest-coverage # -pg LINT=-Wshadow -Wall # -W -Wconversion -Wwrite-strings -Wunused CXXFLAGS+=-O3 -ggdb -DVERSION=\"${VERSION}\" $(LINT) $(DEBUG) -DCONFIG=\"${ETC}/entropy_broker.conf\" -DCACHE_DIR=\"${CACHE}\" -DPID_DIR=\"${PID}\" -DVAR_DIR=\"${VAR}\" -DWEB_DIR=\"${WEB}\" -DFONT=\"${FONT}\" -rdynamic $(PCSC_CFLAGS) LDFLAGS+=$(DEBUG) -lrt -lz -lutil -rdynamic -lcryptopp -pthread ifeq ($(TFO),yes) CXXFLAGS+=-DTCP_TFO endif all: @echo targets: @echo ------- @echo All targets \(except from 'plot'\) require the Crypto++ libraries. @echo @echo entropy_broker @echo eb_server_audio requires libasound2-dev, linux only @echo eb_server_timers @echo eb_server_v4l requires linux only @echo eb_server_stream @echo eb_server_egd @echo eb_server_push_file @echo eb_server_ext_proc @echo eb_server_usb requires libusb-1.0-0-dev @echo eb_server_linux_kernel linux only @echo eb_server_Araneus_Alea linux only @echo eb_client_linux_kernel linux only @echo eb_client_file @echo eb_client_kernel_generic @echo eb_client_egd @echo eb_server_ComScire_R2000KU requires libftdi-dev @echo eb_server_QNG_PQ4000KU @echo eb_proxy_knuth_m @echo eb_proxy_knuth_b @echo eb_server_cycle_count linux only @echo eb_server_smartcard requires libpcsclite-dev @echo plot requires libpng-dev @echo @echo to build all daemons and processes invoke: @echo make everything @echo @echo to install all daemons etc. under $(PREFIX) invoke: @echo make install @echo @echo to install the redhat startup-scripts, invoke: @echo make install_redhat_init @echo @echo \*\*\*\*\* you need to run ./configure first \*\*\*\*\* @echo BINARIES=entropy_broker eb_server_timers eb_server_v4l eb_server_stream eb_client_linux_kernel eb_server_egd eb_client_egd eb_server_linux_kernel eb_client_file eb_server_push_file eb_server_ext_proc eb_proxy_knuth_m eb_proxy_knuth_b eb_server_cycle_count eb_server_Araneus_Alea ${B2} OBJSeb=auth.o pools.o statistics_user.o statistics_global.o statistics.o config.o error.o fips140.o kernel_prng_rw.o log.o protocol.o main.o math.o pool.o scc.o signals.o utils.o my_pty.o kernel_prng_io.o hasher.o stirrer.o hasher_sha512.o stirrer_blowfish.o stirrer_aes.o hasher_md5.o hasher_ripemd160.o stirrer_3des.o stirrer_camellia.o hasher_whirlpool.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o pool_crypto.o http_bundle.o http_server.o http_file_root.o http_file_404.o http_file_version.o http_file.o http_file_file.o http_file_stats.o http_file_logfile.o web_server.o data_store_int.o data_logger.o graph.o http_file_graph_data_logger.o statistics_log.o http_file_users.o hc_protocol.o handle_client.o OBJSsa=server_audio.o error.o utils.o kernel_prng_rw.o log.o protocol.o server_utils.o auth.o my_pty.o kernel_prng_io.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSst=server_timers.o log.o utils.o error.o kernel_prng_rw.o protocol.o server_utils.o auth.o my_pty.o kernel_prng_io.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSsv=server_v4l.o error.o log.o protocol.o kernel_prng_rw.o utils.o server_utils.o auth.o my_pty.o kernel_prng_io.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSss=server_stream.o error.o log.o protocol.o kernel_prng_rw.o utils.o server_utils.o auth.o my_pty.o kernel_prng_io.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSse=server_egd.o error.o log.o protocol.o utils.o server_utils.o auth.o my_pty.o kernel_prng_io.o kernel_prng_rw.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSclk=client_linux_kernel.o error.o kernel_prng_io.o kernel_prng_rw.o log.o protocol.o utils.o auth.o my_pty.o math.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJScle=client_egd.o error.o log.o kernel_prng_io.o kernel_prng_rw.o math.o protocol.o utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSsk=server_linux_kernel.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJScf=client_file.o error.o log.o kernel_prng_io.o kernel_prng_rw.o math.o protocol.o utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSpf=server_push_file.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSep=server_ext_proc.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSsu=server_usb.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJScsr2000ku=server_ComScire_R2000KU.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJScsrqwqng=server_qwqng.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSpkm=proxy_knuth_m.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSpkb=proxy_knuth_b.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSscc=server_cycle_count.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSpicc=server_smartcard.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o OBJSsal=server_Araneus_Alea.o utils.o kernel_prng_rw.o kernel_prng_io.o log.o error.o protocol.o server_utils.o auth.o my_pty.o users.o random_source.o encrypt_stream.o encrypt_stream_blowfish.o hasher.o hasher_md5.o hasher_ripemd160.o hasher_sha512.o hasher_whirlpool.o encrypt_stream_aes.o encrypt_stream_3des.o encrypt_stream_camellia.o statistics.o statistics_global.o statistics_user.o everything: $(BINARIES) makefile.inc makefile.inc: ./configure entropy_broker: $(OBJSeb) $(CXX) $(LINT) $(OBJSeb) $(LDFLAGS) -lpng -lgd -o entropy_broker eb_server_Araneus_Alea: $(OBJSsal) $(CXX) $(LINT) $(OBJSsal) $(LDFLAGS) -lusb-1.0 -o eb_server_Araneus_Alea eb_server_audio: $(OBJSsa) $(CXX) $(LINT) $(OBJSsa) $(LDFLAGS) -lasound -o eb_server_audio eb_server_timers: $(OBJSst) $(CXX) $(LINT) $(OBJSst) $(LDFLAGS) -pthread -o eb_server_timers eb_server_v4l: $(OBJSsv) $(CXX) $(LINT) $(OBJSsv) $(LDFLAGS) -o eb_server_v4l eb_server_stream: $(OBJSss) $(CXX) $(LINT) $(OBJSss) $(LDFLAGS) -o eb_server_stream eb_server_egd: $(OBJSse) $(CXX) $(LINT) $(OBJSse) $(LDFLAGS) -o eb_server_egd eb_client_egd: $(OBJScle) $(CXX) $(LINT) $(OBJScle) $(LDFLAGS) -o eb_client_egd eb_client_linux_kernel: $(OBJSclk) $(CXX) $(LINT) $(OBJSclk) $(LDFLAGS) -o eb_client_linux_kernel eb_server_linux_kernel: $(OBJSsk) $(CXX) $(LINT) $(OBJSsk) $(LDFLAGS) -o eb_server_linux_kernel eb_client_file: $(OBJScf) $(CXX) $(LINT) $(OBJScf) $(LDFLAGS) -o eb_client_file eb_client_kernel_generic: eb_client_file eb_server_push_file: $(OBJSpf) $(CXX) $(LINT) $(OBJSpf) $(LDFLAGS) -o eb_server_push_file eb_server_ext_proc: $(OBJSep) $(CXX) $(LINT) $(OBJSep) $(LDFLAGS) -o eb_server_ext_proc eb_server_usb: $(OBJSsu) $(CXX) $(LINT) $(OBJSsu) $(LDFLAGS) -lusb-1.0 -o eb_server_usb eb_server_ComScire_R2000KU: $(OBJScsr2000ku) $(CXX) $(LINT) $(OBJScsr2000ku) ComScire_R2000KU/qwqng.cpp $(LDFLAGS) -lftdi -o eb_server_ComScire_R2000KU eb_server_QNG_PQ4000KU: $(OBJScsrqwqng) $(CXX) $(LINT) $(OBJScsrqwqng) $(LDFLAGS) `pkg-config --libs libqwqng` -o eb_server_QNG_PQ4000KU eb_proxy_knuth_m: $(OBJSpkm) $(CXX) $(LINT) $(OBJSpkm) $(LDFLAGS) -o eb_proxy_knuth_m eb_proxy_knuth_b: $(OBJSpkb) $(CXX) $(LINT) $(OBJSpkb) $(LDFLAGS) -o eb_proxy_knuth_b eb_server_cycle_count: $(OBJSscc) $(CXX) $(LINT) $(OBJSscc) $(LDFLAGS) -o eb_server_cycle_count eb_server_smartcard: $(OBJSpicc) $(CXX) $(LINT) $(OBJSpicc) $(LDFLAGS) `pkg-config --libs libpcsclite` -o eb_server_smartcard plot: plot.o $(CXX) $(LINT) plot.o $(LDFLAGS) -lpng -o plot install: mkdir -p $(BIN) $(ETC) $(VAR) $(PID) $(CACHE) for file in $(BINARIES) ; do \ test -e $$file && cp $$file $(BIN) ; \ test -e $$file || echo Skipping $$file which was not build ; \ done test -e $(BIN)/eb_client_file && \ (test -e $(BIN)/eb_client_kernel_generic || \ ln $(BIN)/eb_client_file $(BIN)/eb_client_kernel_generic) test -e $(ETC)/entropy_broker.conf || cp entropy_broker.conf $(ETC) test -e $(ETC)/entropy_broker.conf && cp entropy_broker.conf $(ETC)/entropy_broker.conf.dist test -e $(ETC)/users.txt || (cp users.txt $(ETC) ; chmod 600 $(ETC)/users.txt) mkdir -p $(MAN)/man8 cp doc/man/* $(MAN)/man8 mkdir -p $(DOC)/entropy_broker cp *txt license.* $(DOC)/entropy_broker mkdir -p $(WEB) cp web/* $(WEB) install_redhat_init: cp redhat/* /etc/init.d clean: rm -rf $(OBJSeb) $(OBJSsa) $(OBJSst) $(OBJSsv) $(OBJSss)$(OBJSse) $(OBJSclk) $(OBJSte) $(OBJSsk) $(OBJScf) $(OBJSpf) $(OBJSep) $(OBJSsu) $(OBJScsr2000ku) $(OBJScle) $(OBJSse) $(OBJSpkm) $(OBJSpkb) $(OBJSscc) $(OBJSpicc) $(OBJSsal) $(OBJScsrqwqng) plot.o core *.da *.gcov *.bb* $(BINARIES) cov-int distclean: clean rm -f makefile.inc package: svn update mkdir eb-$(VERSION) eb-$(VERSION)/ComScire_R2000KU cp eb.spec version configure *.cpp *.h entropy_broker.conf Makefile bin_to_values.pl do_fft.sh auth.txt network_protocol.txt users.txt readme.txt design.txt interfacing.txt license.* eb-$(VERSION) cp ComScire_R2000KU/*.[ch]pp ComScire_R2000KU/LICENSE eb-$(VERSION)/ComScire_R2000KU tar cf - doc --exclude=.svn | tar xvf - -C eb-$(VERSION) tar cf - redhat --exclude=.svn | tar xvf - -C eb-$(VERSION) tar cf - web --exclude=.svn | tar xvf - -C eb-$(VERSION) tar czf eb-$(VERSION).tgz eb-$(VERSION) rm -rf eb-$(VERSION) # cp network_protocol.txt design.txt ~/site/entropybroker/ coverity: clean rm -rf cov-int cov-build --dir cov-int make everything tar vczf ~/site/coverity/EntropyBroker.tgz README cov-int/ putsite -q /home/folkert/.coverity-eb.sh check: cppcheck -v --enable=all --std=c++11 --inconclusive -I. . 2> err.txt entropybroker-2.9/README000066400000000000000000000000711305163522000151440ustar00rootroot00000000000000Folkert van Heusden folkert@vanheusden.com EntropyBroker entropybroker-2.9/README.md000066400000000000000000000011261305163522000155450ustar00rootroot00000000000000entropybroker ============= Entropy Broker is an infrastructure for distributing cryptographically secure random numbers (entropy data) from one or more servers to one or more clients. http://www.vanheusden.com/entropybroker/ [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=flok&url=https://github.com/flok99/entropybroker&title=entropybroker&language=&tags=github&category=software) [![Support the development of this project](https://pledgie.com/campaigns/28612.png?skin_name=chrome)](https://pledgie.com/campaigns/28612) entropybroker-2.9/auth.cpp000066400000000000000000000246151305163522000157430ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "scc.h" #include "fips140.h" #include "encrypt_stream.h" #include "hasher.h" #include "hasher_type.h" #include "stirrer.h" #include "stirrer_type.h" #include "protocol.h" #include "math.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" int auth_eb_user(int fd, int to, users *user_map, std::string & username_out, std::string & password, long long unsigned int *challenge, bool is_proxy_auth, bool *is_server_in, std::string & type, random_source *rs, encrypt_stream *es, hasher *mac, std::string handshake_hash, unsigned int max_get_put_size, statistics_global *sg) { std::string host = get_endpoint_name(fd); const char *ts = is_proxy_auth ? "Proxy-auth" : "Connection"; /* Inform the client about the hash-functions and ciphers that are used */ std::string mac_data = mac -> get_name(); std::string cipher_data = es -> get_name(); if (send_length_data(fd, handshake_hash.c_str(), handshake_hash.size(), to) == -1) { dolog(LOG_INFO, "%s failure sending handshake hash (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } if (send_length_data(fd, mac_data.c_str(), mac_data.size(), to) == -1) { dolog(LOG_INFO, "%s failure sending data MAC (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } if (send_length_data(fd, cipher_data.c_str(), cipher_data.size(), to) == -1) { dolog(LOG_INFO, "%s failure sending data cipher (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } ///// /* send random with which will be concatenated to the password and then hashed */ long long unsigned int rnd = 9; rs -> get(reinterpret_cast(&rnd), sizeof rnd); char rnd_str[128]; unsigned int rnd_str_size = snprintf(rnd_str, sizeof rnd_str, "%llu", rnd); *challenge = rnd; if (rnd_str_size == 0) error_exit("INTERNAL ERROR: random string is 0 characters!"); if (send_length_data(fd, rnd_str, rnd_str_size, to) == -1) { dolog(LOG_INFO, "%s failure sending random (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } ///// /* receive username */ char *username = NULL; unsigned int username_length = 0; if (recv_length_data(fd, &username, &username_length, to) == -1) { dolog(LOG_INFO, "%s receiving username (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } dolog(LOG_INFO, "User '%s'[len: %d] requesting access (fd: %d, host: %s)", username, username_length, fd, host.c_str()); if (username == NULL || username[0] == 0x00 || username_length == 0) { dolog(LOG_WARNING, "Empty username"); sg -> put_history_log(HL_LOGIN_OTHER, host, "", "", get_ts(), 0, "empty username"); free(username); return -1; } username_out.assign(username); bool user_known = user_map -> get_password(username_out, password); if (!user_known) { dolog(LOG_WARNING, "User '%s' not known, (fd: %d, host: %s)", username, fd, host.c_str()); sg -> put_history_log(HL_LOGIN_USER_FAIL, host, "", username_out, get_ts(), 0, "username not known"); user_known = false; } free(username); ///// /* receive hashed password */ hasher *hh = hasher::select_hasher(handshake_hash); int hash_len = hh -> get_hash_size(); char hash_cmp_str[256], *hash_cmp = reinterpret_cast(malloc(hash_len)), *hash_in = reinterpret_cast(malloc(hash_len)); int hash_cmp_str_len = snprintf(hash_cmp_str, sizeof hash_cmp_str, "%s %s", rnd_str, password.c_str()); if (!hash_cmp || !hash_in) error_exit("out of memory"); hh -> do_hash((unsigned char *)hash_cmp_str, hash_cmp_str_len, reinterpret_cast(hash_cmp)); if (READ_TO(fd, hash_in, hash_len, to) != hash_len) { dolog(LOG_INFO, "%s receiving hash failed (fd: %d, host: %s)", ts, fd, host.c_str()); free(hash_cmp); free(hash_in); delete hh; return -1; } if (!user_known || memcmp(hash_cmp, hash_in, hash_len) != 0) { dolog(LOG_INFO, "%s authentication failed! (fd: %d, host: %s)", ts, fd, host.c_str()); free(hash_cmp); free(hash_in); delete hh; sg -> put_history_log(HL_LOGIN_PW_FAIL, host, "", username_out, get_ts(), 0, "hash mismatch"); return -1; } free(hash_cmp); free(hash_in); delete hh; ///// /* receive a byte which indicates if the other end is a client or a server */ char is_server = 0; if (READ_TO(fd, &is_server, 1, to) != 1) { dolog(LOG_INFO, "%s failed retrieving server/client (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } *is_server_in = is_server ? true : false; ///// /* receive a string which describes the other send */ char *type_in = NULL; unsigned int type_in_size = 0; if (recv_length_data(fd, &type_in, &type_in_size, to) == -1) { dolog(LOG_INFO, "%s failed retrieving type (fd: %d, host: %s)", ts, fd, host.c_str()); return -1; } type = std::string(type_in); free(type_in); ///// /* how many bits can be put/get in one go */ unsigned char max_get_put_size_bytes[4]; uint_to_uchar(max_get_put_size, max_get_put_size_bytes); if (WRITE_TO(fd, max_get_put_size_bytes, 4, to) == -1) { dolog(LOG_INFO, "Connection closed (fd: %d, host: %s)", fd, host.c_str()); return -1; } dolog(LOG_INFO, "%s authentication ok (fd: %d, host: %s)", ts, fd, host.c_str()); double now_ts = get_ts(); user_map -> set_last_login(username_out, now_ts); sg -> put_history_log(HL_LOGIN_OK, host, type, username_out, now_ts, 0, ""); return 0; } int auth_eb(int fd, int to, users *user_map, std::string & username, std::string & password, long long unsigned int *challenge, bool *is_server_in, std::string & type, random_source *rs, encrypt_stream *enc, hasher *mac, std::string handshake_hash, unsigned int max_get_put_size, statistics_global *sg) { char prot_ver[4 + 1] = { 0 }; snprintf(prot_ver, sizeof prot_ver, "%04d", PROTOCOL_VERSION); if (WRITE_TO(fd, prot_ver, 4, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (0)", fd); return -1; } return auth_eb_user(fd, to, user_map, username, password, challenge, false, is_server_in, type, rs, enc, mac, handshake_hash, max_get_put_size, sg); } bool get_auth_from_file(char *filename, std::string & username, std::string & password) { struct stat ss; if (stat(filename, &ss) == -1) error_exit("stat(%s) failed", filename); if (ss.st_mode & (S_IRWXG | S_IRWXO)) error_exit("file %s must only readable by its owner", filename); std::ifstream fh(filename); if (!fh.is_open()) error_exit("Cannot open %s", filename); std::string line; std::getline(fh, line); username.assign(line); std::getline(fh, line); password.assign(line); fh.close(); return true; } int auth_client_server_user(int fd, int to, std::string & username, std::string & password, long long unsigned int *challenge, bool is_server, std::string type, std::string & cd, std::string & mh, unsigned int *max_get_put_size) { char *hash_handshake = NULL; unsigned int hash_handshake_size = 0; if (recv_length_data(fd, &hash_handshake, &hash_handshake_size, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (t1)", fd); return -1; } char *mac_data = NULL; unsigned int mac_data_size = 0; if (recv_length_data(fd, &mac_data, &mac_data_size, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (t2)", fd); return -1; } mh.assign(mac_data); char *cipher_data = NULL; unsigned int cipher_data_size = 0; if (recv_length_data(fd, &cipher_data, &cipher_data_size, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (t3)", fd); return -1; } cd.assign(cipher_data); dolog(LOG_DEBUG, "handshake hash: %s, data mac: %s, data cipher: %s", hash_handshake, mac_data, cipher_data); char *rnd_str = NULL; unsigned int rnd_str_size = 0; if (recv_length_data(fd, &rnd_str, &rnd_str_size, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (a1)", fd); return -1; } if (rnd_str_size == 0) error_exit("INTERNAL ERROR: random string is 0 characters!"); char *dummy = NULL; *challenge = strtoull(rnd_str, &dummy, 10); unsigned int username_length = username.length(); if (send_length_data(fd, const_cast(username.c_str()), username_length, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (a2)", fd); free(rnd_str); return -1; } hasher *hh = hasher::select_hasher(hash_handshake); int hash_len = hh -> get_hash_size(); char hash_cmp_str[256], *hash_cmp = reinterpret_cast(malloc(hash_len)), *hash_in = reinterpret_cast(malloc(hash_len)); int hash_cmp_str_len = snprintf(hash_cmp_str, sizeof hash_cmp_str, "%s %s", rnd_str, password.c_str()); free(rnd_str); if (!hash_cmp || !hash_in) error_exit("out of memory"); hh -> do_hash((unsigned char *)hash_cmp_str, hash_cmp_str_len, reinterpret_cast(hash_cmp)); if (WRITE_TO(fd, hash_cmp, hash_len, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (a3)", fd); free(hash_cmp); free(hash_in); delete hh; return -1; } free(hash_cmp); free(hash_in); delete hh; char is_server_byte = is_server ? 1 : 0; if (WRITE_TO(fd, &is_server_byte, 1, to) != 1) { dolog(LOG_INFO, "Connection for fd %d closed (m1)", fd); return -1; } unsigned int type_length = type.length(); if (send_length_data(fd, const_cast(type.c_str()), type_length, to) == -1) { dolog(LOG_INFO, "Connection for fd %d closed (m2)", fd); return -1; } unsigned char max_get_put_size_bytes[4]; if (READ_TO(fd, max_get_put_size_bytes, 4, to) != 4) { dolog(LOG_INFO, "Connection for fd %d closed (m3)", fd); return -1; } *max_get_put_size = uchar_to_uint(max_get_put_size_bytes); return 0; } int auth_client_server(int fd, int to, std::string & username, std::string & password, long long unsigned int *challenge, bool is_server, std::string type, std::string & cd, std::string &mh, unsigned int *max_get_put_size) { char prot_ver[4 + 1] = { 0 }; if (READ_TO(fd, prot_ver, 4, to) != 4) { dolog(LOG_INFO, "Connection for fd %d closed (0)", fd); return -1; } int eb_ver = atoi(prot_ver); if (eb_ver != PROTOCOL_VERSION) error_exit("Broker server has unsupported protocol version %d! (expecting %d)", eb_ver, PROTOCOL_VERSION); return auth_client_server_user(fd, to, username, password, challenge, is_server, type, cd, mh, max_get_put_size); } entropybroker-2.9/auth.h000066400000000000000000000022541305163522000154030ustar00rootroot00000000000000int auth_eb_user(int fd, int to, users *user_map, std::string & username, std::string & password, long long unsigned int *challenge, bool is_proxy_auth, bool *is_server_in, std::string & type, random_source *rs, encrypt_stream *es, hasher *mac_hasher, std::string hash_hasher, unsigned int max_get_put_size, statistics_global *s); int auth_eb(int fd, int to, users *user_map, std::string & username, std::string & password, long long unsigned int *challenge, bool *is_server_in, std::string & type, random_source *rand_src, encrypt_stream *enc, hasher *mac, std::string handshake_hash, unsigned int max_get_put_size, statistics_global *s); int auth_client_server(int fd, int to, std::string & username, std::string & password, long long unsigned int *challenge, bool is_server, std::string type, std::string & cd, std::string & mh, unsigned int *max_get_put_size_bytes); int auth_client_server_user(int fd, int to, std::string & username, std::string & password, long long unsigned int *challenge, bool is_server, std::string type, std::string & cd, std::string & mh, unsigned int *max_get_put_size_bytes); bool get_auth_from_file(char *filename, std::string & username, std::string & password); entropybroker-2.9/auth.txt000066400000000000000000000000421305163522000157640ustar00rootroot00000000000000joe_user my_password1234123492348 entropybroker-2.9/bin_to_values.pl000077500000000000000000000004011305163522000174520ustar00rootroot00000000000000#! /usr/bin/perl -w # $Revision$ open(FILE, "<" . $ARGV[0]) or die 'Cannot open file '.$ARGV[0]; binmode(FILE); $buffer = ''; while(!eof(FILE)) { read(FILE, $buffer, 4096); foreach(split(//, $buffer)) { printf("%d\n", ord($_)); } } close(FILE); entropybroker-2.9/client_egd.cpp000066400000000000000000000201231305163522000170650ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "math.h" #include "protocol.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #include "kernel_prng_io.h" #define DEFAULT_COMM_TO 15 const char *pid_file = PID_DIR "/client_egd.pid"; const char *client_type = "client_egd " VERSION; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void egd_get__failure(int fd) { unsigned char none = 0; if (WRITE(fd, &none, 1) != 1) dolog(LOG_INFO, "short write on egd client (# bytes)"); } void egd_get(int fd, protocol *p, bool blocking) { unsigned char n_bytes_to_get; if (READ(fd, &n_bytes_to_get, 1) != 1) { dolog(LOG_INFO, "short read on EGD client"); return; } if (n_bytes_to_get == 0) { dolog(LOG_INFO, "client requesting 0 bytes"); return; } int n_bits_to_get = n_bytes_to_get * 8; dolog(LOG_INFO, "will get %d bits (%sblocking)", n_bits_to_get, blocking?"":"non-"); unsigned char *buffer = static_cast(malloc(n_bytes_to_get)); if (!buffer) error_exit("Out of memory"); lock_mem(buffer, n_bytes_to_get); int n_bytes = p -> request_bytes(buffer, n_bits_to_get, !blocking); if (n_bytes == 0) egd_get__failure(fd); else { unsigned char msg = std::min(255, n_bytes); if (!blocking && WRITE(fd, &msg, 1) != 1) dolog(LOG_INFO, "short write on egd client (# bytes)"); else if (WRITE(fd, buffer, msg) != msg) dolog(LOG_INFO, "short write on egd client (data)"); memset(buffer, 0x00, n_bytes); } unlock_mem(buffer, n_bytes); free(buffer); } void egd_entropy_count(int fd) { unsigned int count = 9999; unsigned char reply[4]; reply[0] = (count >> 24) & 255; reply[1] = (count >> 16) & 255; reply[2] = (count >> 8) & 255; reply[3] = count & 255; if (WRITE(fd, reply, 4) != 4) dolog(LOG_INFO, "short write on egd client"); } void egd_put(int fd, protocol *p) { unsigned char cmd[3]; if (READ(fd, cmd, 3) != 3) { dolog(LOG_INFO, "EGD_put short read (1)"); return; } int bit_cnt = (cmd[0] << 8) + cmd[1]; dolog(LOG_INFO, "EGD client puts %d bits of entropy", bit_cnt); unsigned char byte_cnt = cmd[2]; char buffer[256]; lock_mem(buffer, sizeof buffer); if (byte_cnt > 0 && READ(fd, buffer, byte_cnt) != byte_cnt) { dolog(LOG_INFO, "EGD_put short read (2)"); return; } (void)p -> message_transmit_entropy_data(reinterpret_cast(buffer), byte_cnt); memset(buffer, 0x00, sizeof buffer); unlock_mem(buffer, sizeof buffer); } void handle_client(int fd, protocol *p) { for(;!do_exit;) { unsigned char egd_msg; if (READ(fd, &egd_msg, 1, &do_exit) != 1) { dolog(LOG_INFO, "EGD client disconnected"); return; } if (egd_msg == 0) // get entropy count egd_entropy_count(fd); else if (egd_msg == 1) // get data, non blocking egd_get(fd, p, false); else if (egd_msg == 2) // get data, blocking egd_get(fd, p, true); else if (egd_msg == 3) // put data egd_put(fd, p); } } int open_unixdomain_socket(char *path, int nListen) { int len; struct sockaddr_un addr; int fd = -1; if (strlen(path) >= sizeof addr.sun_path) error_exit("Path %s too large (%d limit)", path, sizeof addr.sun_path); memset(&addr, 0x00, sizeof addr); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path); len = offsetof(struct sockaddr_un, sun_path) + strlen(path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) error_exit("socket creation failed"); if (bind(fd, (struct sockaddr *)&addr, len) == -1) error_exit("bind failed"); if (listen(fd, nListen) == -1) error_exit("listen failed"); return fd; } int open_tcp_socket(const char *adapter, int port, int nListen) { return start_listen(adapter, port, nListen); } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-d file egd unix domain socket\n"); printf("-t host egd tcp host to listen on\n"); printf("-T port egd tcp port to listen on\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } void start_child(int fd, bool do_not_fork, struct sockaddr *ca, std::vector *hosts, std::string username, std::string password) { if (fd != -1) { pid_t pid = 0; if (!do_not_fork) pid = fork(); if (pid == 0) { protocol *p = new protocol(hosts, username, password, false, client_type, DEFAULT_COMM_TO); handle_client(fd, p); delete p; if (!do_not_fork) exit(0); } else if (pid == -1) error_exit("failed to fork"); close(fd); } } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *uds = NULL; int u_listen_fd = -1, nListen = 5; std::string username, password; const char *egd_host = "0.0.0.0"; int egd_port = -1; int t_listen_fd = -1; std::vector hosts; int log_level = LOG_INFO; printf("eb_client_egd v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "t:T:hX:P:d:I:L:l:sn")) != -1) { switch(c) { case 't': egd_host = optarg; break; case 'T': egd_port = atoi(optarg); if (egd_port < 1) error_exit("-T requires a value >= 1"); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'd': uds = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (password.length() == 0 || username.length() == 0) error_exit("please set a non-empty username + password"); if (hosts.empty()) error_exit("no host to connect to selected"); if (!uds && egd_port == -1) error_exit("no path for the unix domain socket selected, also no tcp listen port selected"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (uds != NULL) u_listen_fd = open_unixdomain_socket(uds, nListen); if (egd_port != -1) t_listen_fd = open_tcp_socket(egd_host, egd_port, nListen); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); for(; !do_exit;) { fd_set a_fds; FD_ZERO(&a_fds); if (u_listen_fd != -1) FD_SET(u_listen_fd, &a_fds); if (t_listen_fd != -1) FD_SET(t_listen_fd, &a_fds); if (select(std::max(u_listen_fd, t_listen_fd) + 1, &a_fds, NULL, NULL, NULL) == -1) { if (errno != EINTR) error_exit("select() failed"); continue; } struct sockaddr addr; socklen_t addr_len = sizeof addr; if (u_listen_fd != -1 && FD_ISSET(u_listen_fd, &a_fds)) start_child(accept(u_listen_fd, &addr, &addr_len), do_not_fork, &addr, &hosts, username, password); if (t_listen_fd != -1 && FD_ISSET(t_listen_fd, &a_fds)) start_child(accept(t_listen_fd, &addr, &addr_len), do_not_fork, &addr, &hosts, username, password); } unlink(pid_file); dolog(LOG_INFO, "Finished"); return 0; } entropybroker-2.9/client_file.cpp000066400000000000000000000120521305163522000172470ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "math.h" #include "protocol.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #include "kernel_prng_io.h" #define DEFAULT_COMM_TO 15 const char *pid_file = PID_DIR "/client_file.pid"; const char *client_type = NULL; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(bool is_eb_client_file) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); if (is_eb_client_file) printf("-c count number of BYTES, 0=no limit\n"); if (is_eb_client_file) printf("-f file write bytes to \"file\"\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); if (!is_eb_client_file) { printf("-S time how long to sleep between each iteration\n"); printf("-b x how many BYTES to process each iteration\n"); } } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; int count = 0; const char *file = NULL; int block_size = 4096; int sleep_time = 0; char *prog = basename(strdup(argv[0])); std::string username, password; bool is_eb_client_file = strstr(prog, "eb_client_file") != NULL; std::vector hosts; int log_level = LOG_INFO; if (!is_eb_client_file) file = "/dev/random"; if (is_eb_client_file) client_type = "eb_client_file v" VERSION; else client_type = "eb_client_kernel_generic v" VERSION; printf("%s, (C) 2009-2015 by folkert@vanheusden.com\n", client_type); while((c = getopt(argc, argv, "b:S:hc:f:X:P:I:L:l:sn")) != -1) { switch(c) { case 'b': block_size = atoi(optarg); if (block_size < 1) error_exit("invalid block size"); break; case 'S': sleep_time = atoi(optarg); if (sleep_time < 1) error_exit("invalid sleep time"); break; case 'c': count = atoi(optarg); if (count <= 0) count = -1; break; case 'f': file = optarg; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(is_eb_client_file); return 0; default: help(is_eb_client_file); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("password + username cannot be empty"); if (hosts.empty()) error_exit("No host to connect to selected"); if (!file) error_exit("No file to write to selected"); if (count < 1) error_exit("Count must be >= 1"); (void)umask(0177); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); protocol *p = new protocol(&hosts, username, password, false, client_type, DEFAULT_COMM_TO); FILE *fh = fopen(file, "wb"); if (!fh) error_exit("Failed to create file %s", file); no_core(); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); unsigned char buffer[4096]; lock_mem(buffer, sizeof buffer); while((count > 0 || count == -1) && do_exit == false) { int n_bytes_to_get = std::min(block_size, std::min(count <= 0 ? 4096 : count, 4096)); int n_bits_to_get = n_bytes_to_get * 8; dolog(LOG_INFO, "will get %d bits", n_bits_to_get); int n_bytes = p -> request_bytes(buffer, n_bits_to_get, false, &do_exit); if (do_exit) break; if (count == -1) { } else if (n_bytes >= count) count = 0; else count -= n_bytes; if (fwrite(buffer, 1, n_bytes, fh) != (size_t)n_bytes) error_exit("Failed to write %d bytes to file", n_bytes); if (sleep_time > 0) sleep(sleep_time); } memset(buffer, 0x00, sizeof buffer); unlock_mem(buffer, sizeof buffer); fclose(fh); unlink(pid_file); delete p; dolog(LOG_INFO, "Finished"); return 0; } entropybroker-2.9/client_linux_kernel.cpp000066400000000000000000000130371305163522000210330ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "kernel_prng_io.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "math.h" #include "protocol.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #define DEFAULT_COMM_TO 15 const char *pid_file = PID_DIR "/client_linux_kernel.pid"; const char *client_type = "client_linux_kernel " VERSION; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-b x interval in which data will be seeded in a full(!) kernel entropy buffer (default is off)\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { int dev_random_fd = open(DEV_RANDOM, O_RDWR); int max_bits_in_kernel_rng = kernel_rng_get_max_entropy_count(); int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; std::string username, password; int interval = -1; std::vector hosts; int log_level = LOG_INFO; printf("eb_client_linux_kernel v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "b:hX:P:I:L:l:sn")) != -1) { switch(c) { case 'b': interval = atoi(optarg); if (interval < 1) error_exit("Interval must be > 0"); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty()) error_exit("no host to connect to selected"); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } protocol *p = new protocol(&hosts, username, password, false, client_type, DEFAULT_COMM_TO); (void)umask(0177); no_core(); write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); dolog(LOG_INFO, "started with %d bits in kernel rng", kernel_rng_get_entropy_count()); if (dev_random_fd == -1) error_exit("failed to open %s", DEV_RANDOM); bit_count_estimator bce(BCE_SHANNON); for(;!do_exit;) { struct timeval tv, *ptv = NULL; if (interval > 0) { tv.tv_sec = interval; tv.tv_usec = 0; ptv = &tv; } // wait for /dev/random te become writable which means the entropy- // level dropped below a certain threshold fd_set write_fd; FD_ZERO(&write_fd); FD_SET(dev_random_fd, &write_fd); dolog(LOG_DEBUG, "wait for low-event"); for(;!do_exit;) { int rc = select(dev_random_fd + 1, NULL, &write_fd, NULL, ptv); if (rc > 0) break; if (rc == 0 && interval> 0) break; if (errno != EINTR && errno != EAGAIN) error_exit("Select error: %m"); } if (do_exit) break; int n_bits_in_kernel_rng = kernel_rng_get_entropy_count(); dolog(LOG_DEBUG, "kernel rng bit count: %d", n_bits_in_kernel_rng); if (FD_ISSET(dev_random_fd, &write_fd) || interval > 0) { /* find out how many bits to add */ int n_bits_to_get = max_bits_in_kernel_rng - n_bits_in_kernel_rng; if (n_bits_to_get <= 0) { dolog(LOG_DEBUG, "number of bits to get <= 0: %d", n_bits_to_get); continue; } if (n_bits_to_get > 9999) n_bits_to_get = 9999; if (n_bits_to_get < 8) n_bits_to_get = 8; dolog(LOG_INFO, "%d bits left (%d max), will get %d bits", n_bits_in_kernel_rng, max_bits_in_kernel_rng, n_bits_to_get); int n_bytes_to_get = (n_bits_to_get + 7) / 8; unsigned char *buffer = static_cast(malloc(n_bytes_to_get)); if (!buffer) error_exit("out of memory allocating %d bytes", n_bytes_to_get); lock_mem(buffer, n_bytes_to_get); int n_bytes = p -> request_bytes(buffer, n_bits_to_get, false, &do_exit); if (do_exit) break; int is_n_bits = bce.get_bit_count(reinterpret_cast(buffer), n_bytes); int rc = kernel_rng_add_entropy(reinterpret_cast(buffer), n_bytes, is_n_bits); if (rc == -1) error_exit("error submiting entropy data to kernel"); dolog(LOG_DEBUG, "new entropy count: %d", kernel_rng_get_entropy_count()); memset(buffer, 0x00, n_bytes_to_get); unlock_mem(buffer, n_bytes_to_get); free(buffer); } } unlink(pid_file); delete p; return 0; } entropybroker-2.9/config.cpp000066400000000000000000000231041305163522000162370ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "math.h" #include "hasher_type.h" #include "stirrer_type.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "config.h" #include "log.h" #include "stirrer.h" #include "fips140.h" #include "scc.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" bool config_yes_no(char *what) { if (what[0] == '1' || strcasecmp(what, "yes") == 0 || strcasecmp(what, "on") == 0) return true; return false; } void load_config(const char *config, config_t *pconfig) { char *dummy = strdup(config); char *cur_dir_dummy = dirname(dummy); char *cur_dir = realpath(cur_dir_dummy, NULL); int linenr = 0; FILE *fh = fopen(config, "r"); if (!fh) error_exit("error opening configuration file '%s'", config); /* set defaults */ pconfig -> max_number_of_mem_pools = 14; pconfig -> max_number_of_disk_pools = 128; pconfig -> min_store_on_disk_n = 5; pconfig -> bitcount_estimator = BCE_SHANNON; pconfig -> listen_adapter = "0.0.0.0"; pconfig -> listen_port = DEFAULT_BROKER_PORT; pconfig -> listen_queue_size = 64; pconfig -> disable_nagle = false; pconfig -> enable_keepalive = true; pconfig -> reset_counters_interval = 60; pconfig -> statistics_interval = 300; pconfig -> ping_interval = 601; pconfig -> kernelpool_filled_interval = 3600; pconfig -> stats_file = NULL; pconfig -> communication_timeout = 15.0; pconfig -> communication_session_timeout = 3600.0; /* 0 for no timeout */ pconfig -> default_sleep_time_when_pools_full = 10; pconfig -> default_sleep_when_pools_empty = 16; pconfig -> default_max_sleep_when_pools_empty = 60; pconfig -> when_pools_full_allow_submit_interval = 15; pconfig -> max_open_files = 1024; pconfig -> default_max_bits_per_interval = 16000000; pconfig -> ignore_rngtest_fips140 = false; pconfig -> ignore_rngtest_scc = false; pconfig -> scc_threshold = 0.2; pconfig -> allow_event_entropy_addition = true; pconfig -> add_entropy_even_if_all_full = false; pconfig -> allow_prng = false; pconfig -> user_map = new std::string("usermap.txt"); pconfig -> pool_size_bytes = DEFAULT_POOL_SIZE_BITS / 8; pconfig -> prng_seed_file = NULL; pconfig -> max_get_put_size = 1249; pconfig -> ht = H_SHA512; pconfig -> st = S_BLOWFISH; pconfig -> rs = RS_CRYPTOPP; pconfig -> stream_cipher = "blowfish"; pconfig -> mac_hasher = "md5"; pconfig -> hash_hasher = "sha512"; pconfig -> webserver_interface = "0.0.0.0"; pconfig -> webserver_port = -1; pconfig -> graph_font = strdup(FONT); pconfig -> default_max_get_bps = 4096; for(;;) { double parvald; int parval; char read_buffer[4096], *lf, *par; char *cmd = fgets(read_buffer, sizeof read_buffer, fh), *is; if (!cmd) break; linenr++; if (read_buffer[0] == '#' || read_buffer[0] == ';') continue; while(*cmd == ' ') cmd++; lf = strchr(read_buffer, '\n'); if (lf) *lf = 0x00; if (strlen(cmd) == 0) continue; is = strchr(read_buffer, '='); if (!is) error_exit("invalid line at line %d: '=' missing", linenr); *is = 0x00; par = is + 1; while(*par == ' ') par++; parval = atoi(par); parvald = atof(par); is--; while(*is == ' ') { *is = 0x00 ; is--; } if (strcmp(cmd, "max_number_of_mem_pools") == 0) pconfig -> max_number_of_mem_pools = parval; else if (strcmp(cmd, "max_number_of_disk_pools") == 0) pconfig -> max_number_of_disk_pools = parval; else if (strcmp(cmd, "min_store_on_disk_n") == 0) pconfig -> min_store_on_disk_n = parval; else if (strcmp(cmd, "listen_adapter") == 0) pconfig -> listen_adapter = strdup(par); else if (strcmp(cmd, "graph_font") == 0) pconfig -> graph_font = strdup(par); else if (strcmp(cmd, "users") == 0) { char *p_file = static_cast(malloc(strlen(cur_dir) + strlen(par) + 1 + 1)); if (par[0] == '/') strcpy(p_file, par); else sprintf(p_file, "%s/%s", cur_dir, par); dolog(LOG_INFO, "Load users from %s", p_file); delete pconfig -> user_map; pconfig -> user_map = new std::string(p_file); free(p_file); } else if (strcmp(cmd, "bitcount_estimator") == 0) { if (strcmp(par, "shannon") == 0) pconfig -> bitcount_estimator = BCE_SHANNON; else if (strcmp(par, "compression") == 0) pconfig -> bitcount_estimator = BCE_COMPRESSION; else error_exit("bitcount_estimator of type '%s' is not known", par); } else if (strcmp(cmd, "random_source") == 0) { if (strcmp(par, "cryptopp") == 0) pconfig -> rs = RS_CRYPTOPP; else if (strcmp(par, "dev_random") == 0) pconfig -> rs = RS_DEV_RANDOM; else if (strcmp(par, "dev_urandom") == 0) pconfig -> rs = RS_DEV_URANDOM; else error_exit("random_source of type '%s' is not known", par); } else if (strcmp(cmd, "listen_port") == 0) pconfig -> listen_port = parval; else if (strcmp(cmd, "listen_queue_size") == 0) pconfig -> listen_queue_size = parval; else if (strcmp(cmd, "default_max_get_bps") == 0) pconfig -> default_max_get_bps = parval; else if (strcmp(cmd, "max_open_files") == 0) pconfig -> max_open_files = parval; else if (strcmp(cmd, "webserver_interface") == 0) pconfig -> webserver_interface = par; else if (strcmp(cmd, "webserver_port") == 0) pconfig -> webserver_port = parval; else if (strcmp(cmd, "disable_nagle") == 0) pconfig -> disable_nagle = config_yes_no(par); else if (strcmp(cmd, "enable_keepalive") == 0) pconfig -> enable_keepalive = config_yes_no(par); else if (strcmp(cmd, "reset_counters_interval") == 0) pconfig -> reset_counters_interval = parval; else if (strcmp(cmd, "statistics_interval") == 0) pconfig -> statistics_interval = parval; else if (strcmp(cmd, "ping_interval") == 0) pconfig -> ping_interval = parval; else if (strcmp(cmd, "pool_size_in_bytes") == 0) pconfig -> pool_size_bytes = parval; else if (strcmp(cmd, "max_get_put_size") == 0) pconfig -> max_get_put_size = parval; else if (strcmp(cmd, "kernelpool_filled_interval") == 0) pconfig -> kernelpool_filled_interval = parval; else if (strcmp(cmd, "stats_file") == 0) pconfig -> stats_file = strdup(par); else if (strcmp(cmd, "stream_cipher") == 0) pconfig -> stream_cipher = par; else if (strcmp(cmd, "mac_hasher") == 0) pconfig -> mac_hasher = par; else if (strcmp(cmd, "hash_hasher") == 0) pconfig -> hash_hasher = par; else if (strcmp(cmd, "prng_seed_file") == 0) { char *p_file = static_cast(malloc(strlen(VAR_DIR) + strlen(par) + 1 + 1)); if (par[0] == '/') strcpy(p_file, par); else sprintf(p_file, VAR_DIR "/%s", par); dolog(LOG_INFO, "Will load PRNG seed from %s", p_file); pconfig -> prng_seed_file = p_file; } else if (strcmp(cmd, "communication_timeout") == 0) pconfig -> communication_timeout = parvald; else if (strcmp(cmd, "communication_session_timeout") == 0) pconfig -> communication_session_timeout = parvald; else if (strcmp(cmd, "default_sleep_time_when_pools_full") == 0) pconfig -> default_sleep_time_when_pools_full = parval; else if (strcmp(cmd, "default_sleep_when_pools_empty") == 0) pconfig -> default_sleep_when_pools_empty = parval; else if (strcmp(cmd, "default_max_sleep_when_pools_empty") == 0) pconfig -> default_max_sleep_when_pools_empty = parval; else if (strcmp(cmd, "default_max_bits_per_interval") == 0) pconfig -> default_max_bits_per_interval = parval; else if (strcmp(cmd, "ignore_rngtest_fips140") == 0) pconfig -> ignore_rngtest_fips140 = config_yes_no(par); else if (strcmp(cmd, "ignore_rngtest_scc") == 0) pconfig -> ignore_rngtest_scc = config_yes_no(par); else if (strcmp(cmd, "allow_event_entropy_addition") == 0) pconfig -> allow_event_entropy_addition = config_yes_no(par); else if (strcmp(cmd, "add_entropy_even_if_all_full") == 0) pconfig -> add_entropy_even_if_all_full = config_yes_no(par); else if (strcmp(cmd, "allow_prng") == 0) pconfig -> allow_prng = config_yes_no(par); else if (strcmp(cmd, "scc_threshold") == 0) pconfig -> scc_threshold = parvald; else if (strcmp(cmd, "when_pools_full_allow_submit_interval") == 0) pconfig -> when_pools_full_allow_submit_interval = parval; else if (strcmp(cmd, "hash_type") == 0) { if (strcmp(par, "sha512") == 0) pconfig -> ht = H_SHA512; else if (strcmp(par, "md5") == 0) pconfig -> ht = H_MD5; else if (strcmp(par, "ripemd160") == 0) pconfig -> ht = H_RIPEMD160; else if (strcmp(par, "whirlpool") == 0) pconfig -> ht = H_WHIRLPOOL; else error_exit("Hash type '%s' not understood", par); } else if (strcmp(cmd, "stirrer_type") == 0) { if (strcmp(par, "blowfish") == 0) pconfig -> st = S_BLOWFISH; else if (strcmp(par, "aes") == 0) pconfig -> st = S_AES; else if (strcmp(par, "3des") == 0) pconfig -> st = S_3DES; else if (strcmp(par, "camellia") == 0) pconfig -> st = S_CAMELLIA; else error_exit("Stirrer type '%s' not understood", par); } else error_exit("%s=%s not understood", cmd, par); } dolog(LOG_DEBUG, "read %d configuration file lines", linenr); fclose(fh); free(dummy); free(cur_dir); } entropybroker-2.9/config.h000066400000000000000000000023661305163522000157130ustar00rootroot00000000000000typedef struct { unsigned int max_number_of_mem_pools; unsigned int max_number_of_disk_pools; unsigned int min_store_on_disk_n; int pool_size_bytes; const char *listen_adapter; int listen_port; int listen_queue_size; bool disable_nagle; bool enable_keepalive; int reset_counters_interval; int statistics_interval; int ping_interval; int kernelpool_filled_interval; bit_count_estimator_type_t bitcount_estimator; char *stats_file; double communication_timeout; double communication_session_timeout; int default_sleep_time_when_pools_full; int default_sleep_when_pools_empty; int default_max_sleep_when_pools_empty; int when_pools_full_allow_submit_interval; int default_max_bits_per_interval; int max_open_files; bool ignore_rngtest_fips140, ignore_rngtest_scc; double scc_threshold; bool allow_event_entropy_addition; bool add_entropy_even_if_all_full; bool allow_prng; char *prng_seed_file; int max_get_put_size; int default_max_get_bps; hasher_type ht; stirrer_type st; random_source_t rs; std::string stream_cipher, mac_hasher, hash_hasher; std::string *user_map; const char *graph_font; std::string webserver_interface; int webserver_port; } config_t; void load_config(const char *config, config_t *pconfig); entropybroker-2.9/configure000077500000000000000000000064011305163522000161760ustar00rootroot00000000000000#! /bin/sh B2='' FILE=/tmp/a.out_eb_$$ FILE2=/tmp/a.out_eb2_$$ echo \*\*\* Entropy Broker v`grep VERSION version | cut -d = -f 2` \(`echo $Revision$ | awk '{ print $2; }'`\) configure script \*\*\* echo echo -n \* checking for GCC \(G++\)... g++ -O0 -o $FILE test_gcc.cpp 2> $FILE2 if [ $? -ne 0 ] ; then echo echo \! problem invoking GCC echo \! entropy_broker does not require GCC but this echo \! $0 script does echo echo \! errors reported: echo cat $FILE2 echo exit 1 fi echo \ OK echo -n \* checking for CryptoPP... g++ -O0 -o $FILE test_cryptopp.cpp 2> $FILE2 if [ $? -ne 0 ] ; then echo echo \! CryptoPP was NOT detected echo \! CryptoPP is required for entropy_broker echo echo \! errors reported: echo cat $FILE2 echo exit 1 fi echo \ OK echo -n \* checking for zlib... g++ -O0 -o $FILE test_zlib.cpp 2> $FILE2 if [ $? -ne 0 ] ; then echo echo \! zlib was NOT detected echo \! zlib is required for entropy_broker echo echo \! errors reported: echo cat $FILE2 echo exit 1 fi echo \ OK echo -n \* checking for libpng12-dev... g++ -O0 -o $FILE test_libpng.cpp 2> $FILE2 if [ $? -ne 0 ] ; then echo echo \! libpng12-dev was NOT detected echo \! libpng12-dev is required for entropy_broker echo echo \! errors reported: echo cat $FILE2 echo exit 1 fi echo \ OK echo -n \* checking for libgd2-\(no\)xpm-dev... g++ -O0 -o $FILE test_libgd2.cpp 2> $FILE2 if [ $? -ne 0 ] ; then echo echo \! libgd2-\(no\)xpm-dev was NOT detected echo \! libgd2-\(no\)xpm-dev is required for entropy_broker echo echo \! errors reported: echo cat $FILE2 echo exit 1 fi echo \ OK g++ -O0 -o $FILE test_asound2.cpp 2> /dev/null if [ $? -eq 0 ] ; then echo \+ libasound2 detected, enabling eb_server_audio B2="$B2 eb_server_audio" else echo \- libasound2 NOT found, disabling eb_server_audio fi g++ -O0 -o $FILE test_TFO.cpp 2> $FILE2 if [ $? -eq 0 ] ; then echo \+ system supports TCP fast open TFO="TFO=yes" else echo \- this system does NOT support TCP fast open TFO="" fi g++ -O0 -o $FILE test_libusb.cpp 2> /dev/null if [ $? -eq 0 ] ; then echo \+ libusb-1.0-0 detected, enabling eb_server_usb and eb_server_Araneus_Alea B2="$B2 eb_server_usb eb_server_Araneus_Alea" else echo \- libusb-1.0-0 NOT found, disabling eb_server_usb and eb_server_Araneus_Alea fi g++ -O0 -o $FILE `pkg-config --cflags libpcsclite` test_pcsclite.cpp 2> /dev/null if [ $? -eq 0 ] ; then echo \+ libpcsclite-dev detected, enabling eb_server_smartcard B2="$B2 eb_server_smartcard" PCSC='PCSC_CFLAGS=`pkg-config --cflags libpcsclite`' else echo \- libpcsclite-dev NOT found, disabling eb_server_smartcard fi g++ -O0 -o $FILE `pkg-config --cflags libqwqng` test_libqwqng.cpp 2> /dev/null if [ $? -eq 0 ] ; then echo \+ libqwqng-dev detected, enabling eb_server_qwqng B2="$B2 eb_server_qwqng" QWQNG='PCSC_CFLAGS=`pkg-config --cflags libqwqng`' else echo \- libqwqng-dev NOT found, disabling eb_server_qwqng fi g++ -O0 -o $FILE test_libftdi.cpp 2> /dev/null if [ $? -eq 0 ] ; then echo \+ libftdi-dev detected, enabling eb_server_ComScire_R2000KU B2="$B2 eb_server_ComScire_R2000KU" else echo \- libftdi-dev NOT found, disabling eb_server_ComScire_R2000KU fi echo B2=$B2 > makefile.inc echo $PCSC >> makefile.inc echo $QWQNG >> makefile.inc echo $TFO >> makefile.inc rm -f $FILE $FILE2 echo entropybroker-2.9/data_logger.cpp000066400000000000000000000227531305163522000172530ustar00rootroot00000000000000#include #include #include #include #include #include "defines.h" #include "error.h" #include "utils.h" #include "log.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "data_store_int.h" #include "data_logger.h" void *start_data_logger_thread_wrapper(void *p) { data_logger *dl = reinterpret_cast(p); dl -> run(); return NULL; } data_logger::data_logger(statistics *s_in, pools *ppools_in, std::vector *clients_in, pthread_mutex_t *clients_mutex_in) : s(s_in), ppools(ppools_in), clients(clients_in), clients_mutex(clients_mutex_in) { abort = false; pthread_check(pthread_mutex_init(&terminate_flag_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(MEM_POOL_COUNTS)) mem_pool_counts = new data_store_int(MEM_POOL_COUNTS); else mem_pool_counts = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&mem_pool_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(DSK_POOL_COUNTS)) dsk_pool_counts = new data_store_int(DSK_POOL_COUNTS); else dsk_pool_counts = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&dsk_pool_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(CONNECTION_COUNTS)) connection_counts = new data_store_int(CONNECTION_COUNTS); else connection_counts = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&connection_counts_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(MEM_POOL_BIT_COUNT_COUNTS)) mem_pool_bit_count_counts = new data_store_int(MEM_POOL_BIT_COUNT_COUNTS); else mem_pool_bit_count_counts = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&mem_pool_bit_count_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(DSK_POOL_BIT_COUNT_COUNTS)) dsk_pool_bit_count_counts = new data_store_int(DSK_POOL_BIT_COUNT_COUNTS); else dsk_pool_bit_count_counts = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&dsk_pool_bit_count_lck, &global_mutex_attr), "pthread_mutex_init"); prev_recv_n = prev_sent_n = -1; if (file_exist(RECV_BIT_COUNT)) recv_bit_count = new data_store_int(RECV_BIT_COUNT); else recv_bit_count = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&recv_bit_count_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(RECV_BIT_COUNT_IN)) recv_bit_count_in = new data_store_int(RECV_BIT_COUNT_IN); else recv_bit_count_in = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&recv_bit_count_in_lck, &global_mutex_attr), "pthread_mutex_init"); if (file_exist(SENT_BIT_COUNT)) sent_bit_count = new data_store_int(SENT_BIT_COUNT); else sent_bit_count = new data_store_int(MEASURE_KEEP_N, MEASURE_INTERVAL); pthread_check(pthread_mutex_init(&sent_bit_count_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_create(&thread, NULL, start_data_logger_thread_wrapper, this), "pthread_create"); } data_logger::~data_logger() { my_mutex_lock(&terminate_flag_lck); abort = true; my_mutex_unlock(&terminate_flag_lck); dolog(LOG_INFO, "data logger about to terminate: waiting to thread to terminate"); pthread_check(pthread_join(thread, NULL), "pthread_join"); dolog(LOG_INFO, "data logger thread stopped"); pthread_check(pthread_mutex_destroy(&terminate_flag_lck), "pthread_mutex_destroy"); dump_data(); delete mem_pool_counts; pthread_check(pthread_mutex_destroy(&mem_pool_lck), "pthread_mutex_destroy"); delete dsk_pool_counts; pthread_check(pthread_mutex_destroy(&dsk_pool_lck), "pthread_mutex_destroy"); delete connection_counts; pthread_check(pthread_mutex_destroy(&connection_counts_lck), "pthread_mutex_destroy"); delete mem_pool_bit_count_counts; pthread_check(pthread_mutex_destroy(&mem_pool_bit_count_lck), "pthread_mutex_destroy"); delete dsk_pool_bit_count_counts; pthread_check(pthread_mutex_destroy(&dsk_pool_bit_count_lck), "pthread_mutex_destroy"); delete recv_bit_count; pthread_check(pthread_mutex_destroy(&recv_bit_count_lck), "pthread_mutex_destroy"); delete recv_bit_count_in; pthread_check(pthread_mutex_destroy(&recv_bit_count_in_lck), "pthread_mutex_destroy"); delete sent_bit_count; pthread_check(pthread_mutex_destroy(&sent_bit_count_lck), "pthread_mutex_destroy"); dolog(LOG_INFO, "data logger stopped"); } void data_logger::dump_data() { dolog(LOG_INFO, "dump statistics to disk"); my_mutex_lock(&mem_pool_lck); mem_pool_counts -> dump(MEM_POOL_COUNTS); my_mutex_unlock(&mem_pool_lck); my_mutex_lock(&dsk_pool_lck); dsk_pool_counts -> dump(DSK_POOL_COUNTS); my_mutex_unlock(&dsk_pool_lck); my_mutex_lock(&connection_counts_lck); connection_counts -> dump(CONNECTION_COUNTS); my_mutex_unlock(&connection_counts_lck); my_mutex_lock(&mem_pool_bit_count_lck); mem_pool_bit_count_counts -> dump(MEM_POOL_BIT_COUNT_COUNTS); my_mutex_unlock(&mem_pool_bit_count_lck); my_mutex_lock(&dsk_pool_bit_count_lck); dsk_pool_bit_count_counts -> dump(DSK_POOL_BIT_COUNT_COUNTS); my_mutex_unlock(&dsk_pool_bit_count_lck); my_mutex_lock(&sent_bit_count_lck); sent_bit_count -> dump(SENT_BIT_COUNT); my_mutex_unlock(&sent_bit_count_lck); my_mutex_lock(&recv_bit_count_lck); recv_bit_count -> dump(RECV_BIT_COUNT); my_mutex_unlock(&recv_bit_count_lck); my_mutex_lock(&recv_bit_count_in_lck); recv_bit_count_in -> dump(RECV_BIT_COUNT_IN); my_mutex_unlock(&recv_bit_count_in_lck); } void data_logger::run() { double prev_ts = -1, last_dump_ts = get_ts(); for(;;) { my_mutex_lock(&terminate_flag_lck); bool terminate = abort; my_mutex_unlock(&terminate_flag_lck); if (terminate) break; double now_ts = get_ts(); if (now_ts - prev_ts >= MEASURE_INTERVAL) { time_t dummy_ts = time_t(now_ts); my_mutex_lock(&mem_pool_lck); mem_pool_counts -> add_avg(dummy_ts, ppools -> get_memory_pool_count()); my_mutex_unlock(&mem_pool_lck); my_mutex_lock(&dsk_pool_lck); dsk_pool_counts -> add_avg(dummy_ts, ppools -> get_disk_pool_count()); my_mutex_unlock(&dsk_pool_lck); my_mutex_lock(&connection_counts_lck); connection_counts -> add_avg(dummy_ts, clients -> size()); my_mutex_unlock(&connection_counts_lck); my_mutex_lock(&mem_pool_bit_count_lck); mem_pool_bit_count_counts -> add_avg(dummy_ts, ppools -> get_bit_sum(DEFAULT_COMM_TO + 1.0)); my_mutex_unlock(&mem_pool_bit_count_lck); my_mutex_lock(&dsk_pool_bit_count_lck); dsk_pool_bit_count_counts -> add_avg(dummy_ts, ppools -> get_disk_pool_bit_count()); my_mutex_unlock(&dsk_pool_bit_count_lck); long long int recv_total_bits = 0, recv_total_bits_in = 0, sent_total_bits = 0; int n_reqs = 0, n_sents = 0; s -> get_recvs(&recv_total_bits, &n_reqs, &recv_total_bits_in); s -> get_sents(&sent_total_bits, &n_sents); if (prev_recv_n != -1) { my_mutex_lock(&recv_bit_count_lck); recv_bit_count -> add_avg(dummy_ts, recv_total_bits - prev_recv_n); my_mutex_unlock(&recv_bit_count_lck); my_mutex_lock(&recv_bit_count_in_lck); recv_bit_count_in -> add_avg(dummy_ts, recv_total_bits_in - prev_recv_in_n); my_mutex_unlock(&recv_bit_count_in_lck); } prev_recv_n = recv_total_bits; prev_recv_in_n = recv_total_bits_in; if (prev_sent_n != -1) { my_mutex_lock(&sent_bit_count_lck); sent_bit_count -> add_avg(dummy_ts, sent_total_bits - prev_sent_n); my_mutex_unlock(&sent_bit_count_lck); } prev_sent_n = sent_total_bits; prev_ts = now_ts; } if (now_ts - last_dump_ts >= 3600) // push to disk every hour { dump_data(); last_dump_ts = now_ts; } sleep(1); } } void data_logger::get_mem_pool_counts(long int **t, double **v, int *n) { my_mutex_lock(&mem_pool_lck); mem_pool_counts -> get_data(t, v, n); my_mutex_unlock(&mem_pool_lck); } void data_logger::get_dsk_pool_counts(long int **t, double **v, int *n) { my_mutex_lock(&dsk_pool_lck); dsk_pool_counts -> get_data(t, v, n); my_mutex_unlock(&dsk_pool_lck); } void data_logger::get_connection_counts(long int **t, double **v, int *n) { my_mutex_lock(clients_mutex); connection_counts -> get_data(t, v, n); my_mutex_unlock(clients_mutex); } void data_logger::get_pools_bitcounts(long int **t, double **v, int *n) { my_mutex_lock(&mem_pool_bit_count_lck); mem_pool_bit_count_counts -> get_data(t, v, n); my_mutex_unlock(&mem_pool_bit_count_lck); } void data_logger::get_disk_pools_bitcounts(long int **t, double **v, int *n) { my_mutex_lock(&dsk_pool_bit_count_lck); dsk_pool_bit_count_counts -> get_data(t, v, n); my_mutex_unlock(&dsk_pool_bit_count_lck); } void data_logger::get_recv_bit_count(long int **t, double **v, int *n) { my_mutex_lock(&recv_bit_count_lck); recv_bit_count -> get_data(t, v, n); my_mutex_unlock(&recv_bit_count_lck); } void data_logger::get_recv_bit_count_in(long int **t, double **v, int *n) { my_mutex_lock(&recv_bit_count_in_lck); recv_bit_count_in -> get_data(t, v, n); my_mutex_unlock(&recv_bit_count_in_lck); } void data_logger::get_sent_bit_count(long int **t, double **v, int *n) { my_mutex_lock(&sent_bit_count_lck); sent_bit_count -> get_data(t, v, n); my_mutex_unlock(&sent_bit_count_lck); } entropybroker-2.9/data_logger.h000066400000000000000000000037571305163522000167230ustar00rootroot00000000000000#define MEM_POOL_COUNTS VAR_DIR "/mem_pool_counts.dat" #define MEM_POOL_BIT_COUNT_COUNTS VAR_DIR "/mem_pool_bit_count_counts.dat" #define DSK_POOL_COUNTS VAR_DIR "/dsk_pool_counts.dat" #define DSK_POOL_BIT_COUNT_COUNTS VAR_DIR "/dsk_pool_bit_count_counts.dat" #define CONNECTION_COUNTS VAR_DIR "/connection_counts.dat" #define RECV_BIT_COUNT VAR_DIR "/recv_bit_count.dat" #define RECV_BIT_COUNT_IN VAR_DIR "/recv_bit_count_in.dat" #define SENT_BIT_COUNT VAR_DIR "/sent_bit_count.dat" class data_logger { private: pthread_mutex_t mem_pool_lck; data_store_int *mem_pool_counts; pthread_mutex_t dsk_pool_lck; data_store_int *dsk_pool_counts; pthread_mutex_t connection_counts_lck; data_store_int *connection_counts; pthread_mutex_t mem_pool_bit_count_lck; data_store_int *mem_pool_bit_count_counts; pthread_mutex_t dsk_pool_bit_count_lck; data_store_int *dsk_pool_bit_count_counts; long long int prev_recv_n, prev_recv_in_n, prev_sent_n; pthread_mutex_t recv_bit_count_lck; data_store_int *recv_bit_count; pthread_mutex_t recv_bit_count_in_lck; data_store_int *recv_bit_count_in; pthread_mutex_t sent_bit_count_lck; data_store_int *sent_bit_count; pthread_t thread; pthread_mutex_t terminate_flag_lck; bool abort; /// statistics *s; pools *ppools; std::vector *clients; pthread_mutex_t *clients_mutex; void dump_data(); public: data_logger(statistics *s_in, pools *ppools_in, std::vector *clients_in, pthread_mutex_t *clients_mutex_in); ~data_logger(); void get_mem_pool_counts(long int **t, double **v, int *n); void get_dsk_pool_counts(long int **t, double **v, int *n); void get_connection_counts(long int **t, double **v, int *n); void get_pools_bitcounts(long int **t, double **v, int *n); void get_disk_pools_bitcounts(long int **t, double **v, int *n); void get_recv_bit_count(long int **t, double **v, int *n); void get_recv_bit_count_in(long int **t, double **v, int *n); void get_sent_bit_count(long int **t, double **v, int *n); void run(); }; entropybroker-2.9/data_store_int.cpp000066400000000000000000000075261305163522000200030ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "utils.h" #include "data_store_int.h" data_store_int::data_store_int(int n_samples_in, int interval_in) : n_samples(n_samples_in), interval(interval_in) { values = (long long int *)calloc(n_samples, sizeof(long long int)); counts = (int *)calloc(n_samples, sizeof(int)); valid = (bool *)calloc(n_samples, sizeof(bool)); cur_t = 0; } data_store_int::data_store_int(std::string file) { FILE *fh = fopen(file.c_str(), "r"); if (!fh) error_exit("failed to open %s", file.c_str()); if (!get_int(fh, &n_samples)) error_exit("short read on %s", file.c_str()); if (!get_int(fh, &interval)) error_exit("short read on %s", file.c_str()); if (!get_int(fh, &cur_t)) error_exit("short read on %s", file.c_str()); values = (long long int *)calloc(n_samples, sizeof(long long int)); counts = (int *)calloc(n_samples, sizeof(int)); valid = (bool *)calloc(n_samples, sizeof(bool)); for(int index=0; index prev_index) { int n = (cur_index - prev_index) - 1; if (n > 0) { memset(&values[prev_index + 1], 0x00, sizeof(long long int) * n); memset(&counts[prev_index + 1], 0x00, sizeof(int) * n); memset(&valid[prev_index + 1], 0x00, sizeof(bool) * n); } } else { int n = n_samples - prev_index; memset(&values[prev_index], 0x00, sizeof(long long int) * n); memset(&counts[prev_index], 0x00, sizeof(int) * n); memset(&valid[prev_index], 0x00, sizeof(bool) * n); memset(&values[0], 0x00, sizeof(long long int) * cur_index); memset(&counts[0], 0x00, sizeof(int) * cur_index); memset(&valid[0], 0x00, sizeof(bool) * cur_index); } values[cur_index] = 0; counts[cur_index] = 0; valid[cur_index] = true; } cur_t = t; return cur_index; } void data_store_int::add_avg(int t, int value) { int index = init_data(t); values[index] += value; counts[index]++; } void data_store_int::add_sum(int t, int value) { int index = init_data(t); values[index] += value; counts[index] = 1; } bool data_store_int::get(int index, double *value) { if (counts[index]) { *value = double(values[index]) / double(counts[index]); return true; } return false; } void data_store_int::get_data(long int **t, double **v, int *n) { int offset_index = (cur_t / interval) % n_samples; *t = (long int *)malloc(sizeof(long int) * n_samples); *v = (double *)malloc(sizeof(double) * n_samples); *n = 0; long int start_t = cur_t - n_samples * interval; for(int index=0; index $TEMP1 (echo 0 ; confft -f $TEMP1 -m | tail -n +2) > $TEMP2 rm $TEMP1 gnuplot < $2 set term png size 800,600 set autoscale set title "FFT of $1" set xlabel "freq" set ylabel "magnitude plot "$TEMP2" using 1 with lines title 'magnitude' EOF rm $TEMP2 entropybroker-2.9/doc/000077500000000000000000000000001305163522000150335ustar00rootroot00000000000000entropybroker-2.9/doc/man/000077500000000000000000000000001305163522000156065ustar00rootroot00000000000000entropybroker-2.9/doc/man/eb_client_egd.1000066400000000000000000000020121305163522000204260ustar00rootroot00000000000000.TH EB_CLIENT_EGD "1" "July 2012" "eb_client_egd" "User Commands" .SH NAME eb_client_egd \- export entropy data as egd server .SH DESCRIPTION eb_client_egd v1.0, (C) 2009-2012 by folkert@vanheusden.com Egd-clients can use the /tmp/egd.sock unix domain socket. This should work with at least OpenSSL: start eb_client_egd with one of the following parameters: \-d /var/run/egd-pool or \-d /dev/egd-pool or \-d /etc/egd-pool or \-d /etc/entropy To verify that client_egd functions, run: "openssl rand \-rand /var/run/egd-pool \-out /tmp/bla 10". It should return something like "255 semi-random bytes loaded" where "255" should be > 0. If it is zero, check if the current user has enough rights to access the /var/run/egd-pool file. .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-d\fR file UNIX-domain socket to listen on .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_client_file.1000066400000000000000000000010301305163522000206050ustar00rootroot00000000000000.TH EB_CLIENT_FILE "1" "July 2012" "eb_client_file" "User Commands" .SH NAME eb_client_file \- export entropy data to a file .SH DESCRIPTION eb_client_file v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-f\fR file file to write to .TP \fB\-c\fR count number of bytes to write .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_client_kernel_generic.1000066400000000000000000000015221305163522000226500ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH EB_CLIENT_KERNEL_GENERIC "1" "September 2016" "eb_client_kernel_generic" "User Commands" .SH NAME eb_client_kernel_generic \- client for kernel generic, v2.8, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION eb_client_kernel_generic .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-n\fR do not fork .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file .PP \fB\-S\fR time how long to sleep between each iteration .PP \fB\-b\fR x how many BYTES to process each iteration entropybroker-2.9/doc/man/eb_client_linux_kernel.1000066400000000000000000000014221305163522000223720ustar00rootroot00000000000000.TH EB_CLIENT_LINUX_KERNEL "1" "July 2012" "eb_client_linux_kernel" "User Commands" .SH NAME eb_client_linux_kernel \- send entropy data to /dev/random .SH DESCRIPTION eb_client_linux_kernel v1.0, (C) 2009-2012 by folkert@vanheusden.com To keep the entropy buffer of the local linux kernel filled-up, start client_linux_kernel as a root user. If you want the kernel buffers to be filled much earlier (the default is when it only has 128 bits left), then write a new value to: "/proc/sys/kernel/random/write_wakeup_threshold". E.g. 512. .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_proxy_knuth_b.1000066400000000000000000000017261305163522000212370ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH PROXY_KNUTH_B, "1" "September 2016" "proxy_knuth_b" "User Commands" .SH NAME proxy_knuth_b \- server for proxy_knuth_b, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION proxy_knuth_b .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-j\fR adapter adapter to listen on .PP \fB\-p\fR port port to listen on (default: 12347) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-n\fR do not fork .PP \fB\-V\fR file store buffers to this file (default: \fI\,/var/cache/lookup.knuthb\/\fP) .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file (to authenticate to broker) .PP \fB\-U\fR file read u/p for clients from file (to authenticate local clients) entropybroker-2.9/doc/man/eb_proxy_knuth_m.1000066400000000000000000000017261305163522000212520ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH PROXY_KNUTH_M, "1" "September 2016" "proxy_knuth_m" "User Commands" .SH NAME proxy_knuth_m \- server for proxy_knuth_m, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION proxy_knuth_m .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-j\fR adapter adapter to listen on .PP \fB\-p\fR port port to listen on (default: 12347) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-n\fR do not fork .PP \fB\-V\fR file store buffers to this file (default: \fI\,/var/cache/lookup.knuthm\/\fP) .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file (to authenticate to broker) .PP \fB\-U\fR file read u/p for clients from file (to authenticate local clients) entropybroker-2.9/doc/man/eb_server_Araneus_Alea.1000066400000000000000000000015421305163522000222460ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH eb_server_Araneus_Alea "1" "September 2016" "eb_server_Araneus_Alea" "User Commands" .SH NAME eb_server_Araneus_Alea \- server for Araneus Alea, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION eb_server_Araneus_Alea .PP .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-o\fR file file to write entropy data to (mututal exclusive with \fB\-i\fR) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-S\fR show bps (mutual exclusive with \fB\-n\fR) .PP \fB\-n\fR do not fork .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file entropybroker-2.9/doc/man/eb_server_ComScire_R2000KU.1000066400000000000000000000015671305163522000224640ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH eb_server_ComScire_R2000KU "1" "September 2016" "eb_server_ComScire_R2000KU" "User Commands" .SH NAME eb_server_ComScire_R2000KU \- server for ComScire R2000KU, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION eb_server_ComScire_R2000KU .PP .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-o\fR file file to write entropy data to (mututal exclusive with \fB\-i\fR) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-S\fR show bps (mutual exclusive with \fB\-n\fR) .PP \fB\-n\fR do not fork .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file entropybroker-2.9/doc/man/eb_server_audio.1000066400000000000000000000011001305163522000210150ustar00rootroot00000000000000.TH EB_SERVER_AUDIO "1" "July 2012" "eb_server_audio" "User Commands" .SH NAME eb_server_audio \- gather entropy on systems with a spare sound-card .SH DESCRIPTION eb_server_audio v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-d\fR dev audio\-device, default hw:1 .TP \fB\-o\fR file file to write entropy data to .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_egd.1000066400000000000000000000013111305163522000204570ustar00rootroot00000000000000.TH EB_SERVER_EGD "1" "July 2012" "eb_server_egd" "User Commands" .SH NAME eb_server_egd \- gather entropy on systems with an EntropyKey or EGD .SH DESCRIPTION eb_server_egd v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-d\fR path unix domain socket to read from .TP \fB\-o\fR file file to write entropy data to (mututal exclusive with \fB\-i\fR) .TP \fB\-a\fR x bytes per interval to read from egd .TP \fB\-b\fR x interval for reading data .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_ext_proc.1000066400000000000000000000011771305163522000215550ustar00rootroot00000000000000.TH EB_SERVER_EXT_PROC "1" "July 2012" "eb_server_ext_proc" "User Commands" .SH NAME eb_server_ext_proc \- gather entropy on systems with a spare sound-card .SH DESCRIPTION eb_server_ext_proc v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-c\fR cmd command to execute - its output will be fed to the broker .TP \fB\-s\fR shell shell to use to execute the command given with \-c .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_linux_kernel.1000066400000000000000000000015121305163522000224220ustar00rootroot00000000000000.TH EB_SERVER_LINUX_KERNEL "1" "July 2012" "eb_server_linux_kernel" "User Commands" .SH NAME eb_server_linux_kernel \- retrieve entropy data from /dev/random .SH DESCRIPTION eb_server_linux_kernel v1.0, (C) 2009-2012 by folkert@vanheusden.com Please note: this program RETRIEVES entropy data from the kernel and feeds that to the entropybroker! If you want to ADD data to the kernel entropy buffer instead (which is what you most likely want to do), then use eb_client_linux_kernel .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-o\fR file file to write entropy data to .TP \fB\-S\fR show bps (mutual exclusive with \-n) .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_push_file.1000066400000000000000000000010111305163522000216730ustar00rootroot00000000000000.TH EB_SERVER_PUSH_FILE "1" "July 2012" "eb_server_push_file" "User Commands" .SH NAME eb_server_push_file \- push entropy data from file to eb\-host .SH DESCRIPTION eb_server_push_file v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-f\fR file file to write to .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_smartcard.1000066400000000000000000000015231305163522000217050ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH eb_server_smartcard "1" "September 2016" "eb_server_smartcard" "User Commands" .SH NAME eb_server_smartcard \- server for smartcard, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION eb_server_smartcard .PP .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-o\fR file file to write entropy data to (mututal exclusive with \fB\-i\fR) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-S\fR show bps (mutual exclusive with \fB\-n\fR) .PP \fB\-n\fR do not fork .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file entropybroker-2.9/doc/man/eb_server_stream.1000066400000000000000000000012051305163522000212150ustar00rootroot00000000000000.TH EB_SERVER_STREAM "1" "July 2012" "eb_server_stream" "User Commands" .SH NAME eb_server_stream \- gather entropy .SH DESCRIPTION eb_server_stream v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-d\fR dev device to retrieve from (serial port, hw rng device node, etc.) .TP \fB\-p\fR pars if the device is a serial device, then with \fB\-p\fR you can set its parameters: bps,bits .PP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_timers.1000066400000000000000000000007351305163522000212340ustar00rootroot00000000000000.TH EB_SERVER_TIMERS "1" "July 2012" "eb_server_timers" "User Commands" .SH NAME eb_server_timers \- gather entropy on systems that are mostly idle .SH DESCRIPTION eb_server_timers v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/eb_server_usb.1000066400000000000000000000014651305163522000205230ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. .TH eb_server_usb "1" "September 2016" "eb_server_usb" "User Commands" .SH NAME eb_server_usb \- server for USB, (C) 2009-2015 by folkert@vanheusden.com .SH DESCRIPTION eb_server_usb .PP .SH OPTIONS \fB\-I\fR host entropy_broker host to connect to .IP e.g. host .IP host:port [ipv6 literal]:port .IP you can have multiple entries of this .PP \fB\-o\fR file file to write entropy data to (mututal exclusive with \fB\-i\fR) .PP \fB\-l\fR file log to file 'file' .PP \fB\-L\fR x log level, 0=nothing, 255=all .PP \fB\-s\fR log to syslog .PP \fB\-S\fR show bps (mutual exclusive with \fB\-n\fR) .PP \fB\-n\fR do not fork .PP \fB\-P\fR file write pid to file .PP \fB\-X\fR file read username+password from file entropybroker-2.9/doc/man/eb_server_v4l.1000066400000000000000000000011521305163522000204300ustar00rootroot00000000000000.TH EB_SERVER_V4L "1" "July 2012" "eb_server_v4l" "User Commands" .SH NAME eb_server_v4l \- gather entropy from unused video card .SH DESCRIPTION eb_server_v4l v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-i\fR host eb\-host to connect to .TP \fB\-d\fR device device to use .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-n\fR do not fork .TP \fB\-f\fR x skip x frames before processing images (in case the device needs a few frames to settle) .TP \fB\-P\fR file file to write the PID to .TP \fB\-X\fR file file to read the password from entropybroker-2.9/doc/man/entropy_broker.1000066400000000000000000000007261305163522000207410ustar00rootroot00000000000000.TH ENTROPY_BROKER "1" "July 2012" "entropy_broker" "User Commands" .SH NAME entropy_broker \- server to gather entropy data from different clients .SH DESCRIPTION entropy_broker v1.0, (C) 2009-2012 by folkert@vanheusden.com .TP \fB\-c\fR file config\-file to read .TP \fB\-l\fR file log to file 'file' .TP \fB\-s\fR log to syslog .TP \fB\-S\fR statistics\-file to log to .TP \fB\-n\fR do not fork .TP \fB\-P\fR file file to write the PID to entropybroker-2.9/doc/man/test_egd_speed.1000066400000000000000000000002461305163522000206500ustar00rootroot00000000000000.TH TEST_EGD_SPEED "1" "July 2012" "test_egd_speed" "User Commands" .SH NAME test_egd_speed: \- test speed of entropy generation of egd .SH DESCRIPTION no parameters entropybroker-2.9/eb.spec000066400000000000000000000072011305163522000155300ustar00rootroot00000000000000Name: entropy-broker Version: 2.4 Release: 1%{?dist} Summary: entropy broker Group: System Environment/Daemons License: GPL URL: http://www.vanheusden.com/entropybroker/ Source0: entropy-broker-2.4.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: cryptopp-devel, gd-devel, zlib-devel, libpng-devel Requires: cryptopp, gd, zlib, libpng %description entropy broker daemon %package server Summary: entropy broker server %description server entropy broker server %package client Summary: entropy broker client binaries Requires: cryptopp %description client entropy broker client %prep %setup -q %build %configure make %{?_smp_mflags} everything PREFIX=/usr ETC=/etc/entropybroker VAR=/var/ CACHE=/var/cache/entropybroker %install rm -rf %{buildroot} make install PREFIX=%{buildroot}/usr ETC=%{buildroot}/etc/entropybroker VAR=%{buildroot}/var CACHE=%{buildroot}/var/cache/entropybroker mv %{buildroot}/usr/share/man/man8 %{buildroot}/usr/share/man/man1 install -D -m 755 -d %{buildroot}/etc/init.d/ install -m 755 redhat/* %{buildroot}/etc/init.d/ %clean rm -rf %{buildroot} %files server %defattr(-,root,root,-) %doc /usr/doc/entropy_broker/readme.txt %doc /usr/doc/entropy_broker/network_protocol.txt %doc /usr/doc/entropy_broker/interfacing.txt %doc /usr/doc/entropy_broker/users.txt %doc /usr/doc/entropy_broker/license.txt %doc /usr/doc/entropy_broker/auth.txt %doc /usr/doc/entropy_broker/design.txt %config(noreplace) /etc/entropybroker/entropy_broker.conf %config /etc/entropybroker/entropy_broker.conf.dist %config(noreplace) /etc/entropybroker/users.txt /usr/bin/eb_server_Araneus_Alea /usr/bin/eb_server_ext_proc /usr/bin/eb_server_timers /usr/bin/eb_server_usb /usr/bin/eb_server_linux_kernel /usr/bin/entropy_broker /usr/bin/eb_server_v4l /usr/bin/eb_server_cycle_count /usr/bin/eb_proxy_knuth_b /usr/bin/eb_server_stream /usr/bin/eb_server_push_file /usr/bin/eb_proxy_knuth_m /usr/bin/eb_server_ComScire_R2000KU /usr/bin/eb_server_egd /usr/share/eb/web/404.html /usr/share/eb/web/stylesheet.css /usr/share/eb/web/statistics.png /usr/share/eb/web/favicon.ico /usr/share/eb/web/logo.png /usr/share/eb/web/logfiles.png /usr/share/eb/web/logo-bw.png /usr/share/eb/web/users.png /usr/share/man/man1/eb_server_audio.1.gz /usr/share/man/man1/eb_server_egd.1.gz /usr/share/man/man1/eb_server_ext_proc.1.gz /usr/share/man/man1/eb_server_linux_kernel.1.gz /usr/share/man/man1/eb_server_push_file.1.gz /usr/share/man/man1/eb_server_stream.1.gz /usr/share/man/man1/eb_server_timers.1.gz /usr/share/man/man1/eb_server_v4l.1.gz /usr/share/man/man1/entropy_broker.1.gz /usr/share/man/man1/test_egd_speed.1.gz /etc/init.d/eb_server_audio /etc/init.d/eb_server_ComScire_R2000KU /etc/init.d/eb_server_cycle_count /etc/init.d/eb_server_egd /etc/init.d/eb_server_ext_proc /etc/init.d/eb_server_linux_kernel /etc/init.d/eb_server_push_file /etc/init.d/eb_server_smartcard /etc/init.d/eb_server_stream /etc/init.d/eb_server_timers /etc/init.d/eb_server_usb /etc/init.d/eb_server_v4l /etc/init.d/entropy_broker %files client %doc /usr/doc/entropy_broker/readme.txt %doc /usr/doc/entropy_broker/network_protocol.txt %doc /usr/doc/entropy_broker/interfacing.txt %doc /usr/doc/entropy_broker/users.txt %doc /usr/doc/entropy_broker/license.txt %doc /usr/doc/entropy_broker/auth.txt %doc /usr/doc/entropy_broker/design.txt /usr/bin/eb_client_egd /usr/bin/eb_client_kernel_generic /usr/bin/eb_client_file /usr/bin/eb_client_linux_kernel /etc/init.d/eb_client_egd /etc/init.d/eb_client_file /etc/init.d/eb_client_linux_kernel /usr/share/man/man1/eb_client_egd.1.gz /usr/share/man/man1/eb_client_file.1.gz /usr/share/man/man1/eb_client_linux_kernel.1.gz %changelog entropybroker-2.9/encrypt_stream.cpp000066400000000000000000000012601305163522000200300ustar00rootroot00000000000000#include #include #include "error.h" #include "encrypt_stream.h" #include "encrypt_stream_3des.h" #include "encrypt_stream_aes.h" #include "encrypt_stream_blowfish.h" #include "encrypt_stream_camellia.h" encrypt_stream::encrypt_stream() { } encrypt_stream::~encrypt_stream() { } encrypt_stream * encrypt_stream::select_cipher(std::string type) { if (type == "3des") return new encrypt_stream_3des(); if (type == "aes") return new encrypt_stream_aes(); if (type == "blowfish") return new encrypt_stream_blowfish(); if (type == "camellia") return new encrypt_stream_camellia(); error_exit("Cipher '%s' is not known", type.c_str()); return NULL; } entropybroker-2.9/encrypt_stream.h000066400000000000000000000007661305163522000175070ustar00rootroot00000000000000class encrypt_stream { public: encrypt_stream(); virtual ~encrypt_stream(); static encrypt_stream * select_cipher(std::string type); virtual int get_ivec_size() = 0; virtual int get_key_size() = 0; virtual bool init(unsigned char *key, int key_len, unsigned char *ivec, bool force=false) = 0; virtual std::string get_name() = 0; virtual void encrypt(unsigned char *p_in, int len, unsigned char *p_out) = 0; virtual void decrypt(unsigned char *p_in, int len, unsigned char *p_out) = 0; }; entropybroker-2.9/encrypt_stream_3des.cpp000066400000000000000000000035671305163522000207620ustar00rootroot00000000000000#include #include #include #include "encrypt_stream.h" #include "encrypt_stream_3des.h" #include "utils.h" encrypt_stream_3des::encrypt_stream_3des() { enc = NULL; dec = NULL; } encrypt_stream_3des::~encrypt_stream_3des() { delete enc; delete dec; } int encrypt_stream_3des::get_ivec_size() { return CryptoPP::DES_EDE3::BLOCKSIZE; } int encrypt_stream_3des::get_key_size() { return CryptoPP::DES_EDE3::DEFAULT_KEYLENGTH; } bool encrypt_stream_3des::init(unsigned char *key_in, int key_len, unsigned char *ivec_in, bool force) { my_assert(key_len > 0); #ifdef CRYPTO_DEBUG printf("KEY: "); hexdump(key_in, key_len); printf("IVEC STRT: "); hexdump(ivec_in, 8); #endif if (enc) delete enc; if (dec) delete dec; unsigned char dummy[24] = { 0 }; memcpy(dummy, key_in, std::min(int(sizeof dummy), key_len)); enc = new CryptoPP::CFB_Mode::Encryption(dummy, sizeof dummy, ivec_in); dec = new CryptoPP::CFB_Mode::Decryption(dummy, sizeof dummy, ivec_in); return true; } std::string encrypt_stream_3des::get_name() { return "3des"; } void encrypt_stream_3des::encrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("ORG: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif enc -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ENC: "); hexdump(p_out, len); #endif } void encrypt_stream_3des::decrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("DEC: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif dec -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ORG: "); hexdump(p_out, len); #endif } entropybroker-2.9/encrypt_stream_3des.h000066400000000000000000000011071305163522000204130ustar00rootroot00000000000000#include #include class encrypt_stream_3des : public encrypt_stream { private: CryptoPP::CFB_Mode::Encryption *enc; CryptoPP::CFB_Mode::Decryption *dec; public: encrypt_stream_3des(); ~encrypt_stream_3des(); int get_ivec_size(); int get_key_size(); bool init(unsigned char *key, int key_len, unsigned char *ivec, bool force=false); std::string get_name(); void encrypt(unsigned char *p_in, int len, unsigned char *p_out); void decrypt(unsigned char *p_in, int len, unsigned char *p_out); }; entropybroker-2.9/encrypt_stream_aes.cpp000066400000000000000000000036551305163522000206720ustar00rootroot00000000000000#include #include #include #include #include "error.h" #include "encrypt_stream.h" #include "encrypt_stream_aes.h" #include "utils.h" encrypt_stream_aes::encrypt_stream_aes() { enc = NULL; dec = NULL; } encrypt_stream_aes::~encrypt_stream_aes() { delete enc; delete dec; } int encrypt_stream_aes::get_ivec_size() { return CryptoPP::AES::BLOCKSIZE; } int encrypt_stream_aes::get_key_size() { return CryptoPP::AES::DEFAULT_KEYLENGTH; } bool encrypt_stream_aes::init(unsigned char *key_in, int key_len, unsigned char *ivec_in, bool force) { my_assert(key_len > 0); #ifdef CRYPTO_DEBUG printf("KEY: "); hexdump(key_in, key_len); #endif unsigned char key_use[CryptoPP::AES::DEFAULT_KEYLENGTH] = { 0 }; memcpy(key_use, key_in, std::min(CryptoPP::AES::DEFAULT_KEYLENGTH, key_len)); if (enc) delete enc; if (dec) delete dec; enc = new CryptoPP::CFB_Mode::Encryption(key_use, CryptoPP::AES::DEFAULT_KEYLENGTH, ivec_in); dec = new CryptoPP::CFB_Mode::Decryption(key_use, CryptoPP::AES::DEFAULT_KEYLENGTH, ivec_in); return true; } std::string encrypt_stream_aes::get_name() { return "aes"; } void encrypt_stream_aes::encrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("ORG: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif enc -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ENC: "); hexdump(p_out, len); #endif } void encrypt_stream_aes::decrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("DEC: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif dec -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ORG: "); hexdump(p_out, len); #endif } entropybroker-2.9/encrypt_stream_aes.h000066400000000000000000000010721305163522000203260ustar00rootroot00000000000000#include #include class encrypt_stream_aes : public encrypt_stream { private: CryptoPP::CFB_Mode::Encryption *enc; CryptoPP::CFB_Mode::Decryption *dec; public: encrypt_stream_aes(); ~encrypt_stream_aes(); int get_ivec_size(); int get_key_size(); bool init(unsigned char *key, int key_len, unsigned char *ivec, bool force=false); std::string get_name(); void encrypt(unsigned char *p_in, int len, unsigned char *p_out); void decrypt(unsigned char *p_in, int len, unsigned char *p_out); }; entropybroker-2.9/encrypt_stream_blowfish.cpp000066400000000000000000000034451305163522000217340ustar00rootroot00000000000000#include #include #include #include #include "encrypt_stream.h" #include "encrypt_stream_blowfish.h" #include "utils.h" encrypt_stream_blowfish::encrypt_stream_blowfish() { enc = NULL; dec = NULL; } encrypt_stream_blowfish::~encrypt_stream_blowfish() { delete enc; delete dec; } int encrypt_stream_blowfish::get_ivec_size() { return CryptoPP::Blowfish::BLOCKSIZE; } int encrypt_stream_blowfish::get_key_size() { return CryptoPP::Blowfish::DEFAULT_KEYLENGTH; } bool encrypt_stream_blowfish::init(unsigned char *key_in, int key_len, unsigned char *ivec_in, bool force) { my_assert(key_len > 0); #ifdef CRYPTO_DEBUG printf("KEY: "); hexdump(key_in, key_len); #endif if (enc) delete enc; if (dec) delete dec; enc = new CryptoPP::CFB_Mode::Encryption(key_in, key_len, ivec_in); dec = new CryptoPP::CFB_Mode::Decryption(key_in, key_len, ivec_in); return true; } std::string encrypt_stream_blowfish::get_name() { return "blowfish"; } void encrypt_stream_blowfish::encrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("ORG: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif enc -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ENC: "); hexdump(p_out, len); #endif } void encrypt_stream_blowfish::decrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("DEC: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif dec -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ORG: "); hexdump(p_out, len); #endif } entropybroker-2.9/encrypt_stream_blowfish.h000066400000000000000000000011301305163522000213660ustar00rootroot00000000000000#include #include class encrypt_stream_blowfish : public encrypt_stream { private: CryptoPP::CFB_Mode::Encryption *enc; CryptoPP::CFB_Mode::Decryption *dec; public: encrypt_stream_blowfish(); ~encrypt_stream_blowfish(); int get_ivec_size(); int get_key_size(); bool init(unsigned char *key, int key_len, unsigned char *ivec, bool force=false); std::string get_name(); void encrypt(unsigned char *p_in, int len, unsigned char *p_out); void decrypt(unsigned char *p_in, int len, unsigned char *p_out); }; entropybroker-2.9/encrypt_stream_camellia.cpp000066400000000000000000000040261305163522000216620ustar00rootroot00000000000000#include #include #include #include #include "error.h" #include "encrypt_stream.h" #include "encrypt_stream_camellia.h" #include "utils.h" encrypt_stream_camellia::encrypt_stream_camellia() { enc = NULL; dec = NULL; } encrypt_stream_camellia::~encrypt_stream_camellia() { delete enc; delete dec; } int encrypt_stream_camellia::get_ivec_size() { return CryptoPP::Camellia::BLOCKSIZE; } int encrypt_stream_camellia::get_key_size() { return CryptoPP::Camellia::DEFAULT_KEYLENGTH; } bool encrypt_stream_camellia::init(unsigned char *key_in, int key_len, unsigned char *ivec_in, bool force) { my_assert(key_len > 0); #ifdef CRYPTO_DEBUG printf("KEY: "); hexdump(key_in, key_len); #endif unsigned char temp_key[CryptoPP::Camellia::DEFAULT_KEYLENGTH] = { 0 }; memcpy(temp_key, key_in, std::min(CryptoPP::Camellia::DEFAULT_KEYLENGTH, key_len)); if (enc) delete enc; if (dec) delete dec; enc = new CryptoPP::CFB_Mode::Encryption(temp_key, CryptoPP::Camellia::DEFAULT_KEYLENGTH, ivec_in); dec = new CryptoPP::CFB_Mode::Decryption(temp_key, CryptoPP::Camellia::DEFAULT_KEYLENGTH, ivec_in); return true; } std::string encrypt_stream_camellia::get_name() { return "camellia"; } void encrypt_stream_camellia::encrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("ORG: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif enc -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ENC: "); hexdump(p_out, len); #endif } void encrypt_stream_camellia::decrypt(unsigned char *p, int len, unsigned char *p_out) { my_assert(len > 0); #ifdef CRYPTO_DEBUG printf("DEC: "); hexdump(p, len); printf("EIV %d before: ", ivec_offset); hexdump(ivec, 8); #endif dec -> ProcessData(p_out, p, len); #ifdef CRYPTO_DEBUG printf("EIV %d after: ", ivec_offset); hexdump(ivec, 8); printf("ORG: "); hexdump(p_out, len); #endif } entropybroker-2.9/encrypt_stream_camellia.h000066400000000000000000000011301305163522000213200ustar00rootroot00000000000000#include #include class encrypt_stream_camellia : public encrypt_stream { private: CryptoPP::CFB_Mode::Encryption *enc; CryptoPP::CFB_Mode::Decryption *dec; public: encrypt_stream_camellia(); ~encrypt_stream_camellia(); int get_ivec_size(); int get_key_size(); bool init(unsigned char *key, int key_len, unsigned char *ivec, bool force=false); std::string get_name(); void encrypt(unsigned char *p_in, int len, unsigned char *p_out); void decrypt(unsigned char *p_in, int len, unsigned char *p_out); }; entropybroker-2.9/entropy_broker.conf000066400000000000000000000062651305163522000202120ustar00rootroot00000000000000# $Revision$ # each pool is 4Kb (512 bytes) max_number_of_mem_pools = 512 # maximum number of files in cache-dir (see Makefile) # a file can contain 1 or more pools max_number_of_disk_pools = 256 # if the number of full memory pools is reached, try to store # at least 'min_store_on_disk_n' pools in a disk-file # if the maximum number of files in the cache-dir is reached, # no new files are created and the new data is mixed into the # existing memory pools min_store_on_disk_n = 5 # network parameters # to what network interface to bind. use 0.0.0.0 to listen to # all network interfaces listen_adapter = 0.0.0.0 listen_port = 55225 # don't change this one: listen_queue_size = 5 # for lower latency disable_nagle = 0 enable_keepalive = 1 ping_interval = 299 # default pool size # if disk-pools are different in size, then the size of that disk-pool is used(!) # so this setting is for new pools pool_size_in_bytes = 2048 # default maximum bps, can also set the third field in # the users.txt to a per-user value default_max_get_bps = 4096 # how many bits may be put/get in one go # do not change this after clients/servers have connected max_get_put_size = 32768 ## the following two settings are for the pool management # aes, 3des, camellia or blowfish stirrer_type = aes # md5, ripemd160, whirlpool or sha512 hash_type = sha512 ## the following three settings are for the network protocol encryption # encryption method stream_cipher = 3des # hash to verify if the data did not get altered mac_hasher = md5 #mac_hasher = sha512 # hash to use during authentication handshake hash_hasher = sha512 #hash_hasher = ripemd160 # with what algorithm must the broker estimate the information # amount in the data. can be either shannon or compression. # compression is slower, shannon is more conservative bitcount_estimator = shannon # mostly used for client statistics reset_counters_interval = 60 # how often to emit statistics statistics_interval = 300 # how often to ask a client how full it's kernel pool is kernelpool_filled_interval = 3600 # to what file to write statistics to # needs a full path # stats_file = communication_timeout = 15 communication_session_timeout = 3600 default_sleep_time_when_pools_full = 10 default_sleep_when_pools_empty = 16 default_max_sleep_when_pools_empty = 60 # how many bits a client may retrieve per interval, not used currently default_max_bits_per_interval = 16000000 # see http://en.wikipedia.org/wiki/FIPS_140 ignore_rngtest_fips140 = 1 # calc. the serial correlation coefficient? ignore_rngtest_scc = 1 # thrwshold at which the data will fail scc_threshold = 0.2 # an event is a request coming in allow_event_entropy_addition = 1 # might improve the randomness at cost of more cputime add_entropy_even_if_all_full = 0 # if the pools are empty, behave like a prng allow_prng = 0 # when the pools are all full, allow every x seconds # to stir new entropy data in them when_pools_full_allow_submit_interval = 15 # this password-file must be given to the client/server processes using the -X parameter users = users.txt # set port to -1 to disable webserver_interface = 0.0.0.0 webserver_port = 48923 # graph_font = /usr/share/fonts/truetype/freefont/FreeMono.ttf entropybroker-2.9/entropybroker_infrastructure.svg000066400000000000000000000025221305163522000230550ustar00rootroot00000000000000 Page-1 Dynamic connector.49 entropybroker-2.9/error.cpp000066400000000000000000000016131305163522000161240ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "utils.h" void error_exit(const char *format, ...) { char buffer[4096]; va_list ap; va_start(ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end(ap); set_loglevel(255); dolog(LOG_CRIT, "FATAL|%s|%s", get_current_thread_name().c_str(), buffer); dolog(LOG_CRIT, "FATAL|%s|errno at that time: %d (%s)", get_current_thread_name().c_str(), errno, strerror(errno)); void *trace[128]; int trace_size = backtrace(trace, 128); char **messages = backtrace_symbols(trace, trace_size); dolog(LOG_CRIT, "Execution path:"); for(int index=0; index error = the data is not so random as one * would expect), it'll take up to 20k bits before the tester says "ok" * again. That is not a bug, it's expected behaviour. */ #include #include #include #include #include #include #include #include "error.h" #include "log.h" #include "fips140.h" /* array with numberofbitssetto1 */ unsigned char fips140::fips140_bit1cnt[256]; void fips140::init() { /* generate table with number of bits-set-to-1 for each number */ memset(fips140_bit1cnt, 0x00, sizeof fips140_bit1cnt); for(int loop=0; loop<256; loop++) { for(int bit=1; bit<256; bit<<=1) { if (loop & bit) fips140_bit1cnt[loop]++; } } } fips140::fips140() : user(NULL) { memset(fips140_rval, 0x00, sizeof fips140_rval); memset(fips140_pokerbuf, 0x00, sizeof fips140_pokerbuf); fips140_p = fips140_nbits = fips140_nnewbits = fips140_n1 = 0; stats_t.monobit = stats_t.poker = stats_t.longrun = stats_t.runs = 0; fips_version = 2; } fips140::~fips140() { free(user); } void fips140::set_user(const char *puser) { free(user); user = strdup(puser); if (!user) error_exit("memory allocation error"); dolog(LOG_DEBUG, "registered fips140-user %s", user); } void fips140::set_fips_version(int version) { if (version != 1 && version != 2) error_exit("fips version should be 1 or 2, not %d", version); fips_version = version; } void fips140::add(unsigned char newval) { unsigned char old = fips140_rval[fips140_p]; /* get old value */ fips140_rval[fips140_p] = newval; /* remember new value */ fips140_p++; /* go to next */ if (fips140_p == (20000/8)) fips140_p=0; /* ringbuffer */ /* keep track of number of bits in ringbuffer */ if (fips140_nbits == 20000) { /* buffer full, forget old stuff */ fips140_n1 -= fips140_bit1cnt[old]; /* monobit test */ fips140_pokerbuf[old & 15]--; /* poker test */ fips140_pokerbuf[old >> 4]--; } else /* another 8 bits added */ { fips140_nbits += 8; } /* keep track of # new bits since last longtest */ if (fips140_nnewbits < 20000) /* prevent overflowwraps */ { fips140_nnewbits += 8; } /* there must be about 50% of 1's in the bitstream * (monobit test) */ fips140_n1 += fips140_bit1cnt[newval]; /* keep track of n1-counts */ /* poker test */ fips140_pokerbuf[newval & 15]++; /* do the 2 nibbles */ fips140_pokerbuf[newval >> 4]++; } bool fips140::fips140_shorttest() { int loop; int total=0; double X; /* we can only say anything on this data when there had been * enough data to evaluate */ if (fips140_nbits != 20000) { return true; } /* monobit test */ if ((fips_version == 2 && (fips140_n1<=9725 || fips140_n1 >= 10275)) || /* passwd if 9725 < n1 < 10275 */ (fips_version == 1 && (fips140_n1<=9654 || fips140_n1 >= 10346))) { dolog(LOG_CRIT, "fips140|%s: monobit test failed! [%d]", user, fips140_n1); stats_t.monobit++; return false; } /* poker test */ /* X = (16/5000) * (E[f(i)]^2, 0<=i<=15) - 5000 * -passed if 1.03 < X < 57.4 <-- 140-1 * +passwd if 2.16 < X < 46.17 <-- 140-2 */ for(loop=0; loop<16; loop++) { total += (fips140_pokerbuf[loop]*fips140_pokerbuf[loop]); } X = (16.0/5000.0) * double(total) - 5001.0; if ((fips_version == 2 && (X<=2.16 || X>=46.17)) || (fips_version == 1 && (X<=1.03 || X>=57.4))) { dolog(LOG_CRIT, "fips140|%s: poker test failed! [%f]", user, X); stats_t.poker++; return false; } /* well, as far as we could see here, all is fine */ return true; } #define fips140_checkinterval(index, min, max) \ ((runlencounts[(index)][0]<=(min) || runlencounts[(index)][0]>=(max) || \ runlencounts[(index)][1]<=(min) || runlencounts[(index)][1]>=(max)) \ ? 0 : 1) /* warning; this one also invokes the short test(!) */ bool fips140::fips140_longtest() { int byteindex; int lastbit=0; int runlength=0; int runlencounts[7][2]; char nok=0; memset(runlencounts, 0x00, sizeof runlencounts); /* first see if the shorttest fails. no need to do * the long one if the short one is failing already */ if (fips140_shorttest() == 0) { return false; } /* go trough all 20.000 bits */ for(byteindex=0; byteindex<(20000/8); byteindex++) { int bitindex; /* get a byte */ unsigned char curbyte = fips140_rval[byteindex]; /* test all bits in this byte */ for(bitindex=0; bitindex<8; bitindex++) { /* first bit? */ if (byteindex==0 && bitindex==0) { lastbit = (curbyte & 128)?1:0; runlength = 1; } else /* not the first bit, so evaluate */ { int curbit = (curbyte & 128)?1:0; /* this bit is the same as the previous one */ if (curbit == lastbit) { runlength++; /* test for long-run (34 or more bits * with same value) */ if ((fips_version == 2 && runlength >= 26) || /* 140-2 */ (fips_version == 1 && runlength >= 34)) { dolog(LOG_CRIT, "fips140|%s: long-run failed! [%d]", user, runlength); stats_t.longrun++; return false; } } else { /* remember this bit */ lastbit = curbit; /* keep track of run-lengths */ if (runlength > 6){runlength=6;} (runlencounts[runlength][curbit])++; /* reset to runlength=1 */ runlength = 1; } } /* go the next bit */ curbyte <<= 1; } } /* take also care of the last run! */ if (runlength) { /* keep track of run-lengths */ if (runlength > 6){runlength=6;} runlencounts[runlength][lastbit]++; } /* now we evaluated all bits, reset new-bits-counter */ fips140_nnewbits = 0; /* now we have the frequencies of all runs */ /* verify their frequency of occurence */ if (fips_version == 1) { nok |= !fips140_checkinterval(1, 2267, 2733); nok |= !fips140_checkinterval(2, 1079, 1421); nok |= !fips140_checkinterval(3, 502, 748); nok |= !fips140_checkinterval(4, 223, 402); nok |= !fips140_checkinterval(5, 90, 223); nok |= !fips140_checkinterval(6, 90, 223); } else if (fips_version == 2) { nok |= !fips140_checkinterval(1, 2343, 2657); nok |= !fips140_checkinterval(2, 1135, 1365); nok |= !fips140_checkinterval(3, 542, 708); nok |= !fips140_checkinterval(4, 251, 373); nok |= !fips140_checkinterval(5, 111, 201); nok |= !fips140_checkinterval(6, 111, 201); } if (nok) { dolog(LOG_CRIT, "fips140|%s: runs-test failed!", user); stats_t.runs++; return false; } /* this is a fine set of random values */ return true; } bool fips140::is_ok() { if (fips140_nnewbits >= 2495) { return fips140_longtest(); } return fips140_shorttest(); } char *fips140::stats() { static char stats_buffer[4096]; snprintf(stats_buffer, sizeof stats_buffer, "monobit: %d, poker: %d, longrun: %d, runs: %d", stats_t.monobit, stats_t.poker, stats_t.longrun, stats_t.runs); return stats_buffer; } entropybroker-2.9/fips140.h000066400000000000000000000014601305163522000156260ustar00rootroot00000000000000class fips140 { /* ringbuffer of 20000 bits */ unsigned char fips140_rval[20000/8]; /* point to current, ehr, thing */ int fips140_p; /* number of bits in ringbuffer */ int fips140_nbits; /* number of new bits after a long-test */ int fips140_nnewbits; /* number of bits set to 1 (monobit test) */ int fips140_n1; /* for poker test */ int fips140_pokerbuf[16]; /* where to store statistics */ struct { int monobit; int poker; int longrun; int runs; } stats_t; int fips_version; char *user; static unsigned char fips140_bit1cnt[256]; bool fips140_shorttest(); bool fips140_longtest(); public: fips140(); ~fips140(); static void init(); void set_fips_version(int version); void set_user(const char *puser); void add(unsigned char newval); bool is_ok(); char *stats(); }; entropybroker-2.9/graph.cpp000066400000000000000000000151461305163522000161020ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "utils.h" #include "graph.h" graph::graph(std::string font_in) : font(font_in) { } graph::~graph() { } void graph::calc_text_width(std::string font_descr, double font_height, std::string str, int *width, int *height) { int brect[8]; const char *err = gdImageStringFT(NULL, &brect[0], 0, (char *)font_descr.c_str(), font_height, 0., 0, 0, (char *)str.c_str()); if (err) error_exit("Failed working with %s: %s", font_descr.c_str(), err); *width = brect[2] - brect[6]; *height = brect[3] - brect[7]; } void graph::draw_text(gdImagePtr im, std::string font_descr, double font_height, int color, std::string str, int x, int y) { int brect[8]; gdImageStringFT(im, &brect[0], color, (char *)font_descr.c_str(), font_height, 0., x, y, (char *)str.c_str()); } std::string graph::shorten(double value) { double chk = fabs(value); double divider = 1.0; std::string si; if (chk >= 1000000000000.0) { si = "T"; divider = 1000000000000.0; } else if (chk >= 1000000000.0) { si = "G"; divider = 1000000000.0; } else if (chk >= 1000000.0) { si = "M"; divider = 1000000.0; } else if (chk >= 1000.0) { si = "k"; divider = 1000.0; } else if (chk == 0.0) return "0"; else if (chk <= 0.000001) { si = "u"; divider = 0.000001; } else if (chk <= 0.001) { si = "m"; divider = 0.001; } std::string dummy = format("%.0f", value / divider); int len = dummy.length(); if (len < 3) { std::string fmt = "%." + format("%d", 3 - len) + "f"; dummy = format(fmt.c_str(), value / divider); } return dummy + si; } void graph::do_draw(int width, int height, std::string title, long int *ts, double *values, int n_values, char **result, size_t *result_len) { int yAxisTop = (!title.empty()) ? 12 : 5; int yAxisBottom = height - 25; int yTicks = 10; int xTicks = -1; int xAxisLeft = -1; int xAxisRight = width - 5; int font_height = 10; gdImagePtr im = gdImageCreate(width, height); int black = gdImageColorAllocate(im, 0, 0, 0); int gray = gdImageColorAllocate(im, 64, 64, 64); int white = gdImageColorAllocate(im, 255, 255, 255); int red = gdImageColorAllocate(im, 255, 0, 0); int green = gdImageColorAllocate(im, 0, 255, 0); // determine center of date string int dateWidth = -1, dummy; calc_text_width(font, 10.0, "8888/88/88", &dateWidth, &dummy); int timeWidth = -1; calc_text_width(font, 10.0, "88:88:88", &timeWidth, &dummy); double dataMin = 99999999999.9; double dataMax = -99999999999.9; double tMin = 99999999999.9; double tMax = -99999999999.9; double avg = 0.0; for(int index=0; index tMax) tMax = ts[index]; if (values[index] > dataMax) dataMax = values[index]; avg += values[index]; } avg /= double(n_values); // determine x-position of y-axis std::string use_width = "9999W"; if (dataMin < 0) use_width = "-9999W"; calc_text_width(font, font_height, use_width, &xAxisLeft, &dummy); xAxisLeft++; // 1 pixel extra space between text and lines xTicks = (width - xAxisLeft) / dateWidth; double scaleX = (double)(xAxisRight - xAxisLeft) / (double)(tMax - tMin); double scaleY = (double)(yAxisBottom - yAxisTop) / (dataMax - dataMin); double scaleT = (double)(tMax - tMin) / (double)xTicks; if (!title.empty()) { int textWidth = -1; calc_text_width(font, 10.0, title, &textWidth, &dummy); int plotX = (width / 2) - (textWidth / 2); draw_text(im, font, font_height, white, title, plotX, 9); } gdImageLine(im, xAxisLeft, yAxisTop, xAxisLeft, yAxisBottom, black); gdImageLine(im, xAxisLeft, yAxisBottom, xAxisRight, yAxisBottom, black); // draw ticks horizonal for(int xti=0; xti<=xTicks; xti++) { int x = (double(xAxisRight - xAxisLeft) * double(xti)) / double(xTicks) + xAxisLeft; time_t epoch = tMin + scaleT * double(xti); struct tm *tm = localtime(&epoch); char buffer[128]; strftime(buffer, sizeof buffer, "%Y/%m/%d", tm); std::string strDate = std::string(buffer); strftime(buffer, sizeof buffer, "%H:%M:%S", tm); std::string strTime = std::string(buffer); if (xti > 0) gdImageLine(im, x, yAxisTop + 1, x, yAxisBottom, gray); bool date = true; int xPosDate = -1, xPosTime = -1; if (xti == 0) xPosTime = xPosDate = std::max(0, x - dateWidth / 2); else if (xti == xTicks) { xPosDate = width - dateWidth; xPosTime = width - timeWidth; } else if (xti == xTicks - 1) { xPosTime = xPosDate = x - (dateWidth * 5) / 8; date = false; } else { xPosTime = xPosDate = x - dateWidth / 2; } draw_text(im, font, font_height, white, strTime, xPosTime, yAxisBottom + 14); if (date) draw_text(im, font, font_height, white, strDate, xPosDate, yAxisBottom + 24); gdImageLine(im, x, yAxisBottom, x, yAxisBottom + 2, black); } // draw ticks vertical for(int yti=0; yti<=yTicks; yti++) { int y = (double(yAxisBottom - yAxisTop) * double(yti)) / double(yTicks) + yAxisTop; gdImageLine(im, xAxisLeft - 2, y, xAxisLeft, y, black); double value = (((dataMax - dataMin) / double(yTicks)) * double(yTicks - yti) + dataMin); std::string str = shorten(value); gdImageLine(im, xAxisLeft + 1, y, xAxisRight, y, gray); draw_text(im, font, font_height, white, str, 1, y == yAxisTop ? y + 6 : y + 3); } // draw data if (n_values > 1 && dataMax - dataMin > 0.001) { bool first = true; int yPrev = -1, xPrev = -1; for(int index=0; index #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "log.h" #include "math.h" #include "hasher.h" #include "stirrer.h" #include "fips140.h" #include "hasher_type.h" #include "stirrer_type.h" #include "scc.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "statistics_log.h" #include "users.h" #include "encrypt_stream.h" #include "encrypt_stream_blowfish.h" #include "config.h" #include "handle_client.h" #include "utils.h" #include "signals.h" #include "auth.h" #include "protocol.h" #include "hc_protocol.h" const char *pipe_cmd_str[] = { NULL, "have data (1)", "need data (2)", "is full (3)", "quit" }; extern const char *pid_file; long long int client_id = 1; void forget_client_index(statistics_global *sg, std::vector *clients, int nr, bool force) { client_t *p = clients -> at(nr); double now_ts = get_ts(); double since_ts = p -> connected_since; sg -> put_history_log(HL_LOGOUT_OK, p -> host, p -> type, p -> username, since_ts, now_ts - since_ts, ""); close(p -> socket_fd); close(p -> to_thread[1]); close(p -> to_thread[0]); close(p -> to_main[0]); my_yield(); if (force) { int ok[] = { ESRCH, 0 }; pthread_check(pthread_cancel(p -> th), "pthread_cancel", ok); } void *value_ptr = NULL; pthread_check(pthread_join(p -> th, &value_ptr), "pthread_join"); pthread_check(pthread_mutex_destroy(&p -> stats_lck), "pthread_mutex_destroy"); delete p -> pfips140; delete p -> pscc; delete p -> pc; delete p; clients -> erase(clients -> begin() + nr); } client_t *find_client_by_id(std::vector *clients, long long int id_in) { for(unsigned int index=0; index size(); index++) { if (clients -> at(index) -> id == id_in) return clients -> at(index); } return NULL; } void forget_client_thread_id(statistics_global *sg, std::vector *clients, pthread_t *tid, bool force) { for(unsigned int index=0; index size(); index++) { if (pthread_equal(clients -> at(index) -> th, *tid) != 0) { forget_client_index(sg, clients, index, force); break; } } } int send_pipe_command(int fd, unsigned char command) { // printf("SEND TO MAIN %s\n", pipe_cmd_str[command]); for(;;) { int rc = write(fd, &command, 1); if (rc == 0) return -1; if (rc == -1) { if (errno == EINTR) continue; return -1; } break; } return 0; } int send_request_result_to_main_thread(bool is_server, int fd, bool no_bits, bool new_bits, bool is_full) { int rc_pipe = 0; if (is_server) { if (new_bits) rc_pipe |= send_pipe_command(fd, PIPE_CMD_HAVE_DATA); if (is_full) rc_pipe |= send_pipe_command(fd, PIPE_CMD_IS_FULL); } else { if (no_bits) rc_pipe |= send_pipe_command(fd, PIPE_CMD_NEED_DATA); } return rc_pipe != 0 ? -1 : 0; } int send_request_from_main_to_clients(client_t *p) { bool need_data = false, have_data = false, is_full = false; for(;;) { unsigned char cmd = 0; int rc_pipe = read(p -> to_thread[0], &cmd, 1); if (rc_pipe == 0) return -1; if (rc_pipe == -1) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) break; dolog(LOG_CRIT, "Thread connection to main thread lost (2)"); return -1; } if (cmd == PIPE_CMD_NEED_DATA) { need_data = true; have_data = false; is_full = false; } else if (cmd == PIPE_CMD_HAVE_DATA) { need_data = false; have_data = true; is_full = false; } else if (cmd == PIPE_CMD_IS_FULL) { need_data = false; have_data = false; is_full = true; } else if (cmd == PIPE_CMD_QUIT) { return -1; } else { error_exit("Unknown interprocess command %02x", cmd); } } int rc_client = 0; if (need_data && rc_client == 0) rc_client = notify_server_data_needed(p -> socket_fd, p -> config); if (have_data && rc_client == 0) rc_client = notify_client_data_available(p -> socket_fd, p -> ppools, p -> config); if (is_full && rc_client == 0) rc_client = notify_server_full(p -> socket_fd, p -> config); if (rc_client) { dolog(LOG_INFO, "Connection with %s lost", p -> host.c_str()); p -> pu -> inc_network_error(p -> username); p -> stats_glob -> inc_network_error(); return -1; } return 0; } void * thread(void *data) { client_t *p = (client_t *)data; set_thread_name("eb:cl_se"); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); if (p -> config -> disable_nagle) disable_nagle(p -> socket_fd); if (p -> config -> enable_keepalive) enable_tcp_keepalive(p -> socket_fd); encrypt_stream *es = encrypt_stream::select_cipher(p -> config -> stream_cipher); p -> stream_cipher = es; hasher *mh = hasher::select_hasher(p -> config -> mac_hasher); p -> mac_hasher = mh; unsigned char *ivec = reinterpret_cast(malloc(es -> get_ivec_size())); if (!ivec) error_exit("malloc failure"); for(;;) { long long unsigned int auth_rnd = 1; bool ok = auth_eb(p -> socket_fd, p -> config -> communication_timeout, p -> pu, p -> username, p -> password, &auth_rnd, &p -> is_server, p -> type, p -> pc -> get_random_source(), es, mh, p -> config -> hash_hasher, p -> config -> max_get_put_size, p -> stats_glob) == 0; if (!ok) { dolog(LOG_WARNING, "main|client: %s (fd: %d) authentication failed", p -> host.c_str(), p -> socket_fd); break; } dolog(LOG_INFO, "Thread id: %d, fd: %d, user: %s, type: %s, host: %s", gettid(), p -> socket_fd, p -> username.c_str(), p -> type.c_str(), p -> host.c_str()); p -> challenge = auth_rnd; p -> ivec_counter = 0; calc_ivec(p -> password.c_str(), p -> challenge, p -> ivec_counter, es -> get_ivec_size(), ivec); // printf("IVEC: "); hexdump(ivec, 8); set_thread_name(p -> username + "_" + (p -> is_server ? "1":"0")); unsigned char *pw_char = reinterpret_cast(const_cast(p -> password.c_str())); if (!es -> init(pw_char, p -> password.length(), ivec)) { dolog(LOG_CRIT, "Password for %s too weak (fd: %d)", p -> username.c_str(), p -> socket_fd); break; } for(;;) { std::vector fds; pollfd fd; fds.clear(); fd.fd = p -> socket_fd; fd.events = POLLIN; fds.push_back(fd); fd.fd = p -> to_thread[0]; fd.events = POLLIN; fds.push_back(fd); int tv = p -> config -> communication_session_timeout * 1000.0; int rc = poll(&fds[0], (nfds_t)fds.size(), tv); if (rc == -1) { if (errno == EINTR) continue; dolog(LOG_CRIT, "poll() failed for thread %s", p -> host.c_str()); break; } else if (rc == 0) { dolog(LOG_CRIT, "host %s fell asleep", p -> host.c_str()); break; } if (fds[0].revents & POLLIN) { bool no_bits = false, new_bits = false, is_full = false; dolog(LOG_DEBUG, "process fd: %d", p -> socket_fd); if (do_client(p, &no_bits, &new_bits, &is_full) == -1) { dolog(LOG_INFO, "Terminating connection with %s (fd: %d)", p -> host.c_str(), p -> socket_fd); break; } if (send_request_result_to_main_thread(p -> is_server, p -> to_main[1], no_bits, new_bits, is_full) != 0) { dolog(LOG_CRIT, "Thread connection to main thread lost (1)"); break; } dolog(LOG_DEBUG, "finished processing fd: %d", p -> socket_fd); } if (fds[1].revents & POLLIN) { dolog(LOG_DEBUG, "process from main to fd: %d", p -> socket_fd); if (send_request_from_main_to_clients(p) != 0) break; dolog(LOG_DEBUG, "process finished from main to fd: %d", p -> socket_fd); } } dolog(LOG_DEBUG, "End of thread imminent (fd: %d)", p -> socket_fd); break; } free(ivec); close(p -> to_main[1]); delete es; delete mh; dolog(LOG_DEBUG, "End of thread (fd: %d)", p -> socket_fd); return NULL; } void register_new_client(int listen_socket_fd, std::vector *clients, users *user_map, config_t *config, pools *ppools, statistics_global *stats, fips140 *output_fips140, scc *output_scc) { int new_socket_fd = accept(listen_socket_fd, NULL, NULL); if (new_socket_fd != -1) { std::string host = get_endpoint_name(new_socket_fd); dolog(LOG_INFO, "main|new client: %s (fd: %d)", host.c_str(), new_socket_fd); client_t *p = new client_t; if (!p) error_exit("memory allocation error"); p -> id = client_id++; p -> socket_fd = new_socket_fd; p -> host = host; p -> type = "?"; p -> is_server = false; p -> pfips140 = new fips140(); p -> pscc = new scc(); if (!p -> pfips140 || !p -> pscc) error_exit("failed allocating fips140/scc object"); p -> pfips140 -> set_user(p -> host.c_str()); p -> pscc -> set_user(p -> host.c_str()); p -> pscc -> set_threshold(config -> scc_threshold); p -> connected_since = get_ts(); p -> ivec_counter = 0; p -> bits_sent = p -> bits_recv = 0; p -> max_bits_per_interval = config -> default_max_bits_per_interval; p -> ignore_rngtest_fips140 = config -> ignore_rngtest_fips140; p -> ignore_rngtest_scc = config -> ignore_rngtest_scc; p -> allow_prng = config -> allow_prng; p -> pc = new pool_crypto(config -> st, config -> ht, config -> rs); if (!p -> pc) error_exit("failed allocating pool_crypto object"); pthread_check(pthread_mutex_init(&p -> stats_lck, &global_mutex_attr), "pthread_mutex_init"); // globals p -> pu = user_map; p -> config = config; p -> ppools = ppools; p -> stats_glob = stats; p -> output_fips140 = output_fips140; p -> output_scc = output_scc; if (pipe(p -> to_thread) == -1) error_exit("Error creating pipes"); set_fd_nonblocking(p -> to_thread[0]); if (pipe(p -> to_main) == -1) error_exit("Error creating pipes"); set_fd_nonblocking(p -> to_main[0]); pthread_check(pthread_create(&p -> th, NULL, thread, p), "pthread_create"); clients -> push_back(p); } } int process_pipe_from_client_thread(client_t *p, std::vector *msgs_clients, std::vector *msgs_servers) { int rc = 0; for(;;) { unsigned char cmd = 0; int rc_pipe = read(p -> to_main[0], &cmd, 1); if (rc_pipe == 0) // means closed! return -1; if (rc_pipe == -1) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) break; rc = -1; break; } // printf("RECV %s FROM %d\n", pipe_cmd_str[cmd], p -> socket_fd); msg_pair_t queue_entry = { p -> socket_fd, cmd }; if (cmd == PIPE_CMD_HAVE_DATA) msgs_clients -> push_back(queue_entry); else if (cmd == PIPE_CMD_NEED_DATA) msgs_servers -> push_back(queue_entry); else if (cmd == PIPE_CMD_IS_FULL) msgs_servers -> push_back(queue_entry); else error_exit("Message %02x from thread %s/%s is not known", cmd, p -> host.c_str(), p -> type.c_str()); } return rc; } void send_to_client_threads(std::vector *clients, std::vector *msgs, bool is_server_in, bool *send_have_data, bool *send_need_data, bool *send_is_full) { // printf("send_to_client_threads\n"); for(unsigned int loop=0; loop size(); loop++) { msg_pair_t *cur_msg = &msgs -> at(loop); if (cur_msg -> cmd == PIPE_CMD_HAVE_DATA) { if (*send_have_data == true) continue; *send_have_data = true; *send_need_data = false; } else if (cur_msg -> cmd == PIPE_CMD_NEED_DATA) { if (*send_need_data == true) continue; *send_need_data = true; *send_have_data = false; } else if (cur_msg -> cmd == PIPE_CMD_IS_FULL) { if (*send_is_full == true) continue; *send_is_full = true; *send_need_data = false; } for(unsigned int index=0; index size(); index++) { client_t *cur_cl = clients -> at(index); if (cur_cl -> is_server == is_server_in && cur_cl -> socket_fd != cur_msg -> fd_sender) (void)send_pipe_command(cur_cl -> to_thread[1], cur_msg -> cmd); } } } void terminate_threads(statistics_global *sg, std::vector *clients) { for(unsigned int index=0; index size(); index++) { client_t *p = clients -> at(index); (void)send_pipe_command(p -> to_thread[1], PIPE_CMD_QUIT); my_yield(); close(p -> socket_fd); close(p -> to_thread[0]); close(p -> to_thread[1]); close(p -> to_main[0]); close(p -> to_main[1]); } while(!clients -> empty()) { client_t *p = clients -> at(0); dolog(LOG_DEBUG, "... %s/%s (fd: %d)", p -> host.c_str(), p -> type.c_str(), p -> socket_fd); forget_client_index(sg, clients, 0, true); } } void main_loop(std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, config_t *config, fips140 *eb_output_fips140, scc *eb_output_scc, pool_crypto *pc, statistics_global *gs, users *user_map) { double last_counters_reset = get_ts(); double last_statistics_emit = last_counters_reset; event_state_t event_state; int listen_socket_fd = start_listen(config -> listen_adapter, config -> listen_port, config -> listen_queue_size); memset(&event_state, 0x00, sizeof event_state); dolog(LOG_INFO, "main|main-loop started"); bool send_have_data = false, send_need_data = false, send_is_full = false; for(;;) { std::vector fds; pollfd fd; double now = get_ts(); struct timespec tv; bool force_stats = false; sigset_t sig_set; if (sigemptyset(&sig_set) == -1) error_exit("sigemptyset"); double time_left = 300.0, dummy1_time = -1.0; if (config -> statistics_interval > 0) { dummy1_time = std::max(0.0, (last_statistics_emit + config -> statistics_interval) - now); time_left = std::min(time_left, dummy1_time); } if (config -> reset_counters_interval > 0) { dummy1_time = std::max(0.0, (last_counters_reset + config -> reset_counters_interval) - now); time_left = std::min(time_left, dummy1_time); } fds.clear(); my_mutex_lock(clients_mutex); for(unsigned int loop=0; loop size(); loop++) { fd.fd = clients -> at(loop) -> to_main[0]; fd.events = POLLIN; fd.revents = 0; fds.push_back(fd); } my_mutex_unlock(clients_mutex); fd.fd = listen_socket_fd; fd.events = POLLIN; fds.push_back(fd); tv.tv_sec = time_left; tv.tv_nsec = (time_left - double(tv.tv_sec)) * 1000000000.0; my_assert(tv.tv_sec >= 0); my_assert(tv.tv_nsec >= 0); if (tv.tv_sec == 0 && tv.tv_nsec == 0) tv.tv_nsec = 1000; int rc = ppoll(&fds[0], (nfds_t) fds.size(), &tv, &sig_set); now = get_ts(); if (is_SIGHUP()) { dolog(LOG_DEBUG, "Got SIGHUP"); reset_SIGHUP(); user_map -> reload(); force_stats = true; } if (is_SIGEXIT()) { dolog(LOG_INFO, "Program stopping due to either SIGTERM, SIGQUIT or SIGINT"); break; } if (rc == -1) { if (errno == EFAULT || errno == ENOMEM || errno == EINVAL) error_exit("ppoll() failed"); if (errno == EINTR) continue; dolog(LOG_DEBUG, "poll returned with -1, errno: %s (%d)", strerror(errno), errno); } my_mutex_lock(clients_mutex); if ((last_counters_reset + double(config -> reset_counters_interval)) <= now || force_stats) { emit_statistics_log(gs, clients -> size(), force_stats, config -> reset_counters_interval, ppools, eb_output_fips140, eb_output_scc); if (!force_stats) { for(unsigned int loop=0; loop size(); loop++) { client_t *p = clients -> at(loop); my_mutex_lock(&p -> stats_lck); p -> bits_recv = p -> bits_sent = 0; my_mutex_unlock(&p -> stats_lck); } } now = last_counters_reset = get_ts(); } if ((config -> statistics_interval != 0 && (last_statistics_emit + double(config -> statistics_interval)) <= now) || force_stats) { if (config -> stats_file) emit_statistics_file(config -> stats_file, gs, ppools, eb_output_scc, clients -> size()); now = last_statistics_emit = get_ts(); } if (force_stats) { for(unsigned int loop=0; loop size(); loop++) { client_t *p = clients -> at(loop); my_mutex_lock(&p -> stats_lck); dolog(LOG_DEBUG, "stats|%s (%s): %s, scc: %s | sent: %d, recv: %d | last msg: %ld seconds ago, %lds connected", p -> host.c_str(), p -> type.c_str(), p -> pfips140 -> stats(), p -> pscc -> stats().c_str(), p -> bits_sent, p -> bits_recv, (long int)(now - p -> pu -> get_last_msg_ts(p -> username)), (long int)(now - p -> connected_since)); my_mutex_unlock(&p -> stats_lck); } now = get_ts(); } my_mutex_unlock(clients_mutex); if (rc == 0) continue; /* if (config -> allow_event_entropy_addition) { int event_bits = ppools -> add_event(now, reinterpret_cast(&rfds), sizeof rfds, double(config -> communication_timeout) * 0.05, pc); if (event_bits > 0) dolog(LOG_DEBUG, "main|added %d bits of event-entropy to pool", event_bits); } */ my_mutex_lock(clients_mutex); std::vector delete_ids; std::vector msgs_clients; std::vector msgs_servers; for(unsigned int loop=0; loop size(); loop++) { // this way we go through each fd in the process_pipe_from_client_thread part // so that we detect closed fds int set = 0; int failed = 0; for(unsigned int i=0; i at(loop) -> to_main[0]) { if(fds.at(i).revents & POLLIN) { set = 1; break; } if(fds.at(i).revents & (POLLERR|POLLHUP|POLLNVAL)) { failed = 1; break; } }; }; if(rc > 0 && set == 1 ) { if (process_pipe_from_client_thread(clients -> at(loop), &msgs_clients, &msgs_servers) == -1) failed = 1; } if(rc > 0 && failed == 1 ) { dolog(LOG_INFO, "main|connection with %s/%s lost", clients -> at(loop) -> host.c_str(), clients -> at(loop) -> type.c_str()); user_map -> inc_misc_errors(clients -> at(loop) -> username); gs -> inc_misc_errors(); delete_ids.push_back(&clients -> at(loop) -> th); } } for(unsigned int loop=0; loop 0 && ( fds.at(fds.size() - 1).revents & POLLIN ) ) { register_new_client(listen_socket_fd, clients, user_map, config, ppools, gs, eb_output_fips140, eb_output_scc); send_have_data = send_need_data = send_is_full = false; } my_mutex_unlock(clients_mutex); } my_mutex_lock(clients_mutex); dolog(LOG_INFO, "Terminating %d threads...", clients -> size()); terminate_threads(gs, clients); my_mutex_unlock(clients_mutex); close(listen_socket_fd); dolog(LOG_INFO, "main|end of main loop"); } entropybroker-2.9/handle_client.h000066400000000000000000000024021305163522000172260ustar00rootroot00000000000000#define PIPE_CMD_HAVE_DATA 1 #define PIPE_CMD_NEED_DATA 2 #define PIPE_CMD_IS_FULL 3 #define PIPE_CMD_QUIT 4 extern const char *pipe_cmd_str[]; typedef struct { int to_thread[2], to_main[2]; pthread_t th; bool allow_rw; int socket_fd; std::string host, type; long long int id; bool is_server; int max_bits_per_interval; bool allow_prng; bool ignore_rngtest_fips140, ignore_rngtest_scc; std::string username, password; fips140 *pfips140; scc *pscc; long long unsigned int ivec_counter; long long unsigned int challenge; encrypt_stream *stream_cipher; hasher *mac_hasher; double connected_since; double last_message, last_put_message, last_get_message; pool_crypto *pc; int bits_sent, bits_recv; pthread_mutex_t stats_lck; // globals users *pu; config_t *config; pools *ppools; statistics_global *stats_glob; fips140 *output_fips140; scc *output_scc; } client_t; typedef struct { int fd_sender; unsigned char cmd; } msg_pair_t; client_t *find_client_by_id(std::vector *clients, long long int id_in); void main_loop(std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, config_t *config, fips140 *eb_output_fips140, scc *eb_output_scc, pool_crypto *pc, statistics_global *stats, users *user_map); entropybroker-2.9/hasher.cpp000066400000000000000000000007431305163522000162500ustar00rootroot00000000000000#include #include "hasher.h" #include "hasher_md5.h" #include "hasher_ripemd160.h" #include "hasher_sha512.h" #include "hasher_whirlpool.h" hasher::hasher() { } hasher::~hasher() { } hasher *hasher::select_hasher(std::string type) { if (type == "md5") return new hasher_md5(); if (type == "ripemd160") return new hasher_ripemd160(); if (type == "sha512") return new hasher_sha512(); if (type == "whirlpool") return new hasher_whirlpool(); return NULL; } entropybroker-2.9/hasher.h000066400000000000000000000004121305163522000157060ustar00rootroot00000000000000class hasher { public: hasher(); virtual ~hasher(); virtual std::string get_name() = 0; static hasher *select_hasher(std::string type); virtual int get_hash_size() const = 0; virtual void do_hash(unsigned char *in, int in_size, unsigned char *dest) = 0; }; entropybroker-2.9/hasher_md5.cpp000066400000000000000000000006541305163522000170160ustar00rootroot00000000000000#include #include "hasher.h" #include "hasher_md5.h" hasher_md5::hasher_md5() { } hasher_md5::~hasher_md5() { } std::string hasher_md5::get_name() { return "md5"; } int hasher_md5::get_hash_size() const { return CryptoPP::Weak::MD5::DIGESTSIZE; } void hasher_md5::do_hash(unsigned char *in, int in_size, unsigned char *dest) { // FIXME thread safe? CryptoPP::Weak::MD5().CalculateDigest(dest, in, in_size); } entropybroker-2.9/hasher_md5.h000066400000000000000000000004141305163522000164550ustar00rootroot00000000000000#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include class hasher_md5 : public hasher { public: hasher_md5(); ~hasher_md5(); std::string get_name(); int get_hash_size() const; void do_hash(unsigned char *in, int in_size, unsigned char *dest); }; entropybroker-2.9/hasher_ripemd160.cpp000066400000000000000000000007131305163522000200340ustar00rootroot00000000000000#include #include "hasher.h" #include "hasher_ripemd160.h" hasher_ripemd160::hasher_ripemd160() { } hasher_ripemd160::~hasher_ripemd160() { } std::string hasher_ripemd160::get_name() { return "ripemd160"; } int hasher_ripemd160::get_hash_size() const { return CryptoPP::RIPEMD160::DIGESTSIZE; } void hasher_ripemd160::do_hash(unsigned char *in, int in_size, unsigned char *dest) { CryptoPP::RIPEMD160().CalculateDigest(dest, in, in_size); } entropybroker-2.9/hasher_ripemd160.h000066400000000000000000000003671305163522000175060ustar00rootroot00000000000000#include class hasher_ripemd160: public hasher { public: hasher_ripemd160(); ~hasher_ripemd160(); std::string get_name(); int get_hash_size() const; void do_hash(unsigned char *in, int in_size, unsigned char *dest); }; entropybroker-2.9/hasher_sha512.cpp000066400000000000000000000006521305163522000173320ustar00rootroot00000000000000#include #include "hasher.h" #include "hasher_sha512.h" hasher_sha512::hasher_sha512() { } hasher_sha512::~hasher_sha512() { } std::string hasher_sha512::get_name() { return "sha512"; } int hasher_sha512::get_hash_size() const { return CryptoPP::SHA512::DIGESTSIZE; } void hasher_sha512::do_hash(unsigned char *in, int in_size, unsigned char *dest) { CryptoPP::SHA512().CalculateDigest(dest, in, in_size); } entropybroker-2.9/hasher_sha512.h000066400000000000000000000003541305163522000167760ustar00rootroot00000000000000#include class hasher_sha512 : public hasher { public: hasher_sha512(); ~hasher_sha512(); std::string get_name(); int get_hash_size() const; void do_hash(unsigned char *in, int in_size, unsigned char *dest); }; entropybroker-2.9/hasher_type.h000066400000000000000000000001001305163522000167410ustar00rootroot00000000000000enum hasher_type { H_SHA512, H_MD5, H_RIPEMD160, H_WHIRLPOOL }; entropybroker-2.9/hasher_whirlpool.cpp000066400000000000000000000007131305163522000203440ustar00rootroot00000000000000#include #include "hasher.h" #include "hasher_whirlpool.h" hasher_whirlpool::hasher_whirlpool() { } hasher_whirlpool::~hasher_whirlpool() { } std::string hasher_whirlpool::get_name() { return "whirlpool"; } int hasher_whirlpool::get_hash_size() const { return CryptoPP::Whirlpool::DIGESTSIZE; } void hasher_whirlpool::do_hash(unsigned char *in, int in_size, unsigned char *dest) { CryptoPP::Whirlpool().CalculateDigest(dest, in, in_size); } entropybroker-2.9/hasher_whirlpool.h000066400000000000000000000003721305163522000200120ustar00rootroot00000000000000#include class hasher_whirlpool : public hasher { public: hasher_whirlpool(); ~hasher_whirlpool(); std::string get_name(); int get_hash_size() const; void do_hash(unsigned char *in, int in_size, unsigned char *dest); }; entropybroker-2.9/hc_protocol.cpp000066400000000000000000000357051305163522000173170ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "log.h" #include "math.h" #include "hasher.h" #include "stirrer.h" #include "fips140.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "encrypt_stream.h" #include "config.h" #include "scc.h" #include "pools.h" #include "utils.h" #include "signals.h" #include "protocol.h" #include "auth.h" #include "handle_client.h" #include "hc_protocol.h" int send_denied_empty(int fd, config_t *config) { int seconds = config -> default_sleep_when_pools_empty; // & default_max_sleep_when_pools_empty unsigned char buffer[4 + 4]; make_msg(buffer, 9000, seconds); return WRITE_TO(fd, buffer, 8, config -> communication_timeout) == 8 ? 0 : -1; } int send_denied_quota(int fd, config_t *config) { unsigned char buffer[4 + 4]; // FIXME use a time which is calculated with the incoming data rate make_msg(buffer, 9002, config -> reset_counters_interval); return WRITE_TO(fd, buffer, 8, config -> communication_timeout) == 8 ? 0 : -1; } int send_denied_full(int fd, config_t *config, std::string host) { unsigned char buffer[4 + 4]; int seconds = config -> default_sleep_time_when_pools_full; make_msg(buffer, 9001, seconds); dolog(LOG_INFO, "denied|%s all pools full, sleep of %d seconds", host.c_str(), seconds); if (WRITE_TO(fd, buffer, 8, config -> communication_timeout) != 8) return -1; return 0; } int send_accepted_while_full(int fd, statistics *stats, config_t *config) { unsigned char buffer[4 + 4]; make_msg(buffer, 9003, config -> default_sleep_time_when_pools_full); if (WRITE_TO(fd, buffer, 8, config -> communication_timeout) != 8) return -1; return 0; } int send_got_data(int fd, pools *ppools, config_t *config) { unsigned char buffer[4 + 4]; // data is an estimate; it can be different anyway as other clients may come first make_msg(buffer, 9, std::min(9999, ppools -> get_bit_sum(config -> communication_timeout))); // 0009 return WRITE_TO(fd, buffer, 8, config -> communication_timeout) == 8 ? 0 : -1; } int send_need_data(int fd, config_t *config) { unsigned char buffer[4 + 4]; make_msg(buffer, 10, 0); // 0010 0000 return WRITE_TO(fd, buffer, 8, config -> communication_timeout) == 8 ? 0 : -1; } void update_client_fips140_scc(client_t *p, unsigned char *data, int n) { for(int index=0; index pfips140 -> add(data[index]); p -> pscc -> add(data[index]); } } int do_client_get(client_t *client, bool *no_bits) { client -> last_get_message = get_ts(); *no_bits = false; unsigned char n_bits[4] = { 255 }; if (READ_TO(client -> socket_fd, n_bits, 4, client -> config -> communication_timeout) != 4) { dolog(LOG_INFO, "get|%s short read while retrieving number of bits to send", client -> host.c_str()); client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); return -1; } int cur_n_bits = uchar_to_uint(n_bits); if (cur_n_bits == 0) { dolog(LOG_INFO, "get|%s 0 bits requested", client -> host.c_str()); client -> pu -> inc_protocol_error(client -> username); client -> stats_glob -> inc_protocol_error(); return -1; } if (cur_n_bits > client -> config -> max_get_put_size) { dolog(LOG_WARNING, "get|%s client requested more than %d bits: %d", client -> host.c_str(), client -> config -> max_get_put_size, cur_n_bits); client -> pu -> inc_protocol_error(client -> username); client -> stats_glob -> inc_protocol_error(); return -1; } dolog(LOG_DEBUG, "get|%s requested %d bits", client -> host.c_str(), cur_n_bits); cur_n_bits = client -> pu -> calc_max_allowance(client -> username, get_ts(), cur_n_bits); dolog(LOG_DEBUG, "get|%s is allowed to now receive %d bits", client -> host.c_str(), cur_n_bits); if (cur_n_bits < 8) { client -> pu -> cancel_allowance(client -> username); client -> pu -> inc_n_times_quota(client -> username); client -> stats_glob -> inc_n_times_quota(); int rc = send_denied_quota(client -> socket_fd, client -> config); if (rc == -1) { client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); } return rc; } int cur_n_bytes = (cur_n_bits + 7) / 8; dolog(LOG_DEBUG, "get|%s memory allocated, retrieving bits", client -> host.c_str()); unsigned char *temp_buffer = NULL; cur_n_bits = client -> ppools -> get_bits_from_pools(cur_n_bits, &temp_buffer, client -> allow_prng, client -> ignore_rngtest_fips140, client -> output_fips140, client -> ignore_rngtest_scc, client -> output_scc, double(client -> config -> communication_timeout) * 0.9, client -> pc); if (cur_n_bits == 0) { free_locked(temp_buffer, cur_n_bytes + 1); client -> pu -> cancel_allowance(client -> username); dolog(LOG_WARNING, "get|%s no bits in pools, sending deny", client -> host.c_str()); *no_bits = true; client -> pu -> inc_n_times_empty(client -> username); client -> stats_glob -> inc_n_times_empty(); int rc = send_denied_empty(client -> socket_fd, client -> config); if (rc == -1) { client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); } return rc; } if (cur_n_bits < 0) error_exit("internal error: %d < 0", cur_n_bits); cur_n_bytes = (cur_n_bits + 7) / 8; dolog(LOG_DEBUG, "get|%s got %d bits from pool", client -> host.c_str(), cur_n_bits); client -> pu -> use_allowance(client -> username, cur_n_bits); int hash_len = client -> mac_hasher -> get_hash_size(); int out_len = cur_n_bytes + hash_len; #ifdef CRYPTO_DEBUG printf("bytes: %d\n", out_len); #endif unsigned char *ent_buffer_in = reinterpret_cast(malloc_locked(out_len)); memcpy(&ent_buffer_in[hash_len], temp_buffer, cur_n_bytes); memset(ent_buffer_in, 0x00, hash_len); client -> mac_hasher -> do_hash(&ent_buffer_in[hash_len], cur_n_bytes, ent_buffer_in); #ifdef CRYPTO_DEBUG printf("send: "); hexdump(ent_buffer_in, hash_len); printf("data: "); hexdump(&ent_buffer_in[hash_len], 8); #endif unsigned char *ent_buffer = reinterpret_cast(malloc(out_len)); if (!ent_buffer) error_exit("error allocating %d bytes of memory", out_len); // encrypt data client -> stream_cipher -> encrypt(ent_buffer_in, out_len, ent_buffer); #ifdef CRYPTO_DEBUG printf("encr: "); hexdump(ent_buffer, 16); #endif // update statistics for accounting my_mutex_lock(&client -> stats_lck); update_client_fips140_scc(client, temp_buffer, cur_n_bytes); client -> bits_sent += cur_n_bits; my_mutex_unlock(&client -> stats_lck); client -> pu -> track_sents(client -> username, cur_n_bits); client -> stats_glob -> track_sents(cur_n_bits); free_locked(temp_buffer, cur_n_bytes + 1); int transmit_size = 4 + 4 + out_len; unsigned char *output_buffer = reinterpret_cast(malloc(transmit_size)); if (!output_buffer) error_exit("error allocating %d bytes of memory", cur_n_bytes); make_msg(output_buffer, 2, cur_n_bits); // 0002 dolog(LOG_DEBUG, "get|%s transmit size: %d, msg: %s", client -> host.c_str(), transmit_size, output_buffer); memcpy(&output_buffer[8], ent_buffer, out_len); free(ent_buffer); free_locked(ent_buffer_in, cur_n_bytes); int rc = 0; if (WRITE_TO(client -> socket_fd, output_buffer, transmit_size, client -> config -> communication_timeout) != transmit_size) { dolog(LOG_INFO, "%s error while sending data to client", client -> host.c_str()); client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); rc = -1; } free(output_buffer); return rc; } int do_client_put(client_t *client, bool *new_bits, bool *is_full) { client -> last_put_message = get_ts(); bool warn_all_full = false; *new_bits = false; if (client -> ppools -> all_pools_full(double(client -> config -> communication_timeout) * 0.9)) { *is_full = true; double last_submit_ago = get_ts() - client -> stats_glob -> get_last_put_msg_ts(); bool full_allow_interval_submit = last_submit_ago >= client -> config -> when_pools_full_allow_submit_interval; if (!(client -> config -> add_entropy_even_if_all_full || full_allow_interval_submit)) { char dummy_buffer[4]; client -> pu -> inc_n_times_full(client -> username); client -> stats_glob -> inc_n_times_full(); // flush number of bits if (READ_TO(client -> socket_fd, dummy_buffer, 4, client -> config -> communication_timeout) != 4) { client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); return -1; } int rc = send_denied_full(client -> socket_fd, client -> config, client -> host); if (rc == -1) { client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); } return rc; } if (full_allow_interval_submit) dolog(LOG_DEBUG, "put|%s(%s) allow submit when full, after %f seconds", client -> host.c_str(), client -> type.c_str(), last_submit_ago); client -> pu -> inc_submit_while_full(client -> username); client -> stats_glob -> inc_submit_while_full(); warn_all_full = true; } unsigned char n_bits[4]; if (READ_TO(client -> socket_fd, n_bits, 4, client -> config -> communication_timeout) != 4) { dolog(LOG_INFO, "put|%s(%s) short read while retrieving number of bits to recv", client -> host.c_str(), client -> type.c_str()); client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); return -1; } int cur_n_bits = uchar_to_uint(n_bits); if (cur_n_bits <= 0) { dolog(LOG_INFO, "put|%s(%s) 0 bits offered", client -> host.c_str(), client -> type.c_str()); client -> pu -> inc_protocol_error(client -> username); client -> stats_glob -> inc_protocol_error(); return -1; } if (cur_n_bits > client -> config -> max_get_put_size) { dolog(LOG_WARNING, "put|%s(%s) client wants to put more than %d bits: %d", client -> host.c_str(), client -> type.c_str(), client -> config -> max_get_put_size, cur_n_bits); cur_n_bits = client -> config -> max_get_put_size; } unsigned char msg[4 + 4]; if (warn_all_full) make_msg(msg, 9003, cur_n_bits); else make_msg(msg, 1, cur_n_bits); // 0001 if (WRITE_TO(client -> socket_fd, msg, 8, client -> config -> communication_timeout) != 8) { dolog(LOG_INFO, "put|%s short write while sending ack", client -> host.c_str()); client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); return -1; } int cur_n_bytes = (cur_n_bits + 7) / 8; int hash_len = client -> mac_hasher -> get_hash_size(); int in_len = cur_n_bytes + hash_len; unsigned char *buffer_in = reinterpret_cast(malloc(in_len)); if (!buffer_in) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), in_len); if (READ_TO(client -> socket_fd, buffer_in, in_len, client -> config -> communication_timeout) != in_len) { dolog(LOG_INFO, "put|%s short read while retrieving entropy data", client -> host.c_str()); client -> pu -> inc_network_error(client -> username); client -> stats_glob -> inc_network_error(); free(buffer_in); return -1; } unsigned char *buffer_out = reinterpret_cast(malloc_locked(in_len)); if (!buffer_out) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), cur_n_bytes); // decrypt data client -> stream_cipher -> decrypt(buffer_in, in_len, buffer_out); unsigned char *entropy_data = &buffer_out[hash_len]; int entropy_data_len = cur_n_bytes; unsigned char *hash = reinterpret_cast(malloc(hash_len)); client -> mac_hasher -> do_hash(entropy_data, entropy_data_len, hash); if (memcmp(hash, buffer_out, hash_len) != 0) { dolog(LOG_WARNING, "Hash mismatch in retrieved entropy data!"); client -> pu -> inc_protocol_error(client -> username); client -> stats_glob -> inc_protocol_error(); } else { int n_bits_added = client -> ppools -> add_bits_to_pools(entropy_data, entropy_data_len, client -> ignore_rngtest_fips140, client -> pfips140, client -> ignore_rngtest_scc, client -> pscc, double(client -> config -> communication_timeout) * 0.9, client -> pc); if (n_bits_added == -1) { dolog(LOG_CRIT, "put|%s error while adding data to pools", client -> host.c_str()); client -> pu -> inc_misc_errors(client -> username); client -> stats_glob -> inc_misc_errors(); } else { dolog(LOG_DEBUG, "put|%s %d bits mixed into pools", client -> host.c_str(), n_bits_added); my_mutex_lock(&client -> stats_lck); update_client_fips140_scc(client, entropy_data, entropy_data_len); client -> bits_recv += n_bits_added; my_mutex_unlock(&client -> stats_lck); client -> pu -> track_recvs(client -> username, n_bits_added, entropy_data_len * 8); client -> stats_glob -> track_recvs(n_bits_added, entropy_data_len * 8); *new_bits = true; } } free(hash); free_locked(buffer_out, cur_n_bytes); free(buffer_in); return 0; } int do_client(client_t *client, bool *no_bits, bool *new_bits, bool *is_full) { char cmd[4]; client -> pu -> inc_msg_cnt(client -> username); client -> stats_glob -> inc_msg_cnt(); int rc = READ_TO(client -> socket_fd, cmd, 4, client -> config -> communication_timeout); if (rc != 4) { dolog(LOG_INFO, "client|%s short read while retrieving command (%d)", client -> host.c_str(), rc); return -1; } if (memcmp(cmd, "0001", 4) == 0) // GET bits { client -> pu -> register_msg(client -> username, false); client -> stats_glob -> register_msg(false); return do_client_get(client, no_bits); } else if (memcmp(cmd, "0002", 4) == 0) // PUT bits { if (client -> pu -> get_is_rw(client -> username)) { client -> pu -> register_msg(client -> username, true); client -> stats_glob -> register_msg(true); return do_client_put(client, new_bits, is_full); } dolog(LOG_DEBUG, "client|%s PUT denied (fd: %d)", client -> host.c_str(), client -> socket_fd); return -1; } else if (memcmp(cmd, "9999", 4) == 0) // logout { dolog(LOG_DEBUG, "client|%s LOGOUT (fd: %d)", client -> host.c_str(), client -> socket_fd); client -> pu -> inc_disconnects(client -> username); client -> stats_glob -> inc_disconnects(); return -1; } client -> pu -> inc_protocol_error(client -> username); client -> last_message = get_ts(); client -> stats_glob -> inc_protocol_error(); dolog(LOG_INFO, "client|%s command '%s' unknown", client -> host.c_str(), cmd); return -1; } int notify_server_full(int socket_fd, config_t *config) { unsigned char buffer[8]; make_msg(buffer, 9004, 0); // 9004 if (WRITE_TO(socket_fd, buffer, 8, config -> communication_timeout) != 8) return -1; return 0; } int notify_client_data_available(int socket_fd, pools *ppools, config_t *config) { if (send_got_data(socket_fd, ppools, config) == -1) return -1; return 0; } int notify_server_data_needed(int socket_fd, config_t *config) { if (send_need_data(socket_fd, config) == -1) return -1; return 0; } entropybroker-2.9/hc_protocol.h000066400000000000000000000017561305163522000167630ustar00rootroot00000000000000int send_denied_empty(int fd, statistics *stats, config_t *config); int send_denied_quota(int fd, statistics *stats, config_t *config); int send_denied_full(int fd, statistics *stats, config_t *config, char *host); int send_accepted_while_full(int fd, statistics *stats, config_t *config); int send_got_data(int fd, pools *ppools, config_t *config); int send_need_data(int fd, config_t *config); int do_proxy_auth(client_t *client, users *user_map); int do_client_get(client_t *client, bool *no_bits); int do_client_put(client_t *client, bool *new_bits, bool *is_full); int do_client_server_type(client_t *client); int do_client_kernelpoolfilled_reply(client_t *client); int do_client_kernelpoolfilled_request(client_t *client); int do_client(client_t *p, bool *no_bits, bool *new_bits, bool *is_full); int notify_server_full(int socket_fd, config_t *config); int notify_client_data_available(int socket_fd, pools *ppools, config_t *config); int notify_server_data_needed(int socket_fd, config_t *config); entropybroker-2.9/helgrind.sh000077500000000000000000000002621305163522000164210ustar00rootroot00000000000000#! /bin/sh valgrind --tool=helgrind --main-stacksize=16777216 --read-var-info=yes --free-is-write=yes ./entropy_broker -c ./entropy_broker.conf -n -l err.log -L 255 2> err8.log entropybroker-2.9/http_bundle.cpp000066400000000000000000000020401305163522000172760ustar00rootroot00000000000000#include #include #include #include #include "http_bundle.h" http_bundle::http_bundle(std::vector headers_in, unsigned char *data_in, int data_len_in) { headers = headers_in; data = NULL; data_len = 0; if (data_in) { data = reinterpret_cast(malloc(data_len_in)); memcpy(data, data_in, data_len_in); data_len = data_len_in; } } http_bundle::http_bundle(std::vector headers_in, const char *data_in) { headers = headers_in; data = reinterpret_cast(strdup(data_in)); data_len = strlen(data_in); } http_bundle::http_bundle(std::vector headers_in, std::string data_in) { headers = headers_in; data = reinterpret_cast(strdup(data_in.c_str())); data_len = data_in.size(); } http_bundle::~http_bundle() { free(data); } std::vector http_bundle::get_headers() { return headers; } int http_bundle::get_data_len() { return data_len; } unsigned char *http_bundle::get_data() { return data; } entropybroker-2.9/http_bundle.h000066400000000000000000000006531305163522000167530ustar00rootroot00000000000000class http_bundle { std::vector headers; unsigned char *data; int data_len; public: http_bundle(std::vector headers, unsigned char *data, int data_len); http_bundle(std::vector headers, const char *data); http_bundle(std::vector headers, std::string data); ~http_bundle(); std::vector get_headers(); int get_data_len(); unsigned char *get_data(); }; entropybroker-2.9/http_file.cpp000066400000000000000000000112321305163522000167470ustar00rootroot00000000000000#include #include #include #include #include #include "utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" http_file::http_file() { } http_file::~http_file() { } std::string http_file::get_url() { return "?"; } std::map http_file::split_parameters(std::string url) { std::map parameters; size_t parameters_pos = url.find('?'); if (parameters_pos != std::string::npos && parameters_pos < url.size() - 1) { std::string dummy = url.substr(parameters_pos + 1); char **par_array = NULL; int par_array_n = 0; split_string(dummy.c_str(), "&", &par_array, &par_array_n); for(int index=0; index\n" "\n" " \n" " \n" "
\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" " \"entropy\n" "
\n" "\n" "
\n" "\n" "

Entropy Broker

\n"; } std::string http_file::get_style_tail() { return "
\n" "\n" " \n" " \n" "\n"; } std::string generate_logging_table(statistics_global *ps, std::string username) { std::vector log = ps -> get_login_history(); std::string content = "\n"; content += "\n"; content += "\n"; double now_ts = get_ts(); for(int index=log.size()-1; index >= 0; index--) { if (username.size() > 0 && log.at(index).user != username) continue; content += ""; content += ""; content += ""; content += ""; content += ""; content += ""; content += ""; content += ""; if (log.at(index).hl == HL_LOGOUT_OK) content += format("", log.at(index).duration); else if (log.at(index).hl == HL_LOGIN_OK) content += format("", now_ts - log.at(index).time_logged_in); else content += ""; content += ""; content += "\n"; } content += "
event tsevent typeuserhosttype
connected sincedurationnotes
" + time_to_str((time_t)log.at(index).event_ts) + ""; switch(log.at(index).hl) { case HL_LOGIN_OK: content += "login ok"; break; case HL_LOGOUT_OK: content += "logout ok"; break; case HL_LOGIN_USER_FAIL: content += "unknown user"; break; case HL_LOGIN_PW_FAIL: content += "password fail"; break; case HL_LOGIN_OTHER: content += "other error"; break; default: content += "INTERNAL ERROR"; } content += "" + log.at(index).user + "" + log.at(index).host + "" + log.at(index).type + "
" + time_to_str((time_t)log.at(index).time_logged_in) + "%f[%f]" + log.at(index).details + "
\n"; return content; } entropybroker-2.9/http_file.h000066400000000000000000000007511305163522000164200ustar00rootroot00000000000000class http_file { public: http_file(); virtual ~http_file(); virtual std::string get_url() = 0; virtual std::string get_meta_type() = 0; std::map split_parameters(std::string url); std::string get_style_header(); std::string get_style_tail(); virtual http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) = 0; }; std::string generate_logging_table(statistics_global *ps, std::string username); entropybroker-2.9/http_file_404.cpp000066400000000000000000000006241305163522000173410ustar00rootroot00000000000000#include #include #include #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_file.h" #include "http_file_404.h" http_file_404::http_file_404() : http_file_file("/404.html", "text/html", WEB_DIR "/404.html") { } http_file_404::~http_file_404() { } entropybroker-2.9/http_file_404.h000066400000000000000000000001361305163522000170040ustar00rootroot00000000000000class http_file_404 : public http_file_file { public: http_file_404(); ~http_file_404(); }; entropybroker-2.9/http_file_file.cpp000066400000000000000000000034141305163522000177510ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include "log.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_file.h" http_file_file::http_file_file(std::string url_in, std::string meta_in, std::string file_in) : url(url_in), meta(meta_in), file(file_in) { } http_file_file::~http_file_file() { } std::string http_file_file::get_url() { return url; } std::string http_file_file::get_meta_type() { return meta; } void http_file_file::load_file(unsigned char **p, int *len) { bool ok = true; struct stat st; for(;;) { if (stat(file.c_str(), &st) == -1) { dolog(LOG_INFO, "stat on %s failed: %s", file.c_str(), strerror(errno)); ok = false; break; } FILE *fh = fopen(file.c_str(), "rb"); if (!fh) { ok = false; break; } *p = (unsigned char *)malloc(st.st_size); if (!*p) { ok = false; fclose(fh); break; } if (fread(*p, st.st_size, 1, fh) != 1) { dolog(LOG_INFO, "short read on %s", file.c_str()); ok = false; fclose(fh); free(*p); break; } *len = st.st_size; fclose(fh); break; } if (!ok) { *p = (unsigned char *)strdup("file not found"); *len = strlen((char *)*p); } } http_bundle * http_file_file::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { unsigned char *data = NULL; int data_len = 0; load_file(&data, &data_len); std::vector reply_headers; http_bundle *result = new http_bundle(reply_headers, data, data_len); free(data); return result; } entropybroker-2.9/http_file_file.h000066400000000000000000000006371305163522000174220ustar00rootroot00000000000000class http_file_file : public http_file { private: std::string url, meta, file; void load_file(unsigned char **p, int *len); public: http_file_file(std::string url_in, std::string meta_in, std::string file_in); virtual ~http_file_file(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_graph_data_logger.cpp000066400000000000000000000056011305163522000224630ustar00rootroot00000000000000#include #include #include #include #include #include "log.h" #include "utils.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "data_store_int.h" #include "data_logger.h" #include "graph.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_graph_data_logger.h" http_file_graph_data_logger::http_file_graph_data_logger(data_logger *dl_in, std::string font) : dl(dl_in) { g = new graph(font); } http_file_graph_data_logger::~http_file_graph_data_logger() { delete g; } std::string http_file_graph_data_logger::get_url() { return "/graph.png"; } std::string http_file_graph_data_logger::get_meta_type() { return "image/png"; } http_bundle * http_file_graph_data_logger::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::map request_parameters = split_parameters(request_url); std::map::iterator it = request_parameters.find("type"); std::string type = "mem_pool_counts"; if (it != request_parameters.end()) type = it -> second.c_str(); int width = 640, height = 240; it = request_parameters.find("width"); if (it != request_parameters.end()) width = std::max(240, atoi(it -> second.c_str())); it = request_parameters.find("height"); if (it != request_parameters.end()) height = std::max(200, atoi(it -> second.c_str())); std::string title = type; std::vector reply_headers; long int *t = NULL; double *v = NULL; int n = 0; if (type == "mem_pool_counts") dl -> get_mem_pool_counts(&t, &v, &n); else if (type == "dsk_pool_counts") dl -> get_dsk_pool_counts(&t, &v, &n); else if (type == "connection_counts") dl -> get_connection_counts(&t, &v, &n); else if (type == "mem_pools_bitcount") dl -> get_pools_bitcounts(&t, &v, &n); else if (type == "dsk_pools_bitcount") dl -> get_disk_pools_bitcounts(&t, &v, &n); else if (type == "recv_bit_count") dl -> get_recv_bit_count(&t, &v, &n); else if (type == "recv_bit_count_in") dl -> get_recv_bit_count_in(&t, &v, &n); else if (type == "sent_bit_count") dl -> get_sent_bit_count(&t, &v, &n); else { dolog(LOG_INFO, "%s is an unknown graph-type", type.c_str()); return NULL; } char *img_data = NULL; size_t img_data_len = 0; g -> do_draw(width, height, title, t, v, n, &img_data, &img_data_len); free(t); free(v); http_bundle *result = new http_bundle(reply_headers, (unsigned char *)img_data, (int)img_data_len); free(img_data); return result; } entropybroker-2.9/http_file_graph_data_logger.h000066400000000000000000000005661305163522000221350ustar00rootroot00000000000000class http_file_graph_data_logger : public http_file { private: data_logger *dl; graph *g; public: http_file_graph_data_logger(data_logger *dl_in, std::string font); ~http_file_graph_data_logger(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_logfile.cpp000066400000000000000000000023201305163522000204460ustar00rootroot00000000000000#include #include #include #include #include "utils.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_logfile.h" http_file_logfile::http_file_logfile(statistics_global *ps_in) : ps(ps_in) { } http_file_logfile::~http_file_logfile() { } std::string http_file_logfile::get_url() { return "/logfile.html"; } std::string http_file_logfile::get_meta_type() { return "text/html"; } http_bundle * http_file_logfile::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::vector reply_headers; std::string content = get_style_header(); content += generate_logging_table(ps, ""); content += get_style_tail(); return new http_bundle(reply_headers, content.c_str()); } entropybroker-2.9/http_file_logfile.h000066400000000000000000000005071305163522000201200ustar00rootroot00000000000000class http_file_logfile : public http_file { private: statistics_global *ps; public: http_file_logfile(statistics_global *ps_in); ~http_file_logfile(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_root.cpp000066400000000000000000000022421305163522000200130ustar00rootroot00000000000000#include #include #include #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_root.h" http_file_root::http_file_root() { } http_file_root::~http_file_root() { } std::string http_file_root::get_url() { return "/"; } std::string http_file_root::get_meta_type() { return "text/html"; } http_bundle * http_file_root::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::vector reply_headers; return new http_bundle(reply_headers, get_style_header() + " \n" + get_style_tail()); } entropybroker-2.9/http_file_root.h000066400000000000000000000004041305163522000174560ustar00rootroot00000000000000class http_file_root : public http_file { public: http_file_root(); ~http_file_root(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_stats.cpp000066400000000000000000000315451305163522000201760ustar00rootroot00000000000000#include #include #include #include #include "defines.h" #include "utils.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_stats.h" http_file_stats::http_file_stats(std::vector *clients_in, pthread_mutex_t *clients_mutex_in, pools *ppools_in, statistics_global *ps_in, fips140 *pfips140_in, scc *pscc_in) : clients(clients_in), clients_mutex(clients_mutex_in), ppools(ppools_in), ps(ps_in), pfips140(pfips140_in), pscc(pscc_in) { } http_file_stats::~http_file_stats() { } std::string http_file_stats::get_url() { return "/stats.html"; } std::string http_file_stats::get_meta_type() { return "text/html"; } http_bundle * http_file_stats::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::map request_parameters = split_parameters(request_url); std::map::iterator it = request_parameters.find("id"); long int id = -1; if (it != request_parameters.end()) id = atoll(it -> second.c_str()); std::vector reply_headers; std::string content = get_style_header(); double now = get_ts(); if (id > 0) { my_mutex_lock(clients_mutex); client_t *p = find_client_by_id(clients, id); if (!p) content += format("%lld is an unknown client id", id); else { users *pcs = p -> pu; content += "\n"; content += std::string("\n"; content += std::string("\n"; content += std::string("\n"; content += std::string("\n"; content += "\n"; content += format("\n", now - p -> connected_since); content += format("\n", (now - p -> connected_since) / double(pcs -> get_msg_cnt(p -> username))); content += "\n"; content += "\n"; content += format("\n", pcs -> get_times_quota(p -> username)); content += format("\n", pcs -> get_times_empty(p -> username)); content += format("\n", pcs -> get_times_full(p -> username)); content += format("\n", pcs -> get_submit_while_full(p -> username)); content += format("\n", pcs -> get_network_error(p -> username)); content += format("\n", pcs -> get_protocol_error(p -> username)); content += format("\n", pcs -> get_misc_errors(p -> username)); long long int total_bits_recv = 0, total_bits_recv_in = 0; int n_recv = 0; pcs -> get_recvs(p -> username, &total_bits_recv, &n_recv, &total_bits_recv_in); content += format("\n", n_recv); content += format("\n", total_bits_recv); content += format("\n", double(total_bits_recv * 100) / double(total_bits_recv_in)); content += format("\n", double(total_bits_recv) / double(n_recv)); content += format("\n", double(total_bits_recv) / (now - p -> connected_since)); long long int total_bits_sent = 0; int n_sent = 0; pcs -> get_sents(p -> username, &total_bits_sent, &n_sent); content += format("\n", n_sent); content += format("\n", total_bits_sent); content += format("\n", double(total_bits_sent) / double(n_sent)); content += format("\n", double(total_bits_sent) / (now - p -> connected_since)); my_mutex_lock(&p -> stats_lck); content += std::string("\n"; content += std::string("\n"; my_mutex_unlock(&p -> stats_lck); content += "
username:") + p -> username + "
host:") + p -> host + "
type:") + p -> type + "
is server:") + (p -> is_server ? "yes" : "no") + "
connected since:" + time_to_str((time_t)p -> connected_since) + "
duration:%fs
avg time between msgs:%fs
last message:" + time_to_str((time_t)p -> last_message) + "
last put message:" + time_to_str((time_t)p -> last_put_message) + "
denied because of quota:%d
denied because pools empty:%d
denied because full:%d
allowed while full:%d
network errors:%d
protocol errors:%d
miscellaneous errors:%d
put requests:%d
bits put:%lld
bits put density:%f%%
avg bits/put:%f
put bps:%f
get requests:%d
bits requested:%lld
avg bits/get:%f
get bps:%f
FIPS140 stats:") + p -> pfips140 -> stats() + "
SCC stats:") + p -> pscc -> stats() + "
\n"; content += "
\n"; content += generate_logging_table(ps, p -> username); } my_mutex_unlock(clients_mutex); } else { // PER USER STATS content += "\n"; content += "\n"; double recv_bps = 0, sent_bps = 0; my_mutex_lock(clients_mutex); for(unsigned int index=0; index size(); index++) { client_t *p = clients -> at(index); content += "\n"; } my_mutex_unlock(clients_mutex); content += format("\n", recv_bps, sent_bps); content += "
userhostconnected sincebits recvbits senterrorswarnings
"; content += p -> username; content += " id); content += "\">"; content += p -> host; content += ""; users *pcs = p -> pu; content += time_to_str((time_t)p -> connected_since); double duration = now - p -> connected_since; long long int total_bits_recv = 0, total_bits_recv_in = 0, total_bits_sent = 0; int n_recv = 0, n_sent = 0; pcs -> get_recvs(p -> username, &total_bits_recv, &n_recv, &total_bits_recv_in); pcs -> get_sents(p -> username, &total_bits_sent, &n_sent); content += ""; content += format("%lld", total_bits_recv); if (p -> is_server) recv_bps += double(total_bits_recv) / duration; else sent_bps += double(total_bits_sent) / duration; content += ""; content += format("%lld", total_bits_sent); content += ""; // errors int errors = pcs -> get_network_error(p -> username); errors += pcs -> get_protocol_error(p -> username); errors += pcs -> get_misc_errors(p -> username); content += format("%d", errors); content += ""; // warnings int warnings = pcs -> get_times_quota(p -> username); warnings += pcs -> get_times_empty(p -> username); warnings += pcs -> get_times_full(p -> username); warnings += pcs -> get_submit_while_full(p -> username); content += format("%d", warnings); content += "
bps: %.1f%.1f
\n"; content += format("Number of connected clients/servers: %d
\n", clients -> size()); content += "
\n"; // GLOBAL STATS content += "\n"; content += "\n"; content += format("\n", now - get_start_ts()); content += format("\n", (now - get_start_ts()) / double(ps -> get_msg_cnt())); content += "\n"; content += "\n"; content += format("\n", ps -> get_disconnects()); content += format("\n", ps -> get_times_quota()); content += format("\n", ps -> get_times_empty()); content += format("\n", ps -> get_times_full()); content += format("\n", ps -> get_submit_while_full()); content += format("\n", ps -> get_network_error()); content += format("\n", ps -> get_protocol_error()); content += format("\n", ps -> get_misc_errors()); long long int total_bits_recv = 0, total_bits_recv_in = 0; int n_recv = 0; ps -> get_recvs(&total_bits_recv, &n_recv, &total_bits_recv_in); content += format("\n", n_recv); content += format("\n", total_bits_recv); // FIXME should be get density content += format("\n", double(total_bits_recv * 100) / double(total_bits_recv_in)); content += format("\n", double(total_bits_recv) / double(n_recv)); content += format("\n", double(total_bits_recv) / (now - get_start_ts())); long long int total_bits_sent = 0; int n_sent = 0; ps -> get_sents(&total_bits_sent, &n_sent); content += format("\n", n_sent); content += format("\n", total_bits_sent); content += format("\n", double(total_bits_sent) / double(n_sent)); content += format("\n", double(total_bits_sent) / (now - get_start_ts())); content += std::string("\n"; content += std::string("\n"; content += "
running since:" + time_to_str((time_t)get_start_ts()) + "
duration:%fs
avg time between msgs:%fs
last message:" + time_to_str((time_t)ps -> get_last_msg_ts()) + "
last put message:" + time_to_str((time_t)ps -> get_last_put_msg_ts()) + "
logged out sessions: %d
denied because of quota:%d
denied because pools empty:%d
denied because full:%d
allowed while full:%d
network errors:%d
protocol errors:%d
miscellaneous errors:%d
put requests:%d
bits put:%lld
bits put density:%f%%
avg bits/put:%f
put bps:%f
get requests:%d
bits requested:%lld
avg bits/get:%f
get bps:%f
FIPS140 stats:") + pfips140 -> stats() + "
SCC stats:") + pscc -> stats() + "
\n"; content += "
\n"; // POOL STATS content += "\n"; int bit_sum = ppools -> get_bit_sum(1.0); content += format("\n", bit_sum); int mem_pools = ppools -> get_memory_pool_count(); content += format("\n", mem_pools); content += format("\n", double(bit_sum) / double(mem_pools), DEFAULT_POOL_SIZE_BITS); int disk_file_cnt = ppools -> get_disk_pool_count(); content += format("\n", disk_file_cnt); int disk_bit_sum = ppools -> get_disk_pool_bit_count(); content += format("\n", disk_bit_sum); content += format("\n", double(disk_bit_sum) / double(disk_file_cnt)); content += "
in memory bit count:%d
pools in memory:%d
avg bits/mem pool:%f (def max: %d)
pool files on disk:%d
on disk bit count:%d
avg bits/disk pool:%f
\n"; content += "
\n"; std::string dimensions = "&width=640&height=240"; content += "

number of memory pools

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

number of disk pools

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

number of connections

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

memory pools bit count

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

disk pools bit count

\n"; content += "\"graph\"
\n"; content += "
\n"; content += format("Interval: %ds\n", MEASURE_INTERVAL); content += "

data from servers to broker (per interval, entropy count)

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

data from servers to broker (per interval, raw data)

\n"; content += "\"graph\"
\n"; content += "
\n"; content += "

data from broker to clients (per interval)

\n"; content += "\"graph\"
\n"; content += "
\n"; } content += get_style_tail(); return new http_bundle(reply_headers, content.c_str()); } entropybroker-2.9/http_file_stats.h000066400000000000000000000010601305163522000176300ustar00rootroot00000000000000class http_file_stats : public http_file { private: std::vector *clients; pthread_mutex_t *clients_mutex; pools *ppools; statistics_global *ps; fips140 *pfips140; scc *pscc; public: http_file_stats(std::vector *clients_in, pthread_mutex_t *clients_mutex_in, pools *ppools, statistics_global *ps_in, fips140 *pfips140_in, scc *pscc_in); ~http_file_stats(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_users.cpp000066400000000000000000000115331305163522000201740ustar00rootroot00000000000000#include #include #include #include #include "defines.h" #include "utils.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_users.h" http_file_users::http_file_users(users *pusers_in) : pusers(pusers_in) { } http_file_users::~http_file_users() { } std::string http_file_users::get_url() { return "/users.html"; } std::string http_file_users::get_meta_type() { return "text/html"; } http_bundle * http_file_users::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::map request_parameters = split_parameters(request_url); std::vector reply_headers; std::string content = get_style_header(); std::vector user_list = pusers -> get_users(); content += "\n"; content += "\n"; content += "\n"; content += "\n"; for(unsigned int index=0; index\n"; // row 2 content += "\n"; // row 3 content += " 0 ? " class=\"darkyellow\"" : "") + ">"; content += format("%d", disconnects); int times_empty = pusers -> get_times_empty(username); content += " 0 ? " class=\"darkyellow\"" : "") + ">"; content += format("%d", times_empty); int times_full = pusers -> get_times_full(username); content += " 0 ? " class=\"darkyellow\"" : "") + ">"; content += format("%d", times_full); int times_quota = pusers -> get_times_quota(username); content += " 0 ? " class=\"darkyellow\"" : "") + ">"; content += format("%d", times_quota); int submit_while_full = pusers -> get_submit_while_full(username); content += " 0 ? " class=\"darkyellow\"" : "") + ">"; content += format("%d", submit_while_full); int network_error = pusers -> get_network_error(username); content += " 0 ? " class=\"darkred\"" : "") + ">"; content += format("%d", network_error); int protocol_error = pusers -> get_protocol_error(username); content += " 0 ? " class=\"darkred\"" : "") + ">"; content += format("%d", protocol_error); int misc_errors = pusers -> get_misc_errors(username); content += " 0 ? " class=\"darkred\"" : "") + ">"; content += format("%d", misc_errors); content += "\n"; content += "\n"; } content += "
userbits putbits put rawbits sent
latest logonlast messagelast putlast get
msgsdisconnectsemptyfullquota reachedsubmit while fullnetwork errorprotocol errormisc error
"; content += username; content += ""; long long int total_bits_recv, total_bits_recv_in; int n_reqs; pusers -> get_recvs(username, &total_bits_recv, &n_reqs, &total_bits_recv_in); content += format("%lld", total_bits_recv); content += ""; content += format("%lld", total_bits_recv_in); content += ""; int n_sents; long long int total_bits_sent; pusers -> get_sents(username, &total_bits_sent, &n_sents); content += format("%lld", total_bits_sent); content += "
"; content += time_to_str((time_t)pusers -> get_last_login(username)); content += ""; content += time_to_str((time_t)pusers -> get_last_msg_ts(username)); content += ""; content += time_to_str((time_t)pusers -> get_last_put_msg_ts(username)); content += ""; content += time_to_str((time_t)pusers -> get_last_get_msg_ts(username)); content += "
"; content += format("%d", pusers -> get_msg_cnt(username)); int disconnects = pusers -> get_disconnects(username); content += "
\n"; content += get_style_tail(); return new http_bundle(reply_headers, content.c_str()); } entropybroker-2.9/http_file_users.h000066400000000000000000000004611305163522000176370ustar00rootroot00000000000000class http_file_users : public http_file { private: users *pusers; public: http_file_users(users *pusers_in); ~http_file_users(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_file_version.cpp000066400000000000000000000014071305163522000205170ustar00rootroot00000000000000#include #include #include #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "http_bundle.h" #include "http_request_t.h" #include "http_file.h" #include "http_file_version.h" http_file_version::http_file_version() { } http_file_version::~http_file_version() { } std::string http_file_version::get_url() { return "/version.html"; } std::string http_file_version::get_meta_type() { return "text/html"; } http_bundle * http_file_version::do_request(http_request_t request_type, std::string request_url, http_bundle *request_details) { std::vector reply_headers; return new http_bundle(reply_headers, get_style_header() + "

Entropy Broker v" VERSION "

$Id$" + get_style_tail()); } entropybroker-2.9/http_file_version.h000066400000000000000000000004151305163522000201620ustar00rootroot00000000000000class http_file_version : public http_file { public: http_file_version(); ~http_file_version(); std::string get_url(); std::string get_meta_type(); http_bundle * do_request(http_request_t request_type, std::string request_url, http_bundle *request_details); }; entropybroker-2.9/http_request_t.h000066400000000000000000000000721305163522000175100ustar00rootroot00000000000000typedef enum { HR_FAIL, HR_GET, HR_POST } http_request_t; entropybroker-2.9/http_server.cpp000066400000000000000000000073671305163522000173540ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "log.h" #include "utils.h" #include "defines.h" #include "http_request_t.h" #include "http_bundle.h" #include "http_server.h" http_server::http_server(int fd_in) : fd(fd_in), request_type(static_cast(-1)) { request_data = reinterpret_cast(malloc(HTTP_SERVER_READ_SIZE + 1)); request_data_size = 0; request_type = HR_FAIL; char *headers_end = NULL; bool crlf = true; do { int rc = read(fd_in, &request_data[request_data_size], HTTP_SERVER_READ_SIZE); if (rc == -1 || rc == 0) { if (rc == -1 && errno == EINTR) continue; dolog(LOG_INFO, "HTTP: short read"); break; } request_data_size += rc; request_data = reinterpret_cast(realloc(request_data, request_data_size + HTTP_SERVER_READ_SIZE + 1)); request_data[request_data_size] = 0x00; headers_end = strstr(reinterpret_cast(request_data), "\r\n\r\n"); if (!headers_end) { headers_end = strstr(reinterpret_cast(request_data), "\n\n"); if (headers_end) crlf = false; } } while(headers_end == NULL); if (headers_end) { // get headers from request *headers_end = 0x00; const char *line_end = crlf ? "\r\n" : "\n"; char **headers = NULL; int n_headers = 0; split_string(reinterpret_cast(request_data), line_end, &headers, &n_headers); for(int index=0; index= 1) { if (strcmp(request_parts[0], "GET") == 0) request_type = HR_GET; else if (strcmp(request_parts[0], "POST") == 0) request_type = HR_POST; } if (n_request_parts >= 2) request_url = request_parts[1]; for(int index=0; index(request_data)) + (crlf ? 4 : 2); int bytes_left = request_data_size - headers_size; if (bytes_left) { memmove(request_data, &request_data[headers_size], bytes_left); request_data_size -= headers_size; } else { request_data_size = 0; } } } http_server::~http_server() { free(request_data); } http_request_t http_server::get_request_type() { return request_type; } http_bundle * http_server::get_request() { return new http_bundle(request_headers, request_data, request_data_size); } std::string http_server::get_request_url() { return request_url; } bool http_server::send(const char *what) { int len = strlen(what); // printf("> %s", what); return send((unsigned char *)what, len); } bool http_server::send(unsigned char *p, int len) { if (WRITE_TO(fd, p, len, DEFAULT_COMM_TO) != len) return false; return true; } void http_server::send_response(int status_code, std::vector *headers, http_bundle *response) { headers -> insert(headers -> begin(), format("HTTP/1.0 %d", status_code)); headers -> push_back("Expires: Fri, 09 Nov 2015 14:55:30 GMT"); headers -> push_back("Cache-Control: no-cache"); headers -> push_back("Pragma: no-cache"); headers -> push_back(format("Content-Length: %d", response -> get_data_len())); bool ok = true; for(unsigned int index=0; index size() && ok; index++) ok = send((headers -> at(index) + "\r\n").c_str()); if (ok) ok = send("\r\n"); if (ok) ok = send(response -> get_data(), response -> get_data_len()); close(fd); fd = -1; } entropybroker-2.9/http_server.h000066400000000000000000000010401305163522000167770ustar00rootroot00000000000000#define HTTP_SERVER_READ_SIZE 4096 class http_server { private: int fd; std::vector request_headers; http_request_t request_type; unsigned char *request_data; std::string request_url; int request_data_size; bool send(unsigned char *p, int len); bool send(const char *what); public: http_server(int fd); ~http_server(); http_request_t get_request_type(); http_bundle * get_request(); std::string get_request_url(); void send_response(int status_code, std::vector *headers, http_bundle *response); }; entropybroker-2.9/interfacing.txt000066400000000000000000000024041305163522000173200ustar00rootroot00000000000000Writing your own server/client ------------------------------ - include , - instantiate a 'protocol'-class: protocol *p = new protocol(char *host, int port, std::string username, std::string password, bool is_server, std::string type); host + port = entropy broker username + password = authentication against broker is_server = false for client, true for server type = name of server/client with any details added - then to transmit data: int message_transmit_entropy_data(unsigned char *bytes, int n_bytes); bytes / n_bytes = where from, how many returns 0 for ok, -1 for error - to retrieve data: int request_bytes(char *where_to, int n_bits, bool fail_on_no_bits); where_to = where to place the data n_bits = number of bits requested, broker may return less fail_on_no_bits = if the broker does not have data and this is set to true, then this method won't keep trying - when linking, add the following files: error.cpp log.cpp kernel_prng_rw.cpp protocol.cpp utils.cpp server_utils.cpp auth.cpp my_pty.cpp kernel_prng_io.cpp also add the following libraries: -lcrypto -lrt -lz -lutil -rdynamic Contact info ------------ mail@vanheusden.com entropybroker-2.9/java/000077500000000000000000000000001305163522000152075ustar00rootroot00000000000000entropybroker-2.9/java/EntropybrokerConnector.java000066400000000000000000000070501305163522000225740ustar00rootroot00000000000000import java.net.Socket; import java.io.InputStreamReader; import java.io.OutputStreamWriter; class EntropybrokerConnector { String host; int port = 55225; final int maxBytes = 9999 / 8; Socket socket; InputStreamReader inputStream; OutputStreamWriter outputStream; EntropybrokerConnector(String host) { this.host = host; } EntropybrokerConnector(String host, int port) { this.host = host; this.port = port; } void writeData(OutputStreamWriter outputStream, String what) throws Exception { int whatLength = what.length(); System.out.println("what: " + what); for(int loop=0; loop maxBytes) throw new Exception("EntropybrokerConnector::getData, maximum " + maxBytes + " supported"); if (socket == null || !socket.isConnected()) { if (socket != null) socket.close(); connect(); } // request data String requestData = String.format("0001%04d", bytes * 8); writeData(outputStream, requestData); // get request reply byte [] reply = readData(inputStream, 8); String replyString = new String(reply); int nBits = Integer.valueOf(replyString.substring(4)); int nBytes = (nBits + 7) / 8; if (replyString.substring(0, 3).equals("900") ) { throw new Exception("Server is not refusing to send data"); } return readData(inputStream, nBytes); } void putData(byte [] bytes) throws Exception { int whatLength = bytes.length; if (socket == null || !socket.isConnected()) { if (socket != null) socket.close(); connect(); } if (whatLength > maxBytes) { whatLength = maxBytes; throw new Exception("EntropybrokerConnector::putData, maximum " + maxBytes + " supported"); } // send send-request String requestData = String.format("0002%04d", whatLength * 8); writeData(outputStream, requestData); // get send-request reply byte [] reply = readData(inputStream, 8); String replyString = new String(reply); int nBits = Integer.valueOf(replyString.substring(4)); int nBytes = (nBits + 7) / 8; if (replyString.substring(0, 4).equals("0001")) { writeData(outputStream, bytes); } else if (replyString.substring(0, 4).equals("9001")) { throw new Exception("Error code from server: all pools full, sleep " + replyString.substring(4) + " seconds"); } } } entropybroker-2.9/java/Makefile000066400000000000000000000003651305163522000166530ustar00rootroot00000000000000VERSION=0.7-002 clean: rm -f *class package: clean mkdir eb-javaconnector-$(VERSION) cp *.java license.txt eb-javaconnector-$(VERSION) tar czf eb-javaconnector-$(VERSION).tgz eb-javaconnector-$(VERSION) rm -rf eb-javaconnector-$(VERSION) entropybroker-2.9/java/license.txt000066400000000000000000000354511305163522000174020ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS entropybroker-2.9/java/test.java000066400000000000000000000015631305163522000170360ustar00rootroot00000000000000class test { public static void main(String [] args) { try { final int n = 10000; EntropybrokerConnector example = new EntropybrokerConnector("mauer"); byte [] data = example.getData(n); System.out.print("Got: "); for(int loop=0; loop #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "utils.h" #include "kernel_prng_io.h" int kernel_rng_get_entropy_count() { int n_bits; int fd = open(DEV_RANDOM, O_RDONLY); if (fd == -1) error_exit("Failed to open %s", DEV_RANDOM); if (ioctl(fd, RNDGETENTCNT, &n_bits) == -1) error_exit("ioctl(RNDGETENTCNT) failed"); close(fd); return n_bits; } int kernel_rng_add_entropy(unsigned char *data, int n, int n_bits) { int total_size; struct rand_pool_info *output; int fd = open(DEV_RANDOM, O_WRONLY); if (fd == -1) error_exit("Failed to open %s", DEV_RANDOM); total_size = sizeof(struct rand_pool_info) + n; output = (struct rand_pool_info *)malloc(total_size); if (!output) error_exit("malloc failure in kernel_rng_add_entropy_no_bitcount_increase(%d)", n); output -> entropy_count = n_bits; output -> buf_size = n; memcpy(&(output -> buf[0]), data, n); if (ioctl(fd, RNDADDENTROPY, output) == -1) error_exit("ioctl(RNDADDENTROPY) failed!"); free(output); close(fd); return 0; } int kernel_rng_get_max_entropy_count(void) { int bit_count; FILE *fh = fopen(PROC_POOLSIZE, "r"); if (!fh) error_exit("Failed to open %s", PROC_POOLSIZE); if (fscanf(fh, "%d", &bit_count) != 1) error_exit("Failed to read from %s", PROC_POOLSIZE); fclose(fh); return bit_count; } entropybroker-2.9/kernel_prng_io.h000066400000000000000000000004221305163522000174320ustar00rootroot00000000000000#define DEV_RANDOM "/dev/random" #define DEV_URANDOM "/dev/urandom" #define PROC_POOLSIZE "/proc/sys/kernel/random/poolsize" int kernel_rng_get_entropy_count(); int kernel_rng_add_entropy(unsigned char *data, int n, int n_bits); int kernel_rng_get_max_entropy_count(void); entropybroker-2.9/kernel_prng_rw.cpp000066400000000000000000000025171305163522000200150ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "utils.h" #include "kernel_prng_io.h" int kernel_rng_read_blocking(unsigned char *buffer, int n) { int fd = open(DEV_RANDOM, O_RDONLY); if (fd == -1) error_exit("Failed to open %s", DEV_RANDOM); int rc = -1; if (READ(fd, buffer, n) == n) rc = n; close(fd); return rc; } int kernel_rng_read_non_blocking(unsigned char *buffer, int n) { int rc; int fd = open(DEV_URANDOM, O_RDONLY); if (fd == -1) error_exit("Failed to open %s", DEV_URANDOM); for(;;) { rc = read(fd, buffer, n); if (rc == -1) { if (errno == EINTR || errno == EAGAIN) continue; error_exit("error reading from %s", DEV_URANDOM); } break; } close(fd); return rc; } int kernel_rng_write_non_blocking(unsigned char *buffer, int n) { int rc; int fd = open(DEV_URANDOM, O_WRONLY); if (fd == -1) return -1; for(;;) { rc = write(fd, buffer, n); if (rc == -1) { if (errno == EINTR || errno == EAGAIN) continue; error_exit("error writing to %s", DEV_URANDOM); } break; } close(fd); return rc; } entropybroker-2.9/kernel_prng_rw.h000066400000000000000000000002751305163522000174610ustar00rootroot00000000000000int kernel_rng_read_blocking(unsigned char *buffer, int n); int kernel_rng_read_non_blocking(unsigned char *buffer, int n); int kernel_rng_write_non_blocking(unsigned char *buffer, int n); entropybroker-2.9/license.txt000066400000000000000000000002511305163522000164470ustar00rootroot00000000000000EntropyBroker v2.8 and later are licensed under GNU AGPL v3.0. Version 2.7 and earlier were licensed under GNU GPL v2.0. See: http://www.gnu.org/licenses/agpl-3.0.html entropybroker-2.9/log.cpp000066400000000000000000000025301305163522000155530ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "error.h" bool log_console = true; char *log_file = NULL; bool log_syslog = false; int log_level = 1; void dolog(int level, const char *format, ...) { if (level <= log_level) { char buffer[4096]; va_list ap; time_t now = time(NULL); char timestr[256] = { 0 }; ctime_r(&now, timestr); // can't set a limit so hopefully this 256 is enough! char *dummy = strchr(timestr, '\n'); if (dummy) *dummy = 0x00; va_start(ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end(ap); if (log_console) printf("%s]%d| %s\n", timestr, level, buffer); if (log_file) { FILE *fh = fopen(log_file, "a+"); if (!fh) { syslog(LOG_CRIT, "error accessing logfile %s: %m", log_file); fprintf(stderr, "error accessing logfile %s: %s", log_file, strerror(errno)); exit(1); } fprintf(fh, "%s]%d| %s\n", timestr, level, buffer); fclose(fh); } if (log_syslog) syslog(level, "%s", buffer); } } void set_logging_parameters(bool console, char *file, bool sl, int ll) { log_console = console; log_file = file; log_syslog = sl; log_level = ll; if (ll < 0) { ll = 0; error_exit("Log level must be >= 0"); } } void set_loglevel(int ll) { log_level = ll; } entropybroker-2.9/log.h000066400000000000000000000002501305163522000152150ustar00rootroot00000000000000#include void dolog(int level, const char *format, ...); void set_logging_parameters(bool console, char *file, bool sl, int ll); void set_loglevel(int ll); entropybroker-2.9/main.cpp000066400000000000000000000123241305163522000157200ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "math.h" #include "hasher_type.h" #include "hasher.h" #include "hasher_md5.h" #include "hasher_ripemd160.h" #include "hasher_sha512.h" #include "hasher_whirlpool.h" #include "encrypt_stream.h" #include "encrypt_stream_3des.h" #include "encrypt_stream_aes.h" #include "encrypt_stream_blowfish.h" #include "encrypt_stream_camellia.h" #include "stirrer_type.h" #include "stirrer.h" #include "stirrer_3des.h" #include "stirrer_aes.h" #include "stirrer_blowfish.h" #include "stirrer_camellia.h" #include "pool_crypto.h" #include "pool.h" #include "fips140.h" #include "scc.h" #include "config.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "data_store_int.h" #include "data_logger.h" #include "utils.h" #include "log.h" #include "signals.h" #include "auth.h" #include "http_request_t.h" #include "http_bundle.h" #include "http_file.h" #include "web_server.h" const char *pid_file = PID_DIR "/entropy_broker.pid"; const char *version = "entropy_broker v " VERSION ", (C) 2009-2015 by folkert@vanheusden.com"; void seed(pools *ppools, pool_crypto *pc) { int n = 0, dummy; n += ppools -> add_event(get_ts_ns(), NULL, 0, 0.005, pc); dummy = getpid(); n += ppools -> add_event(get_ts_ns(), (unsigned char *)&dummy, sizeof dummy, 0.005, pc); dolog(LOG_DEBUG, "added %d bits of startup-event-entropy to pool", n); } void help(void) { printf("-c file config-file to read (default: " CONFIG "\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S statistics-file to log to\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *stats_file = NULL; fips140 *eb_output_fips140 = new fips140(); scc *eb_output_scc = new scc(); const char *config_file = CONFIG; config_t config; int log_level = LOG_INFO; printf("%s\n", version); eb_output_fips140 -> set_user("output"); eb_output_scc -> set_user("output"); while((c = getopt(argc, argv, "hP:c:S:L:l:sn")) != -1) { switch(c) { case 'P': pid_file = optarg; break; case 'c': config_file = optarg; break; case 'S': stats_file = optarg; break; case 's': log_syslog = true; break; case 'l': log_logfile = optarg; break; case 'L': log_level = atoi(optarg); break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } (void)umask(0177); no_core(); fips140::init(); pthread_check(pthread_mutexattr_init(&global_mutex_attr), "pthread_mutexattr_init"); pthread_check(pthread_mutexattr_settype(&global_mutex_attr, PTHREAD_MUTEX_ERRORCHECK), "pthread_mutexattr_settype"); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); load_config(config_file, &config); if (stats_file) config.stats_file = stats_file; dolog(LOG_INFO, "%s", version); dolog(LOG_DEBUG, "Main thread id: %ld", gettid()); eb_output_scc -> set_threshold(config.scc_threshold); bit_count_estimator *bce = new bit_count_estimator(config.bitcount_estimator); // random pool_crypto pc(config.st, config.ht, config.rs); unsigned int rand_seed = 11; pc.get_random_source() -> get(reinterpret_cast(&rand_seed), sizeof rand_seed); srand(rand_seed); pools *ppools = new pools(std::string(CACHE_DIR), config.max_number_of_mem_pools, config.max_number_of_disk_pools, config.min_store_on_disk_n, bce, config.pool_size_bytes); seed(ppools, &pc); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); set_signal_handlers(); std::vector clients; pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER; statistics_global stats; data_logger *dl = new data_logger(&stats, ppools, &clients, &clients_mutex); users *user_map = new users(*config.user_map, config.default_max_get_bps); if (!user_map) error_exit("failed allocating users-object"); if (config.webserver_port >= 1) start_web_server(&config, &clients, &clients_mutex, ppools, &stats, eb_output_fips140, eb_output_scc, dl, user_map); struct rlimit rlim = {config.max_open_files , config.max_open_files }; if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) error_exit("setrlimit(RLIMIT_NOFILE) failed"); main_loop(&clients, &clients_mutex, ppools, &config, eb_output_fips140, eb_output_scc, &pc, &stats, user_map); dolog(LOG_INFO, "Dumping pool contents to cache-file"); delete dl; delete user_map; delete ppools; delete bce; delete eb_output_fips140; delete eb_output_scc; delete config.user_map; free((void *)config.listen_adapter); free((void *)config.graph_font); unlink(pid_file); dolog(LOG_INFO, "--- terminating ---\n"); return 0; } entropybroker-2.9/math.cpp000066400000000000000000000040771305163522000157330ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "math.h" bit_count_estimator::bit_count_estimator(const bit_count_estimator_type_t type_in) : type(type_in) { } int bit_count_estimator::get_bit_count(const unsigned char *const data, const unsigned int n_bytes) { if (n_bytes == 0) return 0; #ifdef _DEBUG int sh = determine_number_of_bits_of_data_shannon(data, n_bytes); int compr = determine_number_of_bits_of_data_compression(data, n_bytes); dolog(LOG_DEBUG, "in: %d, shannon: %d, compression: %d", n_bytes * 8, sh, compr); if (type == BCE_SHANNON) return sh; else if (type == BCE_COMPRESSION) return compr; #else if (type == BCE_SHANNON) return determine_number_of_bits_of_data_shannon(data, n_bytes); else if (type == BCE_COMPRESSION) return determine_number_of_bits_of_data_compression(data, n_bytes); #endif error_exit("Bit count estimator: unknown mode"); return -1; } int bit_count_estimator::determine_number_of_bits_of_data_shannon(const unsigned char *const data, const unsigned int n_bytes) { double ent = 0.0, nbytesd = double(n_bytes); int cnts[256]; memset(cnts, 0x00, sizeof cnts); for(unsigned int loop=0; loop #include #include #include #include #include #include #include #include #include #ifdef __APPLE__ #include #endif #ifdef __OpenBSD__ #include #endif #if defined(linux) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) #include #endif #ifdef __FreeBSD__ #include #endif #if defined(sun) || defined(__sun) #include #include #endif #if defined(IRIX) || defined(IRIX64) #endif #if defined(AIX) #endif #if defined(_HPUX_SOURCE) #include #include #include #include #include #include #include #include #endif #include /* the following code was mostly taken from: */ /* $NetBSD: sshpty.c,v 1.8 2002/10/15 15:33:04 manu Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Allocating a pseudo-terminal, and making it the controlling tty. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* additional code for *BSD/Linux/Apple, AIX and IRIX by folkert@vanheusden.com */ int get_pty_and_fork(int *fd_master, int *fd_slave) { #if defined(__FreeBSD__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) if (openpty(fd_master, fd_slave, NULL, NULL, NULL) == -1) return -1; return fork(); #elif defined(sun) || defined(__sun) || defined(AIX) || defined(_HPUX_SOURCE) || defined(OSF1) || defined(scoos) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; pid_t pid; #if defined(AIX) char *multiplexer = "/dev/ptc"; #else char *multiplexer = "/dev/ptmx"; #endif ptm = open(multiplexer, O_RDWR | O_NOCTTY); if (ptm < 0) { return -1; } *fd_master = ptm; pid = fork(); if (pid == 0) { if (grantpt(ptm) < 0) exit(1); if (unlockpt(ptm) < 0) exit(1); setsid(); /* lose old controlling terminal (FvH) */ pts = ptsname(ptm); if (pts == NULL) exit(1); /* Open the slave side. */ *fd_slave = open(pts, O_RDWR | O_NOCTTY); if (*fd_slave < 0) exit(1); #if !defined(AIX) && !defined(scoos) /* Push the appropriate streams modules, as described in Solaris pts(7). */ if (ioctl(*fd_slave, I_PUSH, "ptem") < 0) exit(1); if (ioctl(*fd_slave, I_PUSH, "ldterm") < 0) exit(1); (void)ioctl(*fd_slave, I_PUSH, "ttcompat"); /* not on HP-UX? */ #endif } return pid; #elif defined(IRIX) || defined(IRIX64) char *line = _getpty(fd_master, O_RDWR | O_NDELAY, 0600, 0); if (line == NULL) exit(1); *fd_slave = open(line, O_RDWR); if (*fd_slave < 0) exit(1); return fork(); #else #error I'm sorry, but I don't know what kind of system this is. #endif } entropybroker-2.9/my_pty.h000066400000000000000000000000651305163522000157610ustar00rootroot00000000000000int get_pty_and_fork(int *fd_master, int *fd_slave); entropybroker-2.9/network_protocol.txt000066400000000000000000000066031305163522000204460ustar00rootroot00000000000000BC: broker to client/server CB: client/server to broker session setup: - BC 4 bytes ascii value protocol version - BC 4 bytes length of string (big endian): - string containing hash function for handshake (password hash) - BC 4 bytes length of string (big endian): - string containing hash function for data hash - BC 4 bytes length of string (big endian): - string containing cipher function for data encryption - BC 4 bytes length of string (big endian): - string containing a random used for authentication *1 - this random is the ascii representation of a 64 bit value - this random is also used to initialize the IV for the blowfish cipher - CB 4 bytes length of string (big endian): - the client sends a string containing username - CB broker then expects 64 bytes of data from the connecting party containing a SHA512 hash of: random *1 concated with a space and then the password If this hash equals to the one calculated by the broker, then the connection proceeds. If not, the broker just closes the connection. - CB 1 byte: > 0 if server - CB 4 bytes length of string (big endian): - string containing description of client/server - BC 4 bytes: max. number of bits allowed to get/put in one go loop: - client/server send 4 bytes ascii containing a command-code: 0001: get bits - 4 bytes value (big endian) containing the number of bits (not bytes) requested data is send in a multiple of bytes so this value is max 9992 (1249) - if there are not enought bits in the broker, a 9000 is end back with a 4-bytes value containing a suggestion for the number of seconds to delay a new get request - if there's a quota problem (not implemented in v1.1), then a 9002 is send with a 4-byte value containg the interval in which the counters will be reset - if data is available, a 0002 is returned with the data: - a hash of the data, using a SHA256 (*1) hash function so 32 bytes in size - the data - the data + hash are encrypted with blowfish (*1) - the blowfish cipher is at start initialized with the user-password as the key - the IV of the cipher is set to the password xored with the authentication random value: this value is stored as 8 bytes - the cipher is used in "cipher feedback" mode ("cfb64") 0002: put bits - see get bits - a full pool will be notified using 9001 with a suggested number of seconds to sleep - a full pool but still allowing the put will be signaled using 9003 (and number of bits) - a regular ack is 0001 (and the number of bits allowed) 0003: server type (type of a process producing entropy data) - 4 bytes value (endian) length of string: - an ascii string describing the server. format is arbitrary 0006: client type - 4 bytes value (endian) length of string: - an ascii string describing the client. format is arbitrary 0011: proxy auth - regular session setup - then, a 0012 reply is send with 0 = ok (yes, that is correct) and 1 = fail - if all pools are full, the broker sends a 9004 (with a 0 value) to all servers - if there's data available (after a pools empty situation), the broker sends a 0009 with a value that can be ignored (= number of bits maxed at 9999) - if all pools are empty, the broker send 0010 (with a 0 value) to all servers *1 since version 2.0, all ciphers, hashers, etc are configurable entropybroker-2.9/plot.cpp000066400000000000000000000040771305163522000157600ustar00rootroot00000000000000#include #include #include //extern "C" { #include //} #define minval(x, y) ((x) < (y) ? (x) : (y)) #define maxval(x, y) ((x) > (y) ? (x) : (y)) int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s file_in.dat result.png\n", argv[0]); return 1; } char *file_in = argv[1]; char *file_out = argv[2]; int bytes = 256 * 256 * sizeof(int); unsigned int *points = (unsigned int *)calloc(1, bytes); FILE *fhi = fopen(file_in, "rb"); if (!fhi) { fprintf(stderr, "Failed to open %s\n", file_in); return 1; } FILE *fho = fopen(file_out, "wb"); if (!fho) { fprintf(stderr, "Failed to create %s\n", file_out); return 1; } while(!feof(fhi)) { int x = fgetc(fhi); int y = fgetc(fhi); if (x < 0 || y < 0) // EOF probably break; points[y * 256 + x]++; } fclose(fhi); unsigned int c_max = 0, c_min = 1 << 31; for(int index=0; index<(256*256); index++) { if (points[index] > c_max) c_max = points[index]; if (points[index] < c_min) c_min = points[index]; } double div = double(c_max) - double(c_min); bytes = 256 * 256 * 3; unsigned char *result = (unsigned char *)calloc(1, bytes); for(int y=0; y<256; y++) { for(int x=0; x<256; x++) { if (points[y * 256 + x] == 0) continue; double val = double(points[y * 256 + x] - c_min) / div; result[y * 256 * 3 + x * 3 + 0] = result[y * 256 * 3 + x * 3 + 2] = 0; result[y * 256 * 3 + x * 3 + 1] = (unsigned char)maxval(minval(255.0, val * 255.0), 0.0); } } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_set_IHDR (png_ptr, info_ptr, 256, 256, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char *row_pointers[256]; for(int y=0; y<256; y++) row_pointers[y] = &result[y * 256 * 3]; png_init_io(png_ptr, fho); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); fclose(fho); return 0; } entropybroker-2.9/pool.cpp000066400000000000000000000217561305163522000157560ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "math.h" #include "hasher.h" #include "hasher_type.h" #include "stirrer.h" #include "stirrer_type.h" #include "random_source.h" #include "pool_crypto.h" #include "pool.h" #include "error.h" #include "kernel_prng_rw.h" #include "log.h" #include "utils.h" pool::pool(int new_pool_size_bytes, bit_count_estimator *bce_in, pool_crypto *pc) : bce(bce_in) { pool_size_bytes = new_pool_size_bytes; entropy_pool = reinterpret_cast(malloc_locked(pool_size_bytes)); bits_in_pool = 0; pool_init(pc); } pool::pool(int pool_nr, FILE *fh, bit_count_estimator *bce_in, pool_crypto *pc) : bce(bce_in) { if (!get_int(fh, &bits_in_pool)) error_exit("loading pool: short read (bit count)"); if (bits_in_pool < 0 || bits_in_pool >= 4194304) // more than 4MB is ridiculous error_exit("Corrupt dump? bits in pool is strange! %d", bits_in_pool); if (!get_int(fh, &pool_size_bytes)) error_exit("loading pool: short read (size)"); if (pool_size_bytes < 0 || pool_size_bytes >= 4194304) // more than 4MB is ridiculous error_exit("Corrupt dump? pool size is strange! %d", pool_size_bytes); entropy_pool = reinterpret_cast(malloc_locked(pool_size_bytes)); int rc = -1; if ((rc = fread(entropy_pool, 1, pool_size_bytes, fh)) != pool_size_bytes) error_exit("Dump is corrupt: are you using disk-pools from an entropybroker version older than v1.1? (expected %d, got %d)", pool_size_bytes, rc); dolog(LOG_DEBUG, "Pool %d: loaded %d bits from cache", pool_nr, bits_in_pool); pool_init(pc); } int pool::get_file_bit_count(std::string file_name) { FILE *fh = fopen(file_name.c_str(), "rb"); if (!fh) error_exit("Failed to open %s", file_name.c_str()); int bit_sum = 0; while(!feof(fh)) { int bits, bytes; if (!get_int(fh, &bits)) break; if (!get_int(fh, &bytes)) error_exit("Short read in %s", file_name.c_str()); bit_sum += bits; if (fseek(fh, bytes, SEEK_CUR) == -1) error_exit("Error seeking in %s", file_name.c_str()); } fclose(fh); return bit_sum; } void pool::pool_init(pool_crypto *pc) { pthread_check(pthread_mutex_init(&lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_cond_init(&cond, NULL), "pthread_cond_init"); entropy_pool_temp = reinterpret_cast(malloc_locked(pool_size_bytes)); ivec_size = pc -> get_stirrer() -> get_ivec_size(); ivec = reinterpret_cast(malloc_locked(ivec_size)); pc -> get_random_source() -> get(ivec, ivec_size); hash_len = pc -> get_hasher() -> get_hash_size(); hash = reinterpret_cast(malloc_locked(hash_len)); memset(&state, 0x00, sizeof state); } pool::~pool() { free_locked(entropy_pool, pool_size_bytes); free_locked(entropy_pool_temp, pool_size_bytes); free_locked(ivec, ivec_size); free_locked(hash, hash_len); pthread_check(pthread_cond_destroy(&cond), "pthread_cond_destroy"); pthread_check(pthread_mutex_destroy(&lck), "pthread_mutex_destroy"); } pthread_cond_t * pool::lock_object() { int rc = -1; if ((rc = pthread_mutex_trylock(&lck))) { if (rc == EBUSY) return &cond; errno = rc; error_exit("pthread_mutex_trylock failed"); } return NULL; } pthread_cond_t * pool::timed_lock_object(double max_time) { my_assert(max_time > 0.0); struct timespec abs_time; while(max_time > 0.0) { pthread_testcancel(); clock_gettime(CLOCK_REALTIME, &abs_time); double cur_time = std::min(max_time, 1.0); abs_time.tv_sec += cur_time; abs_time.tv_nsec += (cur_time - floor(cur_time)) * 1000000000L; if (abs_time.tv_nsec >= 1000000000L) { abs_time.tv_sec++; abs_time.tv_nsec -= 1000000000L; } int rc = -1; rc = pthread_mutex_timedlock(&lck, &abs_time); if (rc == 0) return NULL; if (rc != ETIMEDOUT) { errno = rc; error_exit("pthread_mutex_timedlock failed"); } max_time -= cur_time; } return &cond; } void pool::unlock_object() { my_mutex_unlock(&lck); pthread_check(pthread_cond_signal(&cond), "pthread_cond_signal"); } void pool::dump(FILE *fh) { if (bits_in_pool > 0) { unsigned char val_buffer[8]; val_buffer[0] = (bits_in_pool >> 24) & 255; val_buffer[1] = (bits_in_pool >> 16) & 255; val_buffer[2] = (bits_in_pool >> 8) & 255; val_buffer[3] = (bits_in_pool ) & 255; val_buffer[4] = (pool_size_bytes >> 24) & 255; val_buffer[5] = (pool_size_bytes >> 16) & 255; val_buffer[6] = (pool_size_bytes >> 8) & 255; val_buffer[7] = (pool_size_bytes ) & 255; if (fwrite(val_buffer, 1, 8, fh) != 8) error_exit("Cannot write to dump (1)"); if (fwrite(entropy_pool, 1, pool_size_bytes, fh) != (size_t)pool_size_bytes) error_exit("Cannot write to dump (2)"); } } int pool::add_entropy_data(unsigned char *entropy_data, int n_bytes_in, pool_crypto *pc, int is_n_bits) { my_assert(n_bytes_in > 0); // this implementation is described in RFC 4086 (June 2005) chapter 6.2.1, second paragraph pc -> get_random_source() -> get(ivec, ivec_size); int n_added = is_n_bits; if (n_added == -1) n_added = bce -> get_bit_count(entropy_data, n_bytes_in); while(n_bytes_in > 0) { // when adding data to the pool, we encrypt the pool using blowfish with // the entropy-data as the encryption-key. blowfish allows keysizes with // a maximum of 448 bits which is 56 bytes int cur_to_add = std::min(n_bytes_in, pc -> get_stirrer() -> get_stir_size()); pc -> get_stirrer() -> do_stir(ivec, entropy_pool, pool_size_bytes, entropy_data, cur_to_add, entropy_pool_temp, true); entropy_data += cur_to_add; n_bytes_in -= cur_to_add; } bits_in_pool += n_added; if (bits_in_pool > pool_size_bytes * 8) bits_in_pool = pool_size_bytes * 8; return n_added; } int pool::get_n_bits_in_pool() const { return bits_in_pool; } int pool::get_entropy_data(unsigned char *entropy_data, int n_bytes_requested, bool prng_ok, pool_crypto *pc) { my_assert(n_bytes_requested > 0); // make sure the hash length is equal or less than 448 bits which is the maximum // blowfish key size int n_given, half_hash_len = hash_len / 2;; pc -> get_random_source() -> get(ivec, ivec_size); n_given = n_bytes_requested; if (!prng_ok) n_given = std::min(n_given, bits_in_pool / 8); n_given = std::min(n_given, half_hash_len); if (n_given > 0) { int loop; pc -> get_hasher() -> do_hash(entropy_pool, pool_size_bytes, hash); bits_in_pool -= (n_given * 8); if (bits_in_pool < 0) bits_in_pool = 0; // if the hash is bigger than what we can stir in: fold it unsigned char *dummy_hash_p = hash; int stir_size = pc -> get_stirrer() -> get_stir_size(), index = 0; while(index < hash_len) { int cur_hash_n = std::min(hash_len - index, stir_size); pc -> get_stirrer() -> do_stir(ivec, entropy_pool, pool_size_bytes, dummy_hash_p, cur_hash_n, entropy_pool_temp, false); dummy_hash_p += cur_hash_n; index += cur_hash_n; } // fold into half for(loop=0; loop delta2) delta = delta2; if (delta > delta3) delta = delta3; if (delta == 0) n_bits_added = 0; else n_bits_added = std::max(0, std::min(MAX_EVENT_BITS, int(log(delta) / log(2.0)))); bits_in_pool += n_bits_added; if (bits_in_pool > (pool_size_bytes * 8)) bits_in_pool = (pool_size_bytes * 8); pc -> get_random_source() -> get(ivec, ivec_size); pc -> get_stirrer() -> do_stir(ivec, entropy_pool, pool_size_bytes, (unsigned char *)&ts, sizeof ts, entropy_pool_temp, true); while(n_event_data > 0) { int cur_n_event_data = std::min(n_event_data, pc -> get_stirrer() -> get_stir_size()); pc -> get_stirrer() -> do_stir(ivec, entropy_pool, pool_size_bytes, event_data, cur_n_event_data, entropy_pool_temp, true); event_data += cur_n_event_data; n_event_data -= cur_n_event_data; } return n_bits_added; } unsigned char * pool::expose_contents() { bits_in_pool = 0; return entropy_pool; } entropybroker-2.9/pool.h000066400000000000000000000032441305163522000154130ustar00rootroot00000000000000#define DEFAULT_POOL_SIZE_BITS 32768 #define MAX_EVENT_BITS 11 typedef struct { double last_time; double last_delta, last_delta2; } event_state_t; class pool { private: unsigned char *entropy_pool, *entropy_pool_temp; int pool_size_bytes; unsigned char *ivec; int ivec_size; unsigned char *hash; int hash_len; int bits_in_pool; event_state_t state; bit_count_estimator *bce; pthread_mutex_t lck; pthread_cond_t cond; void pool_init(pool_crypto *pc); public: pool(int new_pool_size_bytes, bit_count_estimator *bce, pool_crypto *pc); pool(int pool_nr, FILE *fh, bit_count_estimator *bce, pool_crypto *pc); ~pool(); void dump(FILE *fh); // this method returns a condition variable if this object // was already(!) locked and NULL if it is was not locked // and you're now the owner of the lock(!) pthread_cond_t * lock_object(); pthread_cond_t * timed_lock_object(double max_time); void unlock_object(); static int get_file_bit_count(std::string file_name); /* -1 if not full, 0 if full */ int add_entropy_data(unsigned char *entropy_data, int n_bytes, pool_crypto *pc, int is_n_bits = -1); /* returns number of bytes returned, set prng_ok to also return data when pool empty */ int get_entropy_data(unsigned char *entropy_data, int n_bytes_requested, bool prng_ok, pool_crypto *pc); int get_get_size() const; int get_get_size_in_bits() const; int get_n_bits_in_pool() const; int get_pool_size() const; int get_pool_size_bytes() const; unsigned char *expose_contents(); // resets bit count to zero bool is_full() const; bool is_almost_full() const; int add_event(double ts, unsigned char *event_data, int n_event_data, pool_crypto *pc); }; entropybroker-2.9/pool_crypto.cpp000066400000000000000000000024151305163522000173450ustar00rootroot00000000000000#include #include "error.h" #include "encrypt_stream.h" #include "encrypt_stream_3des.h" #include "encrypt_stream_aes.h" #include "encrypt_stream_blowfish.h" #include "encrypt_stream_camellia.h" #include "stirrer_type.h" #include "stirrer.h" #include "stirrer_3des.h" #include "stirrer_aes.h" #include "stirrer_blowfish.h" #include "stirrer_camellia.h" #include "hasher_type.h" #include "hasher.h" #include "hasher_md5.h" #include "hasher_ripemd160.h" #include "hasher_sha512.h" #include "hasher_whirlpool.h" #include "random_source.h" #include "pool_crypto.h" pool_crypto::pool_crypto(stirrer_type st, hasher_type ht, random_source_t rst) { if (ht == H_SHA512) h = new hasher_sha512(); else if (ht == H_MD5) h = new hasher_md5(); else if (ht == H_RIPEMD160) h = new hasher_ripemd160(); else if (ht == H_WHIRLPOOL) h = new hasher_whirlpool(); else error_exit("Internal error: no hasher (%d)", ht); if (st == S_BLOWFISH) s = new stirrer_blowfish(); else if (st == S_AES) s = new stirrer_aes(); else if (st == S_3DES) s = new stirrer_3des(); else if (st == S_CAMELLIA) s = new stirrer_camellia(); else error_exit("Internal error: no stirrer (%d)", st); rs = new random_source(rst); } pool_crypto::~pool_crypto() { delete s; delete h; delete rs; } entropybroker-2.9/pool_crypto.h000066400000000000000000000004541305163522000170130ustar00rootroot00000000000000class pool_crypto { private: stirrer *s; hasher *h; random_source *rs; public: pool_crypto(stirrer_type st, hasher_type ht, random_source_t rst); ~pool_crypto(); stirrer * get_stirrer() { return s; } hasher * get_hasher() { return h; } random_source * get_random_source() { return rs; } }; entropybroker-2.9/pools.cpp000066400000000000000000000504011305163522000161260ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "log.h" #include "math.h" #include "hasher_type.h" #include "hasher.h" #include "stirrer_type.h" #include "stirrer.h" #include "pool_crypto.h" #include "pool.h" #include "utils.h" #include "fips140.h" #include "scc.h" #include "pools.h" pools::pools(std::string cache_dir_in, unsigned int max_n_mem_pools_in, unsigned int max_n_disk_pools_in, unsigned int min_store_on_disk_n_in, bit_count_estimator *bce_in, int new_pool_size_in_bytes) : cache_dir(cache_dir_in), max_n_mem_pools(max_n_mem_pools_in), max_n_disk_pools(max_n_disk_pools_in), min_store_on_disk_n(min_store_on_disk_n_in), disk_limit_reached_notified(false), bce(bce_in) { pthread_check(pthread_rwlock_init(&list_lck, NULL), "pthread_rwlock_init"); is_w_locked = false; pthread_check(pthread_mutex_init(&lat_lck, NULL), "pthread_mutex_init"); last_added_to = 0; new_pool_size = new_pool_size_in_bytes; if (min_store_on_disk_n >= max_n_mem_pools) error_exit("min_store_on_disk_n must be less than max_number_of_mem_pools"); if (min_store_on_disk_n < 0) error_exit("min_store_on_disk_n must be at least 0"); if (max_n_mem_pools < 3) error_exit("maximum number of memory pools must be at least 3"); if (max_n_disk_pools < 0) error_exit("maximum number of disk pools must be at least 0"); load_cachefiles_list(); } pools::~pools() { store_caches(0); pthread_check(pthread_mutex_destroy(&lat_lck), "pthread_mutex_destroy"); pthread_check(pthread_rwlock_destroy(&list_lck), "pthread_rwlock_destroy"); } double calc_time_left(double start_ts, double max_time) { return std::max(MIN_SLEEP, max_time - (get_ts() - start_ts)); } double calc_time_left(double start_ts, unsigned int cur, unsigned int n, double max_duration) { double now_ts = get_ts(); double time_left = ((max_duration * 0.9) - (now_ts - start_ts)) / double(n - cur); if (time_left < MIN_SLEEP) return MIN_SLEEP; return time_left; } void pools::list_wlock() { pthread_check(pthread_rwlock_wrlock(&list_lck), "pthread_rwlock_wrlock"); my_assert(is_w_locked == false); is_w_locked = true; } void pools::list_wunlock() { my_assert(is_w_locked); is_w_locked = false; pthread_check(pthread_rwlock_unlock(&list_lck), "pthread_rwlock_unlock"); } void pools::list_runlock() { pthread_check(pthread_rwlock_unlock(&list_lck), "pthread_rwlock_unlock"); } void pools::list_rlock() { pthread_check(pthread_rwlock_rdlock(&list_lck), "pthread_rwlock_rdlock"); } // keep_n == 0: means dump all void pools::store_caches(unsigned int keep_n) { if(max_n_disk_pools == 0) { dolog(LOG_DEBUG, "Disabled disk pools: not creating any"); return; } if (cache_list.size() >= max_n_disk_pools && keep_n != 0) { if (!disk_limit_reached_notified) { dolog(LOG_DEBUG, "Maximum number of disk pools reached: not creating a new one"); disk_limit_reached_notified = true; } } else { disk_limit_reached_notified = false; dolog(LOG_DEBUG, "Storing %d pools on disk (new number of files: %d)", pool_vector.size() - keep_n, cache_list.size() + 1); long double now = get_ts_ns(); char buffer[128]; snprintf(buffer, sizeof buffer, "%Lf", now); std::string new_cache_file = cache_dir + "/" + std::string(buffer) + ".pool"; FILE *fh = fopen(new_cache_file.c_str(), "wb"); if (!fh) error_exit("Failed to create file %s", new_cache_file.c_str()); if (flock(fileno(fh), LOCK_EX) == -1) error_exit("flock(LOCK_EX) for %s failed", new_cache_file.c_str()); int bit_sum = 0; while(pool_vector.size() > keep_n) { if (pool_vector.at(0) -> timed_lock_object(1.0) == NULL) // will always succeed due to writelock on list { int n_bits = pool_vector.at(0) -> get_n_bits_in_pool(); if (n_bits > 0) { bit_sum += n_bits; pool_vector.at(0) -> dump(fh); } pool_vector.at(0) -> unlock_object(); delete pool_vector.at(0); pool_vector.erase(pool_vector.begin() + 0); } } cache_list.push_back(std::pair(new_cache_file, bit_sum)); fflush(fh); if (flock(fileno(fh), LOCK_UN) == -1) error_exit("flock(LOCK_UN) for %s failed", new_cache_file.c_str()); fclose(fh); } } bool pools::load_caches(unsigned int load_n_bits, pool_crypto *pc) { dolog(LOG_DEBUG, "Loading %d bits from pools", load_n_bits); unsigned int bits_loaded = 0; unsigned int files_loaded = 0; while(!cache_list.empty() && bits_loaded < load_n_bits) { dolog(LOG_DEBUG, "Load bits from %s", cache_list.at(0).first.c_str()); FILE *fh = fopen(cache_list.at(0).first.c_str(), "r"); if (!fh) error_exit("Failed to open cache-file %s", cache_list.at(0).first.c_str()); if (flock(fileno(fh), LOCK_EX) == -1) error_exit("flock(LOCK_EX) for %s failed", cache_list.at(0).first.c_str()); while(!feof(fh)) { /// FIXME ugly hack, should throw an exception in pool-constructor if (fgetc(fh) == -1) break; if (fseek(fh, -1, SEEK_CUR) == -1) error_exit("Problem seeking in %s", cache_list.at(0).first.c_str()); ///// FIXME ///// pool *new_pool = new pool(++files_loaded, fh, bce, pc); bits_loaded += new_pool -> get_n_bits_in_pool(); pool_vector.push_back(new_pool); } if (unlink(cache_list.at(0).first.c_str()) == -1) error_exit("Failed to delete cache-file %s", cache_list.at(0).first.c_str()); fflush(fh); if (flock(fileno(fh), LOCK_UN) == -1) error_exit("flock(LOCK_UN) for %s failed", cache_list.at(0).first.c_str()); fclose(fh); cache_list.erase(cache_list.begin()); } if (bits_loaded > 0 || files_loaded > 0) { dolog(LOG_DEBUG, "%d bits loaded from %d files", bits_loaded, files_loaded); return true; } return false; } void pools::flush_empty_pools() { unsigned int deleted = 0; for(int index=pool_vector.size() - 1; index >= 0; index--) { if (pool_vector.at(index) -> timed_lock_object(1.0) == NULL) // will always succeed due to writelock on list { if (pool_vector.at(index) -> get_n_bits_in_pool() == 0) { pool *obj = pool_vector.at(index); pool_vector.erase(pool_vector.begin() + index); obj -> unlock_object(); delete obj; deleted++; } else { pool_vector.at(index) -> unlock_object(); } } } if (deleted) dolog(LOG_DEBUG, "Deleted %d empty pool(s), new count: %d", deleted, pool_vector.size()); } typedef struct { int index; int n_bits; } merge_t; int merge_compare_bits(const void *a, const void *b) { merge_t *ma = (merge_t *)a; merge_t *mb = (merge_t *)b; return ma -> n_bits - mb -> n_bits; } void pools::merge_pools(pool_crypto *pc) { if (pool_vector.empty()) return; int n_merged = 0; int n_in = pool_vector.size(); int process_n = 0; merge_t *list = reinterpret_cast(malloc(n_in * sizeof(merge_t))); for(int index=0; index timed_lock_object(0.01)) continue; list[process_n].index = index; list[process_n].n_bits = pool_vector.at(index) -> get_n_bits_in_pool(); if (list[process_n].n_bits > 0) process_n++; else pool_vector.at(index) -> unlock_object(); } if (process_n > 0) { qsort(list, process_n, sizeof(merge_t), merge_compare_bits); int stir_size = pc -> get_stirrer() -> get_stir_size(); int add_index = -1, max_n_bits = -1;; for(int index=0; index get_pool_size(); if (index == process_n) break; } if (list[add_index].n_bits + list[index].n_bits > max_n_bits + stir_size) { add_index = -1; index--; } else { int i1 = list[add_index].index; int i2 = list[index].index; int data_size = pool_vector.at(i2) -> get_pool_size_bytes(); unsigned char *data = pool_vector.at(i2) -> expose_contents(); pool_vector.at(i1) -> add_entropy_data(data, data_size, pc, list[index].n_bits); n_merged++; } } } for(int index=0; index unlock_object(); free(list); if (n_merged) dolog(LOG_INFO, "%d pool(s) merged, new count: %d", n_merged, pool_vector.size()); } void pools::load_cachefiles_list() { DIR *dirp = opendir(cache_dir.c_str()); if (!dirp) error_exit("Failed to open directory %s", cache_dir.c_str()); struct dirent *de = NULL; while((de = readdir(dirp)) != NULL) { std::string file_name = cache_dir + "/" + std::string(de -> d_name); struct stat ss; if (stat(file_name.c_str(), &ss) == -1) { if (errno == EEXIST) dolog(LOG_WARNING, "File %s suddenly disappeared?!", file_name.c_str()); error_exit("Error doing stat on %s", file_name.c_str()); } if (ss.st_mode & S_IFDIR) continue; if (file_name.substr(file_name.size() - 5, 5) == ".pool") { dolog(LOG_DEBUG, "Added %s to cache list", file_name.c_str()); cache_list.push_back(std::pair(file_name, pool::get_file_bit_count(file_name))); } } closedir(dirp); } bool pools::verify_quality(unsigned char *data, int n, bool ignore_rngtest_fips140, fips140 *pfips, bool ignore_rngtest_scc, scc *pscc) { if (!ignore_rngtest_fips140 || !ignore_rngtest_scc) { for(int rngtest_loop=0; rngtest_loop add(data[rngtest_loop]); pscc -> add(data[rngtest_loop]); } } bool rc_fips140 = true, rc_scc = true; if (!ignore_rngtest_fips140) rc_fips140 = pfips -> is_ok(); if (!ignore_rngtest_scc) rc_scc = pfips -> is_ok(); return rc_fips140 == true && rc_scc == true; } // returns a locked pool int pools::find_non_full_pool(bool timed, double max_duration) { // be carefull that start_ts is not used when timed == false!!! double start_ts = timed ? get_ts() : 0; int n = pool_vector.size(); // please note: it is not required that this offset is cryptographically // random, it is only used to "spread the load" over all the pools int index_offset = rand(); if (index_offset >= INT_MAX - (n + 1)) index_offset /= 2; for(int loop_index=0; loop_index timed_lock_object(cur_max_duration); } else cond = pool_vector.at(index) -> lock_object(); if (!cond) { if (!pool_vector.at(index) -> is_almost_full()) return index; pool_vector.at(index) -> unlock_object(); } } return -1; } // returns a locked pool int pools::select_pool_to_add_to(bool timed, double max_time, pool_crypto *pc) { double start_ts = timed ? get_ts() : 0.0; list_rlock(); double left = timed ? calc_time_left(start_ts, max_time) : -1.0; int index = find_non_full_pool(timed, left); if (index == -1) { list_runlock(); list_wlock(); // at this point (due to context switching between the unlock and the // wlock), there may already be a non-empty pool: that is not a problem if (pool_vector.size() >= max_n_mem_pools) store_caches(std::max(0, int(pool_vector.size()) - int(min_store_on_disk_n))); // see if the number of in-memory pools is reduced after the call to store_caches // it might have not stored any on disk if the limit on the number of files has been reached if (pool_vector.size() < max_n_mem_pools) { dolog(LOG_DEBUG, "Adding empty pool to queue (new number of pools: %d)", pool_vector.size() + 1); pool_vector.push_back(new pool(new_pool_size, bce, pc)); } list_wunlock(); list_rlock(); left = timed ? calc_time_left(start_ts, max_time) : -1.0; index = find_non_full_pool(timed, left); if (index == -1) { // this can happen if // 1. the number of in-memory-pools limit has been reached and // 2. the number of on-disk-pools limit has been reached my_mutex_lock(&lat_lck); last_added_to++; last_added_to %= pool_vector.size(); index = last_added_to; my_mutex_unlock(&lat_lck); left = calc_time_left(start_ts, max_time); if (pool_vector.at(index) -> timed_lock_object(left)) index = -1; } } if (index != -1) { my_mutex_lock(&lat_lck); last_added_to = index; my_mutex_unlock(&lat_lck); } return index; } int pools::get_bit_sum_unlocked(double max_duration) { double start_ts = get_ts(); int bit_count = 0; unsigned int n = pool_vector.size(); for(unsigned int index=0; index timed_lock_object(time_left)) { bit_count += pool_vector.at(index) -> get_n_bits_in_pool(); pool_vector.at(index) -> unlock_object(); } } return bit_count; } int pools::get_bits_from_pools(int n_bits_requested, unsigned char **buffer, bool allow_prng, bool ignore_rngtest_fips140, fips140 *pfips, bool ignore_rngtest_scc, scc *pscc, double max_duration, pool_crypto *pc) { my_assert(n_bits_requested > 0); pthread_testcancel(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL), "pthread_setcancelstate"); double start_ts = get_ts(); int n_to_do_bytes = (n_bits_requested + 7) / 8; int n_to_do_bits = n_to_do_bytes * 8; int n_bits_retrieved = 0; unsigned char *cur_p = *buffer = reinterpret_cast(malloc_locked(n_to_do_bytes + 1)); if (!cur_p) error_exit("transmit_bits_to_client memory allocation failure"); // load bits from disk if needed bool have_bits = true; for(;;) { list_rlock(); if (!have_bits) break; int bits_needed_to_load = n_bits_requested - get_bit_sum_unlocked(max_duration); // no unlock in the break: need to have the list locked later on if (bits_needed_to_load <= 0) break; // a 'list_relock' would be nice list_runlock(); pthread_testcancel(); list_wlock(); merge_pools(pc); flush_empty_pools(); // due to the un- and relock this might have changed // also merging pools might change this value have_bits = load_caches(bits_needed_to_load, pc); list_wunlock(); pthread_testcancel(); } // at this point the list is read locked unsigned int n = pool_vector.size(); int pool_block_size = -1, get_per_pool_n = -1; if (n == 0) { pool_block_size = pc -> get_hasher() -> get_hash_size() / 2; get_per_pool_n = std::max(pool_block_size, n_bits_requested); } else { pool_block_size = pool_vector.at(0) -> get_get_size(); get_per_pool_n = std::max(pool_block_size, n_bits_requested / int(n)); } get_per_pool_n = std::min(get_per_pool_n, new_pool_size); int index_offset = rand(); if (index_offset >= INT_MAX - int(n + 1)) index_offset /= 2; int round = 0; for(;n_to_do_bits > 0 && round < 2;) { // please note: it is not required that this offset is cryptographically // random, it is only used to "spread the load" over all the pools for(unsigned int loop_index=0; loop_index 0; loop_index++) { int index = abs((int)(loop_index + index_offset)) % n; double time_left = calc_time_left(start_ts, loop_index, n, max_duration); pthread_cond_t *cond = NULL; if (round > 0) cond = pool_vector.at(index) -> timed_lock_object(time_left); else cond = pool_vector.at(index) -> lock_object(); if (!cond) { int cur_n_to_get_bits = (round > 0 && allow_prng) ? get_per_pool_n : n_to_do_bits; int cur_n_to_get_bytes = (cur_n_to_get_bits + 7) / 8; unsigned int got_n_bytes = pool_vector.at(index) -> get_entropy_data(cur_p, cur_n_to_get_bytes, round > 0 ? allow_prng : false, pc); unsigned int got_n_bits = got_n_bytes * 8; if (got_n_bits > 0 && verify_quality(cur_p, got_n_bytes, ignore_rngtest_fips140, pfips, ignore_rngtest_scc, pscc)) { cur_p += got_n_bytes; n_to_do_bits -= got_n_bits; n_bits_retrieved += got_n_bits; dolog(LOG_DEBUG, "Retrieved %d bits from pool %d", got_n_bits, index); } pool_vector.at(index) -> unlock_object(); } } round++; } list_runlock(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); pthread_testcancel(); return n_bits_retrieved; } int pools::add_bits_to_pools(unsigned char *data, int n_bytes, bool ignore_rngtest_fips140, fips140 *pfips, bool ignore_rngtest_scc, scc *pscc, double max_duration, pool_crypto *pc) { my_assert(n_bytes > 0); pthread_testcancel(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL), "pthread_setcancelstate"); double start_ts = get_ts(); int n_bits_added = 0; int start_n = n_bytes; int round = 0, n_was_locked = 0; bool first = true; while(n_bytes > 0) { if (first) { list_rlock(); first = false; } int n = pool_vector.size(); list_runlock(); pthread_testcancel(); double time_left = calc_time_left(start_ts, start_n - n_bytes, start_n, max_duration); int index = select_pool_to_add_to(round > 0, time_left, pc); // returns a locked object // the list is now read-locked if (index == -1) { if (++n_was_locked >= n) { n_was_locked = 0; round++; } } else { int space_available = pool_vector.at(index) -> get_pool_size() - pool_vector.at(index) -> get_n_bits_in_pool(); // in that case we're already mixing in so we can change all data anyway // this only happens when all pools are full if (space_available <= pool_vector.at(index) -> get_get_size_in_bits()) space_available = pool_vector.at(index) -> get_pool_size(); unsigned int n_bytes_to_add = std::min(n_bytes, (space_available + 7) / 8); dolog(LOG_DEBUG, "Adding %d bits to pool %d", n_bytes_to_add * 8, index); if (verify_quality(data, n_bytes_to_add, ignore_rngtest_fips140, pfips, ignore_rngtest_scc, pscc)) n_bits_added += pool_vector.at(index) -> add_entropy_data(data, n_bytes_to_add, pc); n_bytes -= n_bytes_to_add; data += n_bytes_to_add; pool_vector.at(index) -> unlock_object(); } } list_runlock(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); pthread_testcancel(); return n_bits_added; } int pools::get_bit_sum(double max_duration) { pthread_testcancel(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL), "pthread_setcancelstate"); list_rlock(); int bit_count = get_bit_sum_unlocked(max_duration); list_runlock(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); pthread_testcancel(); return bit_count; } int pools::add_event(long double event, unsigned char *event_data, int n_event_data, double max_time, pool_crypto *pc) { pthread_testcancel(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL), "pthread_setcancelstate"); int index = select_pool_to_add_to(true, max_time, pc); // returns a locked object // the list is now read-locked and the object as well int rc = 0; if (index != -1) { rc = pool_vector.at(index) -> add_event(event, event_data, n_event_data, pc); pool_vector.at(index) -> unlock_object(); } list_runlock(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); pthread_testcancel(); return rc; } bool pools::all_pools_full(double max_duration) { pthread_testcancel(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL), "pthread_setcancelstate"); double start_ts = get_ts(); bool rc = true; list_rlock(); unsigned int n = pool_vector.size(); if (n < max_n_mem_pools) rc = false; else { for(unsigned int loop=0; loop timed_lock_object(time_left)) { if (!pool_vector.at(loop) -> is_almost_full()) { pool_vector.at(loop) -> unlock_object(); rc = false; break; } pool_vector.at(loop) -> unlock_object(); } } } list_runlock(); pthread_check(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL), "pthread_setcancelstate"); pthread_testcancel(); return rc; } int pools::get_memory_pool_count() { list_rlock(); int n = pool_vector.size(); list_runlock(); return n; } int pools::get_disk_pool_count() { list_rlock(); int n = cache_list.size(); list_runlock(); return n; } int pools::get_disk_pool_bit_count() { int bit_sum = 0; list_rlock(); for(unsigned int index=0; index pool_vector; std::vector > cache_list; std::string cache_dir; unsigned int max_n_mem_pools; unsigned int max_n_disk_pools; unsigned int min_store_on_disk_n; bool disk_limit_reached_notified; bit_count_estimator *bce; int new_pool_size; pthread_rwlock_t list_lck; bool is_w_locked; unsigned int last_added_to; pthread_mutex_t lat_lck; void list_wlock(); void list_wunlock(); void list_rlock(); void list_runlock(); void load_cachefiles_list(); bool load_caches(unsigned int load_n_bits, pool_crypto *pc); void store_caches(unsigned int keep_n); int select_pool_to_add_to(bool timed, double max_time, pool_crypto *pc); int find_non_full_pool(bool timed, double max_duration); void flush_empty_pools(); void merge_pools(pool_crypto *pc); bool verify_quality(unsigned char *data, int n, bool ignore_rngtest_fips140, fips140 *pfips, bool ignore_rngtest_scc, scc *pscc); int get_bit_sum_unlocked(double max_duration); public: pools(std::string cache_dir, unsigned int max_n_mem_pools, unsigned int max_n_disk_pools, unsigned int min_store_on_disk_n, bit_count_estimator *bce_in, int new_pool_size_in_bytes); ~pools(); int get_bits_from_pools(int n_bits_requested, unsigned char **buffer, bool allow_prng, bool ignore_rngtest_fips140, fips140 *pfips, bool ignore_rngtest_scc, scc *pscc, double max_duration, pool_crypto *pc); int add_bits_to_pools(unsigned char *data, int n_bytes, bool ignore_rngtest_fips140, fips140 *prt, bool ignore_rngtest_scc, scc *pscc, double max_duration, pool_crypto *pc); int get_bit_sum(double max_duration); int add_event(long double event, unsigned char *event_data, int n_event_data, double max_time, pool_crypto *pc); bool all_pools_full(double max_duration); int get_memory_pool_count(); int get_disk_pool_count(); int get_disk_pool_bit_count(); }; entropybroker-2.9/protocol.cpp000066400000000000000000000371551305163522000166460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "log.h" #include "utils.h" #include "math.h" #include "encrypt_stream.h" #include "hasher.h" #include "hasher_type.h" #include "stirrer.h" #include "stirrer_type.h" #include "fips140.h" #include "scc.h" #include "kernel_prng_io.h" #include "server_utils.h" #include "protocol.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" int recv_length_data(int fd, char **data, unsigned int *len, double to) { if (!recv_uint(fd, len, to)) return -1; if (*len == 0) *data = NULL; else if (*len > 100 * 1024 * 1024) // TODO there now is a limit on the data transmitted return -1; else { *data = reinterpret_cast(malloc(*len + 1)); if (!*data) { dolog(LOG_WARNING, "Cannot allocate %d bytes of memory (amount of data to be transmitted by fd: %d)", *len + 1, fd); return -1; } if (READ_TO(fd, *data, int(*len), to) != int(*len)) { free(*data); *data = NULL; return -1; } (*data)[*len] = 0x00; } return 0; } int send_length_data(int fd, const char *data, unsigned int len, double to) { if (!send_uint(fd, len, to)) return -1; if (len > 0 && WRITE_TO(fd, data, int(len), to) != int(len)) return -1; return 0; } void make_msg(unsigned char *where_to, unsigned int code, unsigned int value) { if (code > 9999) error_exit("invalid code: %d", code); snprintf(reinterpret_cast(where_to), 5, "%04d", code); uint_to_uchar(value, &where_to[4]); } void calc_ivec(const char *password, long long unsigned int rnd, long long unsigned int counter, size_t ivec_size, unsigned char *dest) { unsigned char *prnd = reinterpret_cast(&rnd); unsigned char *pcnt = reinterpret_cast(&counter); memset(dest, 0x00, ivec_size); memcpy(dest, password, std::min(strlen(password), ivec_size)); unsigned int index_dest = 0, index_rnd = 0, rnd_len = sizeof rnd; while(index_dest < ivec_size) { dest[index_dest] ^= prnd[index_rnd]; dest[index_dest] ^= pcnt[index_rnd]; index_dest++; index_rnd++; if (index_rnd == rnd_len) index_rnd = 0; } } protocol::protocol(std::vector *hosts_in, std::string username_in, std::string password_in, bool is_server_in, std::string type_in, double comm_time_out_in) : hosts(hosts_in), username(username_in), password(password_in), is_server(is_server_in), type(type_in), comm_time_out(comm_time_out_in) { host_index = 0; stream_cipher = NULL; mac_hasher = NULL; socket_fd = -1; sleep_9003 = 300; pingnr = 0; ivec_counter = 0; challenge = 13; max_get_put_size = 1249; } protocol::~protocol() { if (socket_fd != -1) { unsigned char logout_msg[8] = { 0 }; make_msg(logout_msg, 9999, 0); // 9999 = logout (void)WRITE_TO(socket_fd, logout_msg, 8, comm_time_out); close(socket_fd); } delete stream_cipher; delete mac_hasher; } void protocol::error_sleep(int count) { long int sleep_micro_seconds = myrand(count * 1000000) + 1; dolog(LOG_WARNING, "Failed connecting (%s), sleeping for %f seconds", strerror(errno), double(sleep_micro_seconds) / 1000000.0); usleep((long)sleep_micro_seconds); } reconnect_status_t protocol::reconnect_server_socket(bool *do_exit) { reconnect_status_t rc = RSS_FAIL; char connect_msg = 0; // connect to server if (socket_fd == -1) { rc = RSS_NEW_CONNECTION; connect_msg = 1; delete stream_cipher; stream_cipher = NULL; delete mac_hasher; mac_hasher = NULL; unsigned int host_try_count = 0; int count = 1; std::string cipher_data, mac_hash; for(;;) { std::string host; int port = DEFAULT_BROKER_PORT; split_resource_location(hosts -> at(host_index), host, port); dolog(LOG_INFO, "Connecting to %s:%d", host.c_str(), port); socket_fd = connect_to(host.c_str(), port); if (socket_fd != -1) { if (auth_client_server(socket_fd, 10, username, password, &challenge, is_server, type, cipher_data, mac_hash, &max_get_put_size) == 0) break; close(socket_fd); socket_fd = -1; } if (do_exit && *do_exit) return RSS_FAIL; host_index++; if (host_index == hosts -> size()) { host_index = 0; error_sleep(count); } else { dolog(LOG_WARNING, "Failed to connect to %s:%d (%s), continuing with next host", host.c_str(), port, strerror(errno)); } host_try_count++; if (host_try_count == hosts -> size()) dolog(LOG_WARNING, "All hosts are not reachable, still trying"); if (count < 16) count++; } stream_cipher = encrypt_stream::select_cipher(cipher_data); unsigned char ivec[8] = { 0 }; calc_ivec(password.c_str(), challenge, 0, stream_cipher -> get_ivec_size(), ivec); #ifdef CRYPTO_DEBUG printf("IVEC: "); hexdump(ivec, 8); #endif unsigned char *pw_char = reinterpret_cast(const_cast(password.c_str())); stream_cipher -> init(pw_char, password.length(), ivec); mac_hasher = hasher::select_hasher(mac_hash); } else { rc = RSS_STILL_CONNECTED; } if (connect_msg) dolog(LOG_INFO, "Connected"); return rc; } int protocol::sleep_interruptable(double how_long, bool *do_exit) { if (socket_fd == -1) return -1; int rc = -1; fd_set rfds; for(;;) { FD_ZERO(&rfds); FD_SET(socket_fd, &rfds); struct timeval tv; tv.tv_sec = how_long; tv.tv_usec = (how_long - double(tv.tv_sec)) * 1000000.0; rc = select(socket_fd + 1, &rfds, NULL, NULL, &tv); if (do_exit && *do_exit) return -1; if (rc != -1 || errno != EINTR) break; } if (rc > 0 && FD_ISSET(socket_fd, &rfds)) { char buffer[8]; if (READ_TO(socket_fd, buffer, 8, comm_time_out, do_exit) != 8) { dolog(LOG_INFO, "error receiving unsollicited message"); return -1; } buffer[4] = 0x00; // don't care about the value if (memcmp(buffer, "0010", 4) == 0) dolog(LOG_INFO, "Broker requests for data"); if (memcmp(buffer, "0009", 4) == 0) dolog(LOG_INFO, "Broker informs about data being available"); else if (memcmp(buffer, "9004", 4) != 0) dolog(LOG_WARNING, "Unexpected message '%s' received from broker! (1)", buffer); else dolog(LOG_WARNING, "Unexpected message '%s' received from broker! (2)", buffer); } return 0; } int protocol::message_transmit_entropy_data(unsigned char *bytes_in, unsigned int n_bytes, bool *do_exit) { int error_count = 0; while(n_bytes > 0) { unsigned n_done = -1; for(;;) { unsigned char reply[8] = { 0 }; unsigned char header[8] = { 0 }; if (do_exit && *do_exit) return -1; error_count++; if (error_count > MAX_ERROR_SLEEP) error_count = MAX_ERROR_SLEEP; reconnect_status_t rss = reconnect_server_socket(do_exit); if (rss == RSS_FAIL) continue; disable_nagle(socket_fd); enable_tcp_keepalive(socket_fd); dolog(LOG_DEBUG, "request to send %d bytes", n_bytes); make_msg(header, 2, std::min(max_get_put_size, n_bytes * 8)); // 0002 xmit data request // header if (WRITE_TO(socket_fd, header, 8, comm_time_out, do_exit) != 8) { if (do_exit && *do_exit) return -1; dolog(LOG_INFO, "error transmitting header"); close(socket_fd); socket_fd = -1; error_sleep(error_count); continue; } // ack from server? ignore_unsollicited_msg: // we jump to this label when unsollicited msgs are // received during data-transmission handshake if (READ_TO(socket_fd, reply, 8, comm_time_out, do_exit) != 8) { if (do_exit && *do_exit) return -1; dolog(LOG_INFO, "error receiving ack/nack"); close(socket_fd); socket_fd = -1; error_sleep(error_count); continue; } unsigned int value = uchar_to_uint(&reply[4]); if (memcmp(reply, "0001", 4) == 0 || memcmp(reply, "9003", 4) == 0) // ACK { unsigned int cur_n_bytes = (value + 7) / 8; if (cur_n_bytes > n_bytes) error_exit("ERROR: server requesting more data than available"); dolog(LOG_DEBUG, "Transmitting %d bytes", cur_n_bytes); // encrypt data int hash_len = mac_hasher -> get_hash_size(); int with_hash_n = cur_n_bytes + hash_len; unsigned char *bytes_out = reinterpret_cast(malloc(with_hash_n)); if (!bytes_out) error_exit("out of memory"); unsigned char *temp_buffer = reinterpret_cast(malloc_locked(with_hash_n)); if (!temp_buffer) error_exit("out of memory"); mac_hasher -> do_hash(bytes_in, cur_n_bytes, temp_buffer); memcpy(&temp_buffer[hash_len], bytes_in, cur_n_bytes); stream_cipher -> encrypt(temp_buffer, with_hash_n, bytes_out); free_locked(temp_buffer, with_hash_n); if (WRITE_TO(socket_fd, bytes_out, with_hash_n, comm_time_out, do_exit) != with_hash_n) { if (do_exit && *do_exit) return -1; dolog(LOG_INFO, "error transmitting data"); free(bytes_out); close(socket_fd); socket_fd = -1; error_sleep(error_count); continue; } free(bytes_out); if (memcmp(reply, "9003", 4) == 0) // ACK but full { // only usefull for eb_proxy dolog(LOG_DEBUG, "pool full, sleeping %d seconds (with ACK)", sleep_9003); // same comments as for 9001 apply sleep_interruptable(sleep_9003); } n_done = cur_n_bytes; break; } else if (memcmp(reply, "9001", 4) == 0) // NACK { dolog(LOG_DEBUG, "pool full, sleeping %d seconds", value); sleep_9003 = (sleep_9003 + value * 2) / 2; // now we should sleep and wait for either the time // to pass or a 0010 to come in. in reality we just // sleep until the first message comes in and then // continue; it'll only be 0010 anyway sleep_interruptable(value); } else if (memcmp(reply, "0010", 4) == 0) // there's a need for data { // this message can be received during transmission hand- // shake as it might have been queued earlier goto ignore_unsollicited_msg; } else if (memcmp(reply, "9004", 4) == 0) // all pools full, only for provies goto ignore_unsollicited_msg; else if (memcmp(reply, "0009", 4) == 0) // got data goto ignore_unsollicited_msg; else { dolog(LOG_CRIT, "garbage received: %s", reply); error_sleep(error_count); continue; } error_count = 1; } n_bytes -= n_done; bytes_in += n_done; } return 0; } int protocol::request_bytes(unsigned char *where_to, unsigned int n_bits, bool fail_on_no_bits, bool *do_exit) { bool request_sent = false; if (n_bits < 8) error_exit("Internal error: must request at list 8 bits"); double sleep_trigger = -1; int error_count = 0; for(;;) { if (do_exit && *do_exit) return -1; error_count++; if (error_count > MAX_ERROR_SLEEP) error_count = MAX_ERROR_SLEEP; reconnect_status_t rss = reconnect_server_socket(do_exit); if (rss == RSS_FAIL) error_exit("Failed to connect"); else if (rss == RSS_NEW_CONNECTION) request_sent = false; unsigned char request[8]; make_msg(request, 1, std::min(max_get_put_size, n_bits)); // 0001 if (!request_sent || (sleep_trigger > 0.0 && get_ts() >= sleep_trigger)) { sleep_trigger = -1.0; dolog(LOG_DEBUG, "Send request (%s)", request); if (WRITE(socket_fd, request, 8) != 8) { if (do_exit && *do_exit) return -1; close(socket_fd); socket_fd = -1; error_sleep(error_count); continue; } request_sent = true; } unsigned char reply[8]; int rc = READ_TO(socket_fd, reply, 8, comm_time_out, do_exit); if (do_exit && *do_exit) return -1; if (rc == 0) continue; if (rc != 8) { dolog(LOG_INFO, "Read error, got %d of 8 bytes", rc); close(socket_fd); socket_fd = -1; error_sleep(error_count); continue; } dolog(LOG_DEBUG, "received reply: %s", reply); if (memcmp(reply, "9000", 4) == 0 || memcmp(reply, "9002", 4) == 0) // no data/quota { error_count = 0; unsigned int sleep_time = uchar_to_uint(&reply[4]); dolog(LOG_DEBUG, "data denied: %s, sleep for %d seconds", reply[3] == '0' ? "no data" : "quota", sleep_time); sleep_trigger = get_ts() + sleep_time; if (fail_on_no_bits) return 0; } else if (memcmp(reply, "0004", 4) == 0) /* ping request */ { error_count = 0; dolog(LOG_DEBUG, "PING"); unsigned char xmit_buffer[8]; make_msg(xmit_buffer, 5, pingnr++); // 0005 if (WRITE_TO(socket_fd, xmit_buffer, 8, comm_time_out, do_exit) != 8) { if (do_exit && *do_exit) return -1; close(socket_fd); socket_fd = -1; } } else if (memcmp(reply, "0009", 4) == 0) { error_count = 0; dolog(LOG_INFO, "Broker informs about data"); if (sleep_trigger > 0.0) sleep_trigger = 2.0; } else if (memcmp(reply, "0010", 4) == 0) { error_count = 0; dolog(LOG_INFO, "Broker requests data"); } else if (memcmp(reply, "9004", 4) == 0) { error_count = 0; dolog(LOG_INFO, "Broker is full"); } else if (memcmp(reply, "0002", 4) == 0) // there's data! { error_count = 0; int will_get_n_bits = uchar_to_uint(&reply[4]); int will_get_n_bytes = (will_get_n_bits + 7) / 8; dolog(LOG_INFO, "server is offering %d bits (%d bytes)", will_get_n_bits, will_get_n_bytes); if (will_get_n_bytes == 0) { dolog(LOG_CRIT, "Broker is offering 0 bits?! Please report this to folkert@vanheusden.com"); request_sent = false; continue; } int hash_len = mac_hasher -> get_hash_size(); int xmit_bytes = will_get_n_bytes + hash_len; #ifdef CRYPTO_DEBUG printf("bytes: %d\n", xmit_bytes); #endif unsigned char *buffer_in = reinterpret_cast(malloc(xmit_bytes)); if (!buffer_in) error_exit("out of memory allocating %d bytes", will_get_n_bytes); if (READ_TO(socket_fd, buffer_in, xmit_bytes, comm_time_out, do_exit) != xmit_bytes) { if (do_exit && *do_exit) return -1; dolog(LOG_INFO, "Network read error (data)"); free(buffer_in); close(socket_fd); socket_fd = -1; request_sent = false; continue; } // decrypt unsigned char *temp_buffer = reinterpret_cast(malloc_locked(xmit_bytes)); stream_cipher -> decrypt(buffer_in, xmit_bytes, temp_buffer); // verify data is correct unsigned char *hash = reinterpret_cast(malloc(hash_len)); mac_hasher -> do_hash(&temp_buffer[hash_len], will_get_n_bytes, hash); #ifdef CRYPTO_DEBUG printf("in : "); hexdump(temp_buffer, hash_len); printf("calc: "); hexdump(hash, hash_len); printf("data: "); hexdump(temp_buffer + hash_len, 8); #endif if (memcmp(hash, temp_buffer, hash_len) != 0) error_exit("Data corrupt!"); #ifdef CRYPTO_DEBUG else printf("data is OK\n"); #endif memcpy(where_to, &temp_buffer[hash_len], will_get_n_bytes); free_locked(temp_buffer, xmit_bytes); free(buffer_in); free(hash); dolog(LOG_DEBUG, "got %d bits", will_get_n_bytes * 8); return will_get_n_bytes; } else { dolog(LOG_WARNING, "Unknown message %s received (disconnecting)", reply); close(socket_fd); socket_fd = -1; error_sleep(error_count); } } return 0; } void protocol::drop() { close(socket_fd); socket_fd = -1; } entropybroker-2.9/protocol.h000066400000000000000000000031541305163522000163030ustar00rootroot00000000000000#define PROTOCOL_VERSION 7 int recv_length_data(int fd, char **data, unsigned int *len, double to); int send_length_data(int fd, const char *data, unsigned int len, double to); void make_msg(unsigned char *where_to, unsigned int code, unsigned int value); void calc_ivec(const char *password, long long unsigned int rnd, long long unsigned int counter, size_t ivec_size, unsigned char *dest); typedef enum { RSS_STILL_CONNECTED = 1, RSS_NEW_CONNECTION, RSS_FAIL } reconnect_status_t; class protocol { private: std::vector *hosts; unsigned int host_index; std::string username, password; bool is_server; std::string type; double comm_time_out; // int pingnr; int socket_fd; int sleep_9003; long long unsigned ivec_counter, challenge; // unsigned int max_get_put_size; encrypt_stream *stream_cipher; hasher *mac_hasher; void do_encrypt(unsigned char *buffer_in, unsigned char *buffer_out, int n_bytes); void do_decrypt(unsigned char *buffer_in, unsigned char *buffer_out, int n_bytes); reconnect_status_t reconnect_server_socket(bool *do_exit); void error_sleep(int count); public: protocol(std::vector * hosts_in, std::string username, std::string password, bool is_server, std::string type, double comm_time_out); ~protocol(); unsigned int get_max_get_put_size() { return max_get_put_size; } int sleep_interruptable(double how_long, bool *do_exit = NULL); int message_transmit_entropy_data(unsigned char *bytes_in, unsigned int n_bytes, bool *do_exit = NULL); int request_bytes(unsigned char *where_to, unsigned int n_bits, bool fail_on_no_bits, bool *do_exit = NULL); void drop(); }; entropybroker-2.9/proxy_knuth_b.cpp000066400000000000000000000376201305163522000176750ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "math.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #include "kernel_prng_io.h" #define KNUTH_SIZE 8192 #define KNUTH_FILE "lookup.knuthb" const char *pid_file = PID_DIR "/proxy_knuth_b.pid"; const char *client_type = "proxy_knuth_b v" VERSION; volatile bool sig_quit = false; typedef struct { int fd; std::string host, type; long long unsigned int challenge; long long unsigned int ivec_counter; encrypt_stream *sc; hasher *mac; random_source *rs; } proxy_client_t; typedef struct { unsigned short *table; int t_size, t_offset; unsigned short *A; int n_A; pthread_mutex_t lock; } lookup_t; int read_value(FILE *fh) { unsigned char buffer[4]; if (fread(buffer, 1, 4, fh) != 4) error_exit("short read on file, please delete cache file and retry"); return (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0]; } void write_value(FILE *fh, int value) { unsigned char buffer[4]; buffer[3] = (value >> 24) & 255; buffer[2] = (value >> 16) & 255; buffer[1] = (value >> 8) & 255; buffer[0] = (value ) & 255; if (fwrite(buffer, 1, 4, fh) != 4) error_exit("short write on file, please delete cache file"); } void load_knuth_file(std::string file, lookup_t *lt) { FILE *fh = fopen(file.c_str(), "rb"); if (!fh) { if (errno != ENOENT) error_exit("Error accessing file %s", file.c_str()); dolog(LOG_INFO, "No cache file '%s' exists, starting with fresh buffers", file.c_str()); lt -> t_size = KNUTH_SIZE; lt -> table = (unsigned short *)malloc(lt -> t_size * sizeof(unsigned short)); lt -> A = (unsigned short *)malloc(KNUTH_SIZE * sizeof(unsigned short)); } else { dolog(LOG_INFO, "Reading cached data from %s", file.c_str()); lt -> t_size = read_value(fh); lt -> t_offset = read_value(fh); lt -> table = (unsigned short *)malloc(lt -> t_size * sizeof(unsigned short)); size_t bytes = lt -> t_size * sizeof(unsigned short); if (fread(lt -> table, 1, bytes, fh) != bytes) error_exit("Short read in file, please delete %s and retry", file.c_str()); int dummy = read_value(fh); if (dummy != KNUTH_SIZE) error_exit("Unexpected A/B size %d (expecting %d), please delete %s and retry", dummy, KNUTH_SIZE, file.c_str()); bytes = KNUTH_SIZE * sizeof(unsigned short); lt -> A = (unsigned short *)malloc(KNUTH_SIZE * sizeof(unsigned short)); if (fread(lt -> A, 1, bytes, fh) != bytes) error_exit("Short read in file, please delete %s and retry", file.c_str()); fclose(fh); } } void write_knuth_file(std::string file, lookup_t *lt) { dolog(LOG_INFO, "Writing cached data to %s", file.c_str()); FILE *fh = fopen(file.c_str(), "wb"); if (!fh) error_exit("Failed to create file %s", file.c_str()); write_value(fh, lt -> t_size); write_value(fh, lt -> t_offset); size_t bytes = lt -> t_size * sizeof(unsigned short); if (fwrite(lt -> table, 1, bytes, fh) != bytes) error_exit("Error writing to file %s", file.c_str()); write_value(fh, KNUTH_SIZE); bytes = KNUTH_SIZE * sizeof(unsigned short); if (fwrite(lt -> A, 1, bytes, fh) != bytes) error_exit("Error writing to file %s", file.c_str()); fclose(fh); } int put_data(proxy_client_t *client, lookup_t *lt) { unsigned char bit_cnt[4] = { 0 }; // receive number of bits if (READ_TO(client -> fd, bit_cnt, 4, DEFAULT_COMM_TO) != 4) return -1; unsigned int cur_n_bits = uchar_to_uint(bit_cnt); if (cur_n_bits > 9992) // FIXME might be bigger now return -1; unsigned char reply[4 + 4] = { 0 }; make_msg(reply, 1, cur_n_bits); // make_msg(reply, full ? 9003 : 1, cur_n_bits); if (WRITE_TO(client -> fd, reply, 8, DEFAULT_COMM_TO) != 8) return -1; unsigned int cur_n_bytes = (cur_n_bits + 7) / 8; int hash_len = client -> mac -> get_hash_size(); unsigned int in_len = cur_n_bytes + hash_len; unsigned char *buffer_in = reinterpret_cast(malloc(in_len)); if (!buffer_in) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), in_len); if (READ_TO(client -> fd, buffer_in, in_len, DEFAULT_COMM_TO) != int(in_len)) { dolog(LOG_INFO, "put|%s short read while retrieving entropy data", client -> host.c_str()); free(buffer_in); return -1; } unsigned char *buffer_out = reinterpret_cast(malloc(in_len)); if (!buffer_out) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), cur_n_bytes); // FIXME lock_mem(buffer_out, cur_n_bytes); // decrypt data client -> sc -> decrypt(buffer_in, in_len, buffer_out); unsigned char *entropy_data = &buffer_out[hash_len]; int entropy_data_len = cur_n_bytes; unsigned char *hash = reinterpret_cast(malloc(hash_len)); client -> mac -> do_hash(entropy_data, entropy_data_len, hash); if (memcmp(hash, buffer_out, hash_len) != 0) { dolog(LOG_WARNING, "Hash mismatch in retrieved entropy data!"); free(buffer_out); free(buffer_in); free(hash); return -1; } free(hash); my_mutex_lock(< -> lock); bool use = false; if (lt -> t_offset < lt -> t_size) { int n = lt -> t_size - lt -> t_offset; int do_n_bytes = std::min((unsigned int)(n * sizeof(unsigned short)), cur_n_bytes); memcpy(lt -> table, buffer_out, do_n_bytes); lt -> t_offset += do_n_bytes / sizeof(unsigned short); if (lt -> t_offset == lt -> t_size) dolog(LOG_INFO, "look-up table is filled"); else dolog(LOG_DEBUG, "Look-up table fill: %.2f%%", double(lt -> t_offset * 100) / double(lt -> t_size)); use = true; } else { int n = KNUTH_SIZE - lt -> n_A; int do_n_bytes = std::min((unsigned int)(n * sizeof(unsigned short)), cur_n_bytes); if (do_n_bytes > 0) { memcpy(< -> A[lt -> n_A], buffer_out, do_n_bytes); lt -> n_A += do_n_bytes / sizeof(unsigned short); use = true; } } if (use) dolog(LOG_DEBUG, "storing %d bits from %s", cur_n_bits, client -> host.c_str()); my_mutex_unlock(< -> lock); // memset // unlock_mem free(buffer_out); free(buffer_in); return 0; } int handle_client(proxy_client_t *client, lookup_t *lt) { char cmd[4] = { 0 }; if (READ_TO(client -> fd, cmd, 4, DEFAULT_COMM_TO) != 4) { dolog(LOG_INFO, "Short read on fd %d / %s", client -> fd, client -> host.c_str()); return -1; } if (memcmp(cmd, "0002", 4) == 0) // put data { return put_data(client, lt); } else { dolog(LOG_WARNING, "Unknown / unexpected message %s received", cmd); return -1; } return 0; } typedef struct { protocol *p; lookup_t *lt; } thread_pars_t; void * thread(void *pars) { thread_pars_t *p = (thread_pars_t *)pars; for(;!sig_quit;) { my_mutex_lock(&p -> lt -> lock); // transmit to broker bool send = false; if (p -> lt -> n_A >= 2) { send = true; dolog(LOG_DEBUG, "buffered data: %d", p -> lt -> n_A); } while (p -> lt -> n_A >= 2 && !sig_quit) { int n_short = 4096 / sizeof(unsigned short); int n = std::min(n_short, p -> lt -> n_A / 2); int n_bytes = n * sizeof(unsigned short); unsigned short *out = (unsigned short *)malloc(n_bytes); dolog(LOG_DEBUG, "Processing %d shorts", n); for(int loop=0; loop lt -> A[p -> lt -> n_A - 1]; p -> lt -> n_A--; int y = p -> lt -> A[p -> lt -> n_A - 1]; p -> lt -> n_A--; int j = x % p -> lt -> t_size; int v = p -> lt -> table[j]; p -> lt -> table[j] = y; out[loop] = v; } my_mutex_unlock(&p -> lt -> lock); (void)p -> p -> message_transmit_entropy_data(reinterpret_cast(out), n_bytes); free(out); my_mutex_lock(&p -> lt -> lock); } if (send) dolog(LOG_DEBUG, "Finished transmitting"); my_mutex_unlock(&p -> lt -> lock); usleep(250000); // FIXME condwait or so } return NULL; } void sig_handler(int sig) { dolog(LOG_INFO, "Got signal %d", sig); if (sig == SIGTERM || sig == SIGINT || sig == SIGQUIT) sig_quit = true; else { fprintf(stderr, "Exit due to signal %d\n", sig); unlink(pid_file); exit(0); } } void help() { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-j adapter adapter to listen on\n"); printf("-p port port to listen on (default: %d)\n", DEFAULT_PROXY_LISTEN_PORT); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-V file store buffers to this file (default: %s/%s)\n", CACHE_DIR, KNUTH_FILE); printf("-P file write pid to file\n"); printf("-X file read username+password from file (to authenticate to broker)\n"); printf("-U file read u/p for clients from file (to authenticate local clients)\n"); } int main(int argc, char *argv[]) { const char *listen_adapter = "0.0.0.0"; int listen_port = DEFAULT_PROXY_LISTEN_PORT; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; std::string username, password; std::string clients_auths; std::string knuth_file = CACHE_DIR + std::string("/") + KNUTH_FILE; std::vector hosts; int log_level = LOG_INFO; random_source_t rst = RS_CRYPTOPP; std::string cipher = "blowfish", handshake_hash = "sha512", mac_hasher = "md5"; printf("proxy_knuth_b, (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "V:j:p:U:hf:X:P:I:L:l:sn")) != -1) { switch(c) { case 'V': knuth_file = optarg; break; case 'j': listen_adapter = optarg; break; case 'p': listen_port = atoi(optarg); break; case 'U': clients_auths = optarg; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: fprintf(stderr, "-%c not known\n", c); help(); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("password + username cannot be empty"); if (clients_auths.length() == 0) error_exit("No file with usernames + passwords selected for client authentication"); if (hosts.empty()) error_exit("No host to connect to selected"); (void)umask(0177); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); // bit rate is dummy, only servers connect to the proxy users *user_map = new users(clients_auths, 4096); protocol *p = new protocol(&hosts, username, password, true, client_type, DEFAULT_COMM_TO); no_core(); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); proxy_client_t *clients[2] = { new proxy_client_t, new proxy_client_t }; int listen_socket_fd = start_listen(listen_adapter, listen_port, 5); clients[0] -> fd = -1; clients[1] -> fd = -1; lookup_t lt; memset(<, 0x00, sizeof lt); load_knuth_file(knuth_file, <); pthread_check(pthread_mutex_init(<.lock, NULL), "pthread_mutex_init"); thread_pars_t tp = { p, < }; pthread_t th; pthread_check(pthread_create(&th, NULL, thread, &tp), "pthread_create"); statistics_global sg; for(;!sig_quit;) { fd_set rfds; FD_ZERO(&rfds); int max_fd = -1; FD_SET(listen_socket_fd, &rfds); max_fd = std::max(max_fd, listen_socket_fd); for(int client_index=0; client_index<2; client_index++) { if (clients[client_index] -> fd != -1) { FD_SET(clients[client_index] -> fd, &rfds); max_fd = std::max(max_fd, clients[client_index] -> fd); } } sigset_t sig_set; if (sigemptyset(&sig_set) == -1) error_exit("sigemptyset"); if (pselect(max_fd + 1, &rfds, NULL, NULL, NULL, &sig_set) == -1) { if (errno != EINTR) error_exit("select failed"); continue; } for(int client_index=0; client_index<2; client_index++) { if (clients[client_index] -> fd != -1 && FD_ISSET(clients[client_index] -> fd, &rfds)) { if (handle_client(clients[client_index], <) == -1) { close(clients[client_index] -> fd); clients[client_index] -> fd = -1; delete clients[client_index] -> sc; delete clients[client_index] -> mac; delete clients[client_index] -> rs; } } } if (!sig_quit && FD_ISSET(listen_socket_fd, &rfds)) { int new_socket_fd = accept(listen_socket_fd, NULL, NULL); if (new_socket_fd != -1) { std::string host = get_endpoint_name(new_socket_fd); dolog(LOG_INFO, "new client: %s (fd: %d)", host.c_str(), new_socket_fd); encrypt_stream *enc = encrypt_stream::select_cipher(cipher); hasher *mac = hasher::select_hasher(mac_hasher); random_source *rs = new random_source(rst); std::string client_username, client_password; long long unsigned int challenge = 1; bool is_server = false; std::string type; if (auth_eb(new_socket_fd, DEFAULT_COMM_TO, user_map, client_username, client_password, &challenge, &is_server, type, rs, enc, mac, handshake_hash, 4096, &sg) == 0) { dolog(LOG_INFO, "%s/%s %d/%d (%s)", host.c_str(), type.c_str(), new_socket_fd, is_server, client_username.c_str()); if (clients[0] -> fd != -1 && clients[1] -> fd != -1) { dolog(LOG_WARNING, "New connection with 2 clients connected: dropping all previous connections"); close(clients[0] -> fd); close(clients[1] -> fd); clients[0] -> fd = -1; clients[1] -> fd = -1; delete clients[0] -> sc; delete clients[1] -> sc; delete clients[0] -> mac; delete clients[1] -> mac; delete clients[0] -> rs; delete clients[1] -> rs; } proxy_client_t *pcp = NULL; if (clients[0] -> fd == -1) pcp = clients[0]; else if (clients[1] -> fd == -1) pcp = clients[1]; pcp -> fd = new_socket_fd; pcp -> challenge = challenge; char dummy_str[256]; snprintf(dummy_str, sizeof dummy_str, "%s", host.c_str()); pcp -> host = dummy_str; pcp -> challenge = challenge; pcp -> ivec_counter = 0; unsigned char ivec[8] = { 0 }; calc_ivec(client_password.c_str(), pcp -> challenge, pcp -> ivec_counter, enc -> get_ivec_size(), ivec); pcp -> sc = enc; unsigned char *pw_char = reinterpret_cast(const_cast(client_password.c_str())); pcp -> sc -> init(pw_char, client_password.length(), ivec); pcp -> mac = mac; pcp -> rs = rs; } else { close(new_socket_fd); delete enc; delete mac; delete rs; } } } } dolog(LOG_INFO, "Terminating..."); pthread_check(pthread_join(th, NULL), "pthread_join"); // FIXME pthread_tryjoin_np en dan cancel delete p; write_knuth_file(knuth_file, <); unlink(pid_file); dolog(LOG_INFO, "Finished"); return 0; } entropybroker-2.9/proxy_knuth_m.cpp000066400000000000000000000404301305163522000177010ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "math.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #include "kernel_prng_io.h" #define KNUTH_SIZE 8192 #define A_B_SIZE 8192 #define KNUTH_FILE "lookup.knuthm" const char *pid_file = PID_DIR "/proxy_knuth_m.pid"; const char *client_type = "proxy_knuth_m v" VERSION; volatile bool sig_quit = false; typedef struct { int fd; std::string host, type; long long unsigned int challenge; long long unsigned int ivec_counter; encrypt_stream *sc; hasher *mac; random_source *rs; } proxy_client_t; typedef struct { unsigned short *table; int t_size, t_offset; unsigned short *A; int n_A; unsigned short *B; int n_B; pthread_mutex_t lock; } lookup_t; int read_value(FILE *fh) { unsigned char buffer[4]; if (fread(buffer, 1, 4, fh) != 4) error_exit("short read on file, please delete cache file and retry"); return (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0]; } void write_value(FILE *fh, int value) { unsigned char buffer[4]; buffer[3] = (value >> 24) & 255; buffer[2] = (value >> 16) & 255; buffer[1] = (value >> 8) & 255; buffer[0] = (value ) & 255; if (fwrite(buffer, 1, 4, fh) != 4) error_exit("short write on file, please delete cache file"); } void load_knuth_file(std::string file, lookup_t *lt) { FILE *fh = fopen(file.c_str(), "rb"); if (!fh) { if (errno != ENOENT) error_exit("Error accessing file %s", file.c_str()); dolog(LOG_INFO, "No cache file '%s' exists, starting with fresh buffers", file.c_str()); lt -> t_size = KNUTH_SIZE; lt -> table = (unsigned short *)malloc(lt -> t_size * sizeof(unsigned short)); lt -> A = (unsigned short *)malloc(A_B_SIZE * sizeof(unsigned short)); lt -> B = (unsigned short *)malloc(A_B_SIZE * sizeof(unsigned short)); } else { dolog(LOG_INFO, "Reading cached data from %s", file.c_str()); lt -> t_size = read_value(fh); if (lt -> t_size > 67108864) error_exit("%s is probably corrupt (size > 128MB)", file.c_str()); lt -> t_offset = read_value(fh); lt -> table = (unsigned short *)malloc(lt -> t_size * sizeof(unsigned short)); size_t bytes = lt -> t_size * sizeof(unsigned short); if (fread(lt -> table, 1, bytes, fh) != bytes) error_exit("Short read in file, please delete %s and retry", file.c_str()); int dummy = read_value(fh); if (dummy != A_B_SIZE) error_exit("Unexpected A/B size %d (expecting %d), please delete %s and retry", dummy, A_B_SIZE, file.c_str()); bytes = A_B_SIZE * sizeof(unsigned short); lt -> A = (unsigned short *)malloc(A_B_SIZE * sizeof(unsigned short)); if (fread(lt -> A, 1, bytes, fh) != bytes) error_exit("Short read in file, please delete %s and retry", file.c_str()); lt -> B = (unsigned short *)malloc(A_B_SIZE * sizeof(unsigned short)); if (fread(lt -> B, 1, bytes, fh) != bytes) error_exit("Short read in file, please delete %s and retry", file.c_str()); fclose(fh); } } void write_knuth_file(std::string file, lookup_t *lt) { dolog(LOG_INFO, "Writing cached data to %s", file.c_str()); FILE *fh = fopen(file.c_str(), "wb"); if (!fh) error_exit("Failed to create file %s", file.c_str()); write_value(fh, lt -> t_size); write_value(fh, lt -> t_offset); size_t bytes = lt -> t_size * sizeof(unsigned short); if (fwrite(lt -> table, 1, bytes, fh) != bytes) error_exit("Error writing to file %s", file.c_str()); write_value(fh, A_B_SIZE); bytes = A_B_SIZE * sizeof(unsigned short); if (fwrite(lt -> A, 1, bytes, fh) != bytes) error_exit("Error writing to file %s", file.c_str()); if (fwrite(lt -> B, 1, bytes, fh) != bytes) error_exit("Error writing to file %s", file.c_str()); fclose(fh); } int put_data(proxy_client_t *client, lookup_t *lt, bool is_A) { unsigned char bit_cnt[4] = { 0 }; // receive number of bits if (READ_TO(client -> fd, bit_cnt, 4, DEFAULT_COMM_TO) != 4) return -1; unsigned int cur_n_bits = uchar_to_uint(bit_cnt); if (cur_n_bits > 9992) return -1; unsigned char reply[4 + 4] = { 0 }; make_msg(reply, 1, cur_n_bits); // make_msg(reply, full ? 9003 : 1, cur_n_bits); if (WRITE_TO(client -> fd, reply, 8, DEFAULT_COMM_TO) != 8) return -1; unsigned int cur_n_bytes = (cur_n_bits + 7) / 8; int hash_len = client -> mac -> get_hash_size(); unsigned int in_len = cur_n_bytes + hash_len; unsigned char *buffer_in = reinterpret_cast(malloc(in_len)); if (!buffer_in) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), in_len); if (READ_TO(client -> fd, buffer_in, in_len, DEFAULT_COMM_TO) != int(in_len)) { dolog(LOG_INFO, "put|%s short read while retrieving entropy data", client -> host.c_str()); free(buffer_in); return -1; } unsigned char *buffer_out = reinterpret_cast(malloc(in_len)); if (!buffer_out) error_exit("%s error allocating %d bytes of memory", client -> host.c_str(), cur_n_bytes); // FIXME lock_mem(buffer_out, cur_n_bytes); // decrypt data client -> sc -> decrypt(buffer_in, in_len, buffer_out); unsigned char *entropy_data = &buffer_out[hash_len]; int entropy_data_len = cur_n_bytes; unsigned char *hash = reinterpret_cast(malloc(hash_len)); client -> mac -> do_hash(entropy_data, entropy_data_len, hash); if (memcmp(hash, buffer_out, hash_len) != 0) { dolog(LOG_WARNING, "Hash mismatch in retrieved entropy data!"); free(buffer_out); free(buffer_in); return -1; } my_mutex_lock(< -> lock); bool use = false; if (is_A) { if (lt -> t_offset < lt -> t_size) { int n = lt -> t_size - lt -> t_offset; int do_n_bytes = std::min((unsigned int)(n * sizeof(unsigned short)), cur_n_bytes); memcpy(lt -> table, buffer_out, do_n_bytes); lt -> t_offset += do_n_bytes / sizeof(unsigned short); if (lt -> t_offset == lt -> t_size) dolog(LOG_INFO, "look-up table is filled"); else dolog(LOG_DEBUG, "Look-up table fill: %.2f%%", double(lt -> t_offset * 100) / double(lt -> t_size)); use = true; } else { int n = A_B_SIZE - lt -> n_A; int do_n_bytes = std::min((unsigned int)(n * sizeof(unsigned short)), cur_n_bytes); if (do_n_bytes > 0) { memcpy(< -> A[lt -> n_A], buffer_out, do_n_bytes); use = true; } lt -> n_A += do_n_bytes / sizeof(unsigned short); } } else { int n = A_B_SIZE - lt -> n_B; int do_n_bytes = std::min((unsigned int)(n * sizeof(unsigned short)), cur_n_bytes); if (do_n_bytes > 0) { memcpy(< -> B[lt -> n_B], buffer_out, do_n_bytes); use = true; } lt -> n_B += do_n_bytes / sizeof(unsigned short); } if (use) dolog(LOG_DEBUG, "storing %d bits from %s", cur_n_bits, client -> host.c_str()); my_mutex_unlock(< -> lock); // memset // unlock_mem free(buffer_out); free(buffer_in); return 0; } int handle_client(proxy_client_t *client, lookup_t *lt, bool is_A) { char cmd[4] = { 0 }; if (READ_TO(client -> fd, cmd, 4, DEFAULT_COMM_TO) != 4) { dolog(LOG_INFO, "Short read on fd %d / %s", client -> fd, client -> host.c_str()); return -1; } if (memcmp(cmd, "0002", 4) == 0) // put data { return put_data(client, lt, is_A); } else { dolog(LOG_WARNING, "Unknown / unexpected message %s received", cmd); return -1; } return 0; } typedef struct { protocol *p; lookup_t *lt; } thread_pars_t; void * thread(void *pars) { thread_pars_t *p = (thread_pars_t *)pars; for(;!sig_quit;) { my_mutex_lock(&p -> lt -> lock); // transmit to broker bool send = false; if (p -> lt -> n_A > 0 && p -> lt -> n_B > 0) { send = true; dolog(LOG_DEBUG, "buffered data: %d %d", p -> lt -> n_A, p -> lt -> n_B); } while (p -> lt -> n_A > 0 && p -> lt -> n_B > 0 && !sig_quit) { int n_short = 4096 / sizeof(unsigned short); int n = std::min(n_short, std::min(p -> lt -> n_A, p -> lt -> n_B)); int n_bytes = n * sizeof(unsigned short); unsigned short *out = (unsigned short *)malloc(n_bytes); dolog(LOG_DEBUG, "Processing %d shorts", n); for(int loop=0; loop lt -> A[p -> lt -> n_A - 1]; p -> lt -> n_A--; int B = p -> lt -> B[p -> lt -> n_B - 1]; p -> lt -> n_B--; int j = B % p -> lt -> t_size; int v = p -> lt -> table[j]; p -> lt -> table[j] = A; out[loop] = v; } my_mutex_unlock(&p -> lt -> lock); (void)p -> p -> message_transmit_entropy_data(reinterpret_cast(out), n_bytes); free(out); my_mutex_lock(&p -> lt -> lock); } if (send) dolog(LOG_DEBUG, "Finished transmitting"); my_mutex_unlock(&p -> lt -> lock); usleep(250000); // FIXME condwait or so } return NULL; } void sig_handler(int sig) { dolog(LOG_INFO, "Got signal %d", sig); if (sig == SIGTERM || sig == SIGINT || sig == SIGQUIT) sig_quit = true; else { fprintf(stderr, "Exit due to signal %d\n", sig); unlink(pid_file); exit(0); } } void help() { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-j adapter adapter to listen on\n"); printf("-p port port to listen on (default: %d)\n", DEFAULT_PROXY_LISTEN_PORT); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-V file store buffers to this file (default: %s/%s)\n", CACHE_DIR, KNUTH_FILE); printf("-P file write pid to file\n"); printf("-X file read username+password from file (to authenticate to broker)\n"); printf("-U file read u/p for clients from file (to authenticate local clients)\n"); } int main(int argc, char *argv[]) { const char *listen_adapter = "0.0.0.0"; int listen_port = DEFAULT_PROXY_LISTEN_PORT; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; std::string username, password; std::string clients_auths; std::string knuth_file = CACHE_DIR + std::string("/") + KNUTH_FILE; std::vector hosts; int log_level = LOG_INFO; random_source_t rst = RS_CRYPTOPP; std::string cipher = "blowfish", handshake_hash = "sha512", mac_hasher = "md5"; printf("proxy_knuth_m, (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "V:j:p:U:hf:X:P:I:L:l:sn")) != -1) { switch(c) { case 'V': knuth_file = optarg; break; case 'j': listen_adapter = optarg; break; case 'p': listen_port = atoi(optarg); break; case 'U': clients_auths = optarg; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: fprintf(stderr, "-%c not known\n", c); help(); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("password + username cannot be empty"); if (clients_auths.length() == 0) error_exit("No file with usernames + passwords selected for client authentication"); if (hosts.empty()) error_exit("No host to connect to selected"); (void)umask(0177); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); // bit rate is dummy: only servers connect to the proxy users *user_map = new users(clients_auths, 4096); protocol *p = new protocol(&hosts, username, password, true, client_type, DEFAULT_COMM_TO); no_core(); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); proxy_client_t *clients[2] = { new proxy_client_t, new proxy_client_t }; int listen_socket_fd = start_listen(listen_adapter, listen_port, 5); clients[0] -> fd = -1; clients[1] -> fd = -1; lookup_t lt; memset(<, 0x00, sizeof lt); load_knuth_file(knuth_file, <); pthread_check(pthread_mutex_init(<.lock, NULL), "pthread_mutex_init"); thread_pars_t tp = { p, < }; pthread_t th; pthread_check(pthread_create(&th, NULL, thread, &tp), "pthread_create"); statistics_global sg; for(;!sig_quit;) { fd_set rfds; FD_ZERO(&rfds); int max_fd = -1; FD_SET(listen_socket_fd, &rfds); max_fd = std::max(max_fd, listen_socket_fd); for(int client_index=0; client_index<2; client_index++) { if (clients[client_index] -> fd != -1) { FD_SET(clients[client_index] -> fd, &rfds); max_fd = std::max(max_fd, clients[client_index] -> fd); } } sigset_t sig_set; if (sigemptyset(&sig_set) == -1) error_exit("sigemptyset"); if (pselect(max_fd + 1, &rfds, NULL, NULL, NULL, &sig_set) == -1) { if (errno != EINTR) error_exit("select failed"); continue; } for(int client_index=0; client_index<2; client_index++) { if (clients[client_index] -> fd != -1 && FD_ISSET(clients[client_index] -> fd, &rfds)) { if (handle_client(clients[client_index], <, client_index == 0) == -1) { close(clients[client_index] -> fd); clients[client_index] -> fd = -1; delete clients[client_index] -> sc; delete clients[client_index] -> mac; delete clients[client_index] -> rs; } } } if (!sig_quit && FD_ISSET(listen_socket_fd, &rfds)) { int new_socket_fd = accept(listen_socket_fd, NULL, NULL); if (new_socket_fd != -1) { std::string host = get_endpoint_name(new_socket_fd); dolog(LOG_INFO, "new client: %s (fd: %d)", host.c_str(), new_socket_fd); encrypt_stream *enc = encrypt_stream::select_cipher(cipher); hasher *mac = hasher::select_hasher(mac_hasher); random_source *rs = new random_source(rst); std::string client_username, client_password; long long unsigned int challenge = 1; bool is_server = false; std::string type; if (auth_eb(new_socket_fd, DEFAULT_COMM_TO, user_map, client_username, client_password, &challenge, &is_server, type, rs, enc, mac, handshake_hash, 4096, &sg) == 0) { dolog(LOG_INFO, "%s/%s %d/%d (%s)", host.c_str(), type.c_str(), new_socket_fd, is_server, client_username.c_str()); if (clients[0] -> fd != -1 && clients[1] -> fd != -1) { dolog(LOG_WARNING, "New connection with 2 clients connected: dropping all previous connections"); close(clients[0] -> fd); close(clients[1] -> fd); clients[0] -> fd = -1; clients[1] -> fd = -1; delete clients[0] -> sc; delete clients[1] -> sc; delete clients[0] -> mac; delete clients[1] -> mac; delete clients[0] -> rs; delete clients[1] -> rs; } proxy_client_t *pcp = NULL; if (clients[0] -> fd == -1) pcp = clients[0]; else if (clients[1] -> fd == -1) pcp = clients[1]; pcp -> fd = new_socket_fd; pcp -> challenge = challenge; pcp -> ivec_counter = 0; unsigned char ivec[8] = { 0 }; calc_ivec(client_password.c_str(), pcp -> challenge, pcp -> ivec_counter, enc -> get_ivec_size(), ivec); pcp -> sc = enc; unsigned char *pw_char = reinterpret_cast(const_cast(client_password.c_str())); pcp -> sc -> init(pw_char, client_password.length(), ivec); pcp -> mac = mac; pcp -> rs = rs; } else { close(new_socket_fd); delete enc; delete mac; delete rs; } } } } dolog(LOG_INFO, "Terminating..."); pthread_check(pthread_join(th, NULL), "pthread_join"); delete p; write_knuth_file(knuth_file, <); unlink(pid_file); dolog(LOG_INFO, "Finished"); return 0; } entropybroker-2.9/random_source.cpp000066400000000000000000000040761305163522000176410ustar00rootroot00000000000000#include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "kernel_prng_io.h" #include "kernel_prng_rw.h" #include "random_source.h" random_source::random_source(const random_source_t rs_in) : rs(rs_in), notified_errors(false) { rng = new CryptoPP::AutoSeededRandomPool(); } random_source::random_source(const random_source_t rs_in, const std::string & state_file_in) : rs(rs_in), state_file(state_file_in), notified_errors(false) { retrieve_state(state_file_in); rng = new CryptoPP::AutoSeededRandomPool(); } random_source::~random_source() { if (state_file.length() > 0) dump_state(state_file); delete rng; } void random_source::get(unsigned char *const p, const size_t n) { if (rs == RS_CRYPTOPP) { // this construction is implemented this as crypto++ 5.6.1 does not handle // EAGAIN errors correctly when reading from /dev/urandom int attempt = 0; for(;;) { try { rng -> GenerateBlock(p, n); break; } catch(CryptoPP::OS_RNG_Err ore) { if (!notified_errors) { notified_errors = true; dolog(LOG_WARNING, "crypto++ threw an error in the OS RNG: %s", ore.what()); } if (++attempt > 16) error_exit("crypto++ CryptoPP::AutoSeededRandomPool() failed %d times, aborting", attempt); delete rng; rng = new CryptoPP::AutoSeededRandomPool(); } } } else if (rs == RS_DEV_URANDOM) { if (kernel_rng_read_non_blocking(p, n) == -1) error_exit("kernel_rng_read_non_blocking failed"); } else if (rs == RS_DEV_RANDOM) { if (kernel_rng_read_blocking(p, n) == -1) error_exit("kernel_rng_read_non_blocking failed"); } else { error_exit("Unknown random source %s", rs); } } bool random_source::check_empty() const { // FIXME /dev/[u]random, check if kernel_rng_get_entropy_count() < write_threshold return false; } void random_source::seed(const unsigned char *const in, const size_t n, const double byte_count) { } void random_source::dump_state(const std::string & file) { } void random_source::retrieve_state(const std::string & file) { } entropybroker-2.9/random_source.h000066400000000000000000000012221305163522000172740ustar00rootroot00000000000000#include typedef enum { RS_CRYPTOPP, RS_DEV_URANDOM, RS_DEV_RANDOM } random_source_t; class random_source { private: const random_source_t rs; CryptoPP::AutoSeededRandomPool *rng; std::string state_file; bool notified_errors; void dump_state(const std::string & file); void retrieve_state(const std::string & file); public: random_source(const random_source_t rst); random_source(const random_source_t rst, const std::string & dump_file_in); ~random_source(); void get(unsigned char *const p, const size_t n); bool check_empty() const; void seed(const unsigned char *const in, const size_t n, const double byte_count); }; entropybroker-2.9/readme.txt000066400000000000000000000324571305163522000162770ustar00rootroot00000000000000*** PLEASE NOTE: since 1.0, 'eb' was renamed to 'entropy_broker' *** *** also the other daemons were renamed *** *** ALSO: the network protocol has changed so it is no longer *** *** compatible with older versions (1.1 is also incompatible *** *** with 1.0) *** *** ANOTHER NOTE: disk-pools of version 1.0 are NOT compatible *** *** with the ones of 1.1! *** *** LAST NOTE: the configuration file changed, see example *** How it works ------------ The 'entropy_broker' process is the central process of it all. It collects all entropy data, mixes it within its pool(s), measures the amount of randomness in that data en then serves it to clients. server_* processes, which can run in other systems than the entropy_broker-process, collect the random-data and transmit that to the central entropy_broker-process. client_* processes, which also can run everywhere, get random-data from the central entropy_broker-process and feed that to for example the local linux-kernel (/dev/random so to say) or to processes that read from a egb-compatible unix-domain socket. Most daemons should run on all UNIX systems. The ones that are Linux-specific are markes as such. See "design.txt" for details on the crypto used. See "interfacing.txt" for details on how to connect your own applications to entropy broker. Building -------- ./configure make everything install Files will be installed in /usr/local/entropybroker You need the Crypto++ and zlib development libraries. libasound2-dev is for eb_server_audio libusb-1.0-0-dev is for eb_server_usb libftdi-dev is for eb_server_ComScire_R2000KU libpcsclite-dev is for eb_server_smartcard libpng12-dev is for plot libgd2-noxpm-dev or libgd2-xpm-dev The configure script will determine which libraries are available and then select which daemons to build. Usage ----- Since version 1.0 all entropy-data is encrypted before it is transmitted over the network. Also, clients and servers need to authenticate before they can talk to the entropybroker. Then 'my-password.txt' should contain the username and password (on seperate lines) you want to use. Also the file should only be readable by the user under which the entropy-broker and/or servers/clients run. E.g. use chmod 600 my-password.txt eb_server_v4l -X my-password.txt Passwords should not be longer than 56 characters. On the server, there should be a password-file too. This file should contain one users per line, with the password seperated with a '|', e.g.: user|password some user|my password If you change the password and want to reload the user-file without restarting the complete broker, sent SIGHUP to it. Of course the size of the password depends on the cipher you configure for the password. E.g. 3DES requires 24 characters. You can also add a 3d and 4th parameter: maximum bps and allow write access. E.g.: user|password|1024|yes This allows the user 'user' to get a maximum of 1024 bits per second and also allow him to put new data into the server. All clients and servers need a '-I' commandline parameter. This parameter can be used 1 or more times. It selects one (or more) entrop broker instance(s). If one is not reachable, the other(s) are tried. Examples: -I ::ffff:192.168.0.1 -I [::ffff:192.168.0.1]:12341 with portnumber -I hostname.bla.com -I hostname.bla.com:55225 -I [2001:888:13b3:172:a80a:1111:fe0e:daaa] ipv6 -I [2001:888:13b3:172:a80a:1111:fe0e:daaa]:1400 with port server processes ================ On the server, invoke 'entropy_broker' (/usr/local/entropybroker/bin/entropy_broker). Send a HUP signal to the entropy_broker-daemon to let it log the current state. E.g. recv/sent requests, etc. The main entropy broker process listens by default on port 55225 (TCP). On systems with a spare sound-card, start server_audio. This requires a functioning ALSA audio sub-system. Look in /proc/asound/devices for the parameters. For example: mauer:/usr/local/entropybroker/var/log# cat /proc/asound/devices 1: : sequencer 2: [ 0- 1]: digital audio playback 3: [ 0- 0]: digital audio playback 4: [ 0- 0]: digital audio capture 5: [ 0- 2]: hardware dependent 6: [ 0] : control 7: [ 1- 3]: digital audio playback 8: [ 1- 0]: hardware dependent 9: [ 1] : control 10: [ 2- 0]: digital audio capture 11: [ 2] : control 33: : timer In this example there are 3 audio cards (0, 1 and 2, see first column between [ and ]). If we want to take the audio from card 2 (see line 10) it would look like this: eb_server_audio -d hw:2,0 -s -I broker -X This program is Linux-only (due to the ALSA requirement). This program should work with the Johnson Noise 1* produced by the electronic parts of the sound-card. So it is best, maybe not obvious, to turn the volume as low as possible. 1* http://en.wikipedia.org/wiki/Johnson%E2%80%93Nyquist_noise On systems with a spare tv-card/webcam, start server_v4l. E.g.: eb_server_v4l -I broker -d /dev/video0 -s -X password.txt This program is Linux-only (due to the video4linux2 requirement). The same note regarding Johnson Noise (see the audio driver) applies to this program. On the other hand: LavaRnd (http://www.lavarnd.org/) works by the principle that what the camera "sees" is moving in a random way. So either put e.g. a lava-lamp or fishtank in front of the camera, or tune the tuner of the tv-card to a channel with only noise or put a cap in front of the lense. On systems that are mostly idle, start server_timers. Check http://vanheusden.com/te/#bps to see some expected bitrates. eb_server_timers -I broker -s -X password.txt This program compares timers. Due to jitter in their frequency, noise can be measured. On systems with an random generator connected to e.g. a serial port, or with a rng in the motherboard chipset, use server_stream to feed its data to entropy_broker. For example a rng in the system would be used like this: eb_server_stream -I entropy_broker -d /dev/hwrng -s -X password.txt For example an Orion RNG can be processed at 19200 bps via /dev/ttyS* An IDQ Quantis has a device node /dev/qrandom0 available (http://www.idquantique.com/true-random-number-generator/products-overview.html). On systems with an EntropyKey (http://www.entropykey.co.uk/) or EGD, start server_egd. server_egd requires a read-interval and how many bytes to read in that interval. E.g.: eb_server_egd -I broker -d /tmp/egd.socket.ekey -a 1024 -b 5 -X password.txt This would require the following: EGDUnixSocket "/tmp/egd.socket.ekey in the entropy-key daemons configuration (which is /etc/entropykey/ekeyd.conf on Debian systems). This program can also connect to EGD servers which listen on a TCP port. On systems with a RNG in the chipset that automatically gets send to the linux kernel entropy buffer, use server_linux_kernel. This program is Linux-only. On systems with one or more USB devices attached (can be simple as a keyboard or a mouse) you can use server_usb. This needs to run with root access. This program measures the response time of a device. This program can be compared to server_timers as it measures the difference between the clock of the pc and the clock in the usb device. On systems without any hardware available for retrieving data, one can, as a last resort, using eb_server_ext_proc. This command can execute any command (as long as it is supported by the shell) and feed its output to the broker. E.g.: eb_server_ext_proc -I localhost -c '(find /proc -type f -print0 | xargs -0 cat ; ps auwx ; sensors -u) | gzip -9' -n -X password.txt On x86 compatible systems (e.g. not a Sparc), one can use server_cycle_count. This program is a simplified copy of http://www.issihosts.com/haveged/ with the following differences: - lower bit count - lower entropy count This version was implemented to have something that speaks either entropy_broker or EGD protocol. This program might work on virtual machines too. The server daemons that obtain data from hardware sources use von neumann software whitening. See: http://en.wikipedia.org/wiki/Hardware_random_number_generator#Software_whitening If you have a large amount of entropy data available in a file on disk, you can use eb_server_push_file. Please note that you can use the data only once. Use eb_server_ComScire_R2000KU when you have a ComSire R2000KU device connected via USB. If you have a ISO 7816 smartcard connected via a PCSC compatible reader, you can use eb_server_smartcard to use that smartcard to generate entropy data. This is obtained by sending the 0x84 INS which means "GET CHALLENGE". Note that not all cards support this command. Two Dutch EMV cards I tried refuse this command with a 0x6e (class not supported) error. Other cards return 0x6d (instruction code not supported or invalid). Proxies ======= eb_proxy_knuth_m: this proxy mixes to streams (of preferably the same bit-rate) and feeds it to the broker. For this, algorithm M (chapter 3.2.2 The Art of Computer Programming (Donald E. Knuth) Volume 2, Seminumerical Algorithms (3d edition)) is used (also described in Applied Cryptography by Bruce Schneier, second edition, chapter 16.11). client processes ================ To keep the entropy buffer of the local linux kernel filled-up, start client_linux_kernel as a root user. If you want the kernel buffers to be filled much earlier (the default is when it only has 128 bits left), then write a new value to: /proc/sys/kernel/random/write_wakeup_threshold E.g.: echo 512 > /proc/sys/kernel/random/write_wakeup_threshold This program is Linux-only. eb_client_kernel_generic is for other systems like for example freebsd and macos x. For it to work, the /dev/random device needs to accept data written to it. This should be the case for *bsd. The program accepts a parameter indicating the number of bytes to write and the number of seconds to sleep between each write. To server entropy data like as if it was an EGD-server, start client_egd. E.g.: eb_client_egd -d /tmp/egd.sock -I entropy_broker-server.test.com You may need to delete the socket before starting eb_client_egd. Now egd-clients can use the /tmp/egd.sock unix domain socket. This should work with at least OpenSSL: start client_egd with one of the following parameters: -d /var/run/egd-pool or -d /dev/egd-pool or -d /etc/egd-pool or -d /etc/entropy To verify that client_egd functions, run: openssl rand -rand /var/run/egd-pool -out /tmp/bla 10 It should return something like 255 semi-random bytes loaded where '255' should be > 0. If it is zero, check if the current user has enough rights to access /var/run/egd-pool This program can also service via a TCP socket. Problem resolving ================= If one of the server processes quits after a while (or even immediately), then check its logging to see what the problem is. All processes have the following command-line switches for that: -s log to syslog -l file log to a file -n do not fork: messages will appear in your terminal Note: logfiles need an absolute path. Also note: if not a full path is given for the password-file (for client and server processes), then the program looks in the directory from the current configuration file. Please invoke these commands first with -h to see a list of options. You probably need to use '-I' to select the server(s) on which 'entropy_broker' runs. Also adding '-s' is usefull as it'll make the servers/clients/entropy_broker log to syslog. If a warning appears about mlock() failing you have to options: - ignore it - but if the system starts swapping, entropy data may end up in swap. on the other hand: pools are stored in plain on disk anyway... - increase the maximum amount of memory a process can lock in bash this can be done with "ulimit -l n_kb" where n_kb is the number of KB a process is allowed to lock Tips ---- When your system has enough entropy, you can decide to let all OpenSSL applications use the kernel entropy driver. For that, in /etc/ssl/openssl.cnf change the line with RANDFILE in it to: RANDFILE = /dev/urandom Evaluating Entropy Broker ------------------------- Use eb_client_file to write a couple of bytes to a file. Then with dieharder: http://www.phy.duke.edu/~rgb/General/dieharder.php and also with ent: http://www.fourmilab.ch/random/ you can do some analysis of the randomness of the data. You can also convert that binary file to a text-file containing values so that you can analyze it using e.g. confft. Convert it using: ./bin_to_values.pl my_bin_file.dat > my_text_file.txt confft can be retrieved from: http://www.vanheusden.com/confft/ You can also directly plot the fft using the do_fft.sh script: ./do_fft.sh test.dat test.png This requires gnuplot and confft. An other option is to do a pixel-plot of some data (the more the better). Here, for each pixel 2 bytes are taken and then used as an x and y coordinate. That pixel is then increased by one. If the result looks like noise, then all is fine. Patterns are an indication that something is wrong. To build that binary, invoke: make plot This requires libpng-dev. To invoke: plot input_data.dat result.png Thanks ------ Håvard Moen: - added config variable to set max number of open files - rewritten select/pselect to use poll/ppoll. This is to get around the hardcoded Linux kernel limit of 1024 file descriptors for the select system call. The code has been running nicely with hundreds of clients for a month now - added rpm spec file - added new qwqng server which uses libqwqng, this is for the ComScire QNG PQ4000KU License ------- AGPL-3 Contact info ------------ mail@vanheusden.com entropybroker-2.9/redhat/000077500000000000000000000000001305163522000155355ustar00rootroot00000000000000entropybroker-2.9/redhat/eb_client_egd000077500000000000000000000030171305163522000202270ustar00rootroot00000000000000#!/bin/sh # # eb_client_egd # SVN: $Revision$ # # chkconfig: 2345 28 83 # description: eb_client_egd # # processname: eb_client_egd # pidfile: /usr/local/entropybroker/var/run/client_egd.pid ### BEGIN INIT INFO # Provides: eb_client_egd # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop linux kernel entropy client # Description: eb_client_egd is a daemon for installing brokered entropy into the kernel. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_client_egd" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) killproc $prog -HUP exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_client_file000077500000000000000000000031531305163522000204100ustar00rootroot00000000000000#!/bin/sh # # eb_client_file - Entropy broker linux kernel client # SVN: $Revision$ # # chkconfig: 2345 28 83 # description: This daemon installs brokered entropy into the linux kernel # # processname: eb_client_file # pidfile: /usr/local/entropybroker/var/run/eb_client_file.pid ### BEGIN INIT INFO # Provides: eb_client_file # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop linux kernel entropy client # Description: eb_client_file is a daemon for installing brokered entropy into the kernel. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_client_file" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) killproc $prog -HUP exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_client_linux_kernel000077500000000000000000000040621305163522000221700ustar00rootroot00000000000000#!/bin/sh # # eb_client_linux_kernel - Entropy broker linux kernel client # SVN: $Revision$ # # chkconfig: 2345 28 83 # description: This daemon installs brokered entropy into the linux kernel # # processname: eb_client_linux_kernel # pidfile: /usr/local/entropybroker/var/run/client_linux_kernel.pid ### BEGIN INIT INFO # Provides: eb_client_linux_kernel # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop linux kernel entropy client # Description: eb_client_linux_kernel is a daemon for installing brokered entropy into the kernel. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_client_linux_kernel" prog=$(basename $exec) KERNEL_WAKE_THRESHOLD=512 [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " echo "$KERNEL_WAKE_THRESHOLD" >/proc/sys/kernel/random/write_wakeup_threshold $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_ComScire_R2000KU000077500000000000000000000037211305163522000222510ustar00rootroot00000000000000#!/bin/sh # # eb_server_ComScire_R2000KU - Entropy broker egd source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_ComScire_R2000KU # pidfile: /usr/local/entropybroker/var/run/server_ComScire_R2000KU.pid ### BEGIN INIT INFO # Provides: eb_server_ComScire_R2000KU # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop egd entropy server # Description: eb_server_ComScire_R2000KU is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_ComScire_R2000KU" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_audio000077500000000000000000000036171305163522000206270ustar00rootroot00000000000000#!/bin/sh # # eb_server_audio - Entropy broker egd source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_audio # pidfile: /usr/local/entropybroker/var/run/server_audio.pid ### BEGIN INIT INFO # Provides: eb_server_audio # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop egd entropy server # Description: eb_server_audio is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_audio" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_cycle_count000077500000000000000000000037031305163522000220310ustar00rootroot00000000000000#!/bin/sh # # eb_server_cycle_count - Entropy broker cycle_count source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_cycle_count # pidfile: /usr/local/entropybroker/var/run/server_cycle_count.pid ### BEGIN INIT INFO # Provides: eb_server_cycle_count # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop cycle_count entropy server # Description: eb_server_cycle_count is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_cycle_count" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_egd000077500000000000000000000036031305163522000202600ustar00rootroot00000000000000#!/bin/sh # # eb_server_egd - Entropy broker egd source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_egd # pidfile: /usr/local/entropybroker/var/run/server_egd.pid ### BEGIN INIT INFO # Provides: eb_server_egd # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop egd entropy server # Description: eb_server_egd is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_egd" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_ext_proc000077500000000000000000000036531305163522000213510ustar00rootroot00000000000000#!/bin/sh # # eb_server_ext_proc - Entropy broker ext_proc source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_ext_proc # pidfile: /usr/local/entropybroker/var/run/server_ext_proc.pid ### BEGIN INIT INFO # Provides: eb_server_ext_proc # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop ext_proc entropy server # Description: eb_server_ext_proc is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_ext_proc" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_linux_kernel000077500000000000000000000037131305163522000222220ustar00rootroot00000000000000#!/bin/sh # # eb_server_linux_kernel - Entropy broker linux_kernel source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_linux_kernel # pidfile: /usr/local/entropybroker/var/run/server_linux_kernel.pid ### BEGIN INIT INFO # Provides: eb_server_linux_kernel # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop linux_kernel entropy server # Description: eb_server_linux_kernel is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_linux_kernel" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_push_file000077500000000000000000000036631305163522000215050ustar00rootroot00000000000000#!/bin/sh # # eb_server_push_file - Entropy broker push_file source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_push_file # pidfile: /usr/local/entropybroker/var/run/server_push_file.pid ### BEGIN INIT INFO # Provides: eb_server_push_file # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop push_file entropy server # Description: eb_server_push_file is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_push_file" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_smartcard000077500000000000000000000036631305163522000215070ustar00rootroot00000000000000#!/bin/sh # # eb_server_smartcard - Entropy broker smartcard source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_smartcard # pidfile: /usr/local/entropybroker/var/run/server_smartcard.pid ### BEGIN INIT INFO # Provides: eb_server_smartcard # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop smartcard entropy server # Description: eb_server_smartcard is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_smartcard" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_stream000077500000000000000000000036331305163522000210170ustar00rootroot00000000000000#!/bin/sh # # eb_server_stream - Entropy broker stream source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_stream # pidfile: /usr/local/entropybroker/var/run/server_stream.pid ### BEGIN INIT INFO # Provides: eb_server_stream # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop stream entropy server # Description: eb_server_stream is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_stream" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_timers000077500000000000000000000036331305163522000210270ustar00rootroot00000000000000#!/bin/sh # # eb_server_timers - Entropy broker timers source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_timers # pidfile: /usr/local/entropybroker/var/run/server_timers.pid ### BEGIN INIT INFO # Provides: eb_server_timers # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop timers entropy server # Description: eb_server_timers is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_timers" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_usb000077500000000000000000000036031305163522000203120ustar00rootroot00000000000000#!/bin/sh # # eb_server_usb - Entropy broker usb source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_usb # pidfile: /usr/local/entropybroker/var/run/server_usb.pid ### BEGIN INIT INFO # Provides: eb_server_usb # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop usb entropy server # Description: eb_server_usb is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_usb" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/eb_server_v4l000077500000000000000000000036031305163522000202260ustar00rootroot00000000000000#!/bin/sh # # eb_server_v4l - Entropy broker v4l source # SVN: $Revision$ # # chkconfig: 2345 27 84 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: eb_server_v4l # pidfile: /usr/local/entropybroker/var/run/server_v4l.pid ### BEGIN INIT INFO # Provides: eb_server_v4l # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop v4l entropy server # Description: eb_server_v4l is a daemon for collecting entropy from EGD. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/eb_server_v4l" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/redhat/entropy_broker000077500000000000000000000036031305163522000205310ustar00rootroot00000000000000#!/bin/sh # # entropy_broker - Entropy distribution service # SVN: $Revision$ # # chkconfig: 2345 26 85 # description: This daemon manages entropy sources and distributes entropy # to clients. # # processname: entropy_broker # pidfile: /usr/local/entropybroker/var/run/entropy_broker.pid ### BEGIN INIT INFO # Provides: entropy_broker # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop entropy broker # Description: entropy_broker is a daemon for distributing entropy. ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/usr/local/entropybroker/bin/entropy_broker" prog=$(basename $exec) [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog start() { echo -n $"Starting $prog: " $exec $OPTIONS retval=$? [ $retval -ne 0 ] && failure [ $retval -eq 0 ] && success && touch $lockfile echo return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } case "$1" in start|stop|restart) $1 ;; force-reload) restart ;; status) status $prog ;; try-restart|condrestart) if status $prog >/dev/null ; then restart fi ;; reload) # If config can be reloaded without restarting, implement it here, # remove the "exit", and add "reload" to the usage message below. # For example: # status $prog >/dev/null || exit 7 killproc $prog -HUP #action $"Service ${0##*/} does not support the reload action: " /bin/false exit 3 ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" exit 2 esac entropybroker-2.9/scc.cpp000066400000000000000000000033621305163522000155460ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "math.h" #include "log.h" #include "scc.h" scc::scc() { index = bytes_in = 0; memset(buffer, 0x00, sizeof buffer); threshold = 0.2; user = NULL; } scc::~scc() { free(user); } void scc::set_user(const char *puser) { free(user); user = strdup(puser); if (!user) error_exit("memory allocation error"); dolog(LOG_DEBUG, "registered scc-user %s", user); } void scc::set_threshold(double t) { threshold = t; } void scc::add(unsigned char byte) { buffer[index++] = byte; if (bytes_in < SCC_BUFFER_SIZE) bytes_in++; if (index >= SCC_BUFFER_SIZE) index = 0; } // 0: ok, -1: not ok double scc::get_cur_scc() { double scc_val; double prev_val = 0.0, u0 = 0.0; double t[3]; int loop; if (bytes_in < 2) return 0; // ok t[0] = t[1] = t[2] = 0.0; for(loop=0; loop #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USB_VENDOR_ARANEUS 0x12d8 #define USB_ARANEUS_PRODUCT_ALEA 0x0001 #define TIMEOUT 5000 #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" const char *pid_file = PID_DIR "/server_Araneus_Alea.pid"; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to (mututal exclusive with -i)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; int verbose = 0; char server_type[128]; bool show_bps = false; libusb_context *ctx = NULL; libusb_device_handle *handle = NULL; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "eb_server_Araneus_Alea v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "I:hSX:P:o:L:l:snv")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'v': verbose++; break; case 'o': bytes_file = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if(libusb_init(&ctx) < 0) error_exit("Error initialising Araneus Alea"); libusb_set_debug(ctx, 3); handle = libusb_open_device_with_vid_pid(ctx,USB_VENDOR_ARANEUS,USB_ARANEUS_PRODUCT_ALEA); if (!handle) error_exit("No Alea device found"); if(libusb_claim_interface(handle, 0) < 0){ error_exit("Cannot Claim Interface"); } snprintf(server_type, sizeof server_type, "eb_server_Araneus_Alea v" VERSION); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { if (libusb_bulk_transfer(handle, (1 | LIBUSB_ENDPOINT_IN), (unsigned char *)bytes, sizeof bytes, &c, TIMEOUT) < 0) error_exit("Failed to retrieve random bytes from device %x", c); //////// if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, sizeof bytes); if (!hosts.empty() && p -> message_transmit_entropy_data(bytes, sizeof bytes, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); } delete p; memset(bytes, 0x00, sizeof bytes); unlink(pid_file); return 0; } entropybroker-2.9/server_ComScire_R2000KU.cpp000066400000000000000000000114061305163522000211110ustar00rootroot00000000000000#include "ComScire_R2000KU/qwqng.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" const char *pid_file = PID_DIR "/server_ComScire_R2000KU.pid"; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to (mututal exclusive with -i)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int read_fd = -1; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; int index = 0; int verbose = 0; char server_type[128]; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "eb_server_ComScire_R2000KU v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "I:hSX:P:o:L:l:snv")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'v': verbose++; break; case 'o': bytes_file = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); QWQNG *q = QWQNG::Instance(); if (!q) error_exit("Could not find a device? (1)"); if (!q -> DeviceID()) error_exit("Could not find a device? (2)"); lock_mem(q, sizeof *q); snprintf(server_type, sizeof server_type, "eb_server_ComScire_R2000KU v" VERSION " %s", q -> DeviceID()); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); bool stats_error_reported = false; for(;!do_exit;) { int rc = q -> RandBytes(reinterpret_cast(bytes), 4096); if (rc != QNG_S_OK && rc != S_OK) { if (rc == QNG_E_STATS_EXCEPTION) { if (!stats_error_reported) { dolog(LOG_WARNING, "Device reports a statistics test exception"); stats_error_reported = true; } usleep(10000); // do not hog cpu continue; } error_exit("Failed to retrieve random bytes from device %x", rc); } stats_error_reported = false; //////// if (index == sizeof bytes) { if (show_bps) update_showbps(4096); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (!hosts.empty() && p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); index = 0; } } delete p; memset(bytes, 0x00, sizeof bytes); unlink(pid_file); return 0; } entropybroker-2.9/server_audio.cpp000066400000000000000000000255271305163522000174740ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char *pid_file = PID_DIR "/eb_server_audio.pid"; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #define DEFAULT_SAMPLE_RATE 11025 #define DEFAULT_CLICK_READ (1 * DEFAULT_SAMPLE_RATE) bool do_exit = false; void sig_handler(int sig) { signal(sig, SIG_IGN); fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } int setparams(snd_pcm_t *chandle, int sample_rate, snd_pcm_format_t *format, const char *cdevice) { int err; snd_pcm_hw_params_t *ct_params; /* templates with rate, format and channels */ snd_pcm_hw_params_alloca(&ct_params); err = snd_pcm_hw_params_any(chandle, ct_params); if (err < 0) error_exit("Broken configuration for %s PCM: no configurations available: %s", cdevice, snd_strerror(err)); /* Disable rate resampling */ err = snd_pcm_hw_params_set_rate_resample(chandle, ct_params, 0); if (err < 0) error_exit("Could not disable rate resampling: %s", snd_strerror(err)); /* Set access to SND_PCM_ACCESS_RW_INTERLEAVED */ err = snd_pcm_hw_params_set_access(chandle, ct_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) error_exit("Could not set access to SND_PCM_ACCESS_RW_INTERLEAVED: %s", snd_strerror(err)); /* Restrict a configuration space to have rate nearest to our target rate */ err = snd_pcm_hw_params_set_rate_near(chandle, ct_params, (unsigned int *)&sample_rate, 0); if (err < 0) error_exit("Rate %iHz not available for %s: %s", sample_rate, cdevice, snd_strerror(err)); /* Set sample format */ *format = SND_PCM_FORMAT_S16_BE; err = snd_pcm_hw_params_set_format(chandle, ct_params, *format); if (err < 0) { *format = SND_PCM_FORMAT_S16_LE; err = snd_pcm_hw_params_set_format(chandle, ct_params, *format); } if (err < 0) error_exit("Sample format (SND_PCM_FORMAT_S16_BE and _LE) not available for %s: %s", cdevice, snd_strerror(err)); /* Set stereo */ err = snd_pcm_hw_params_set_channels(chandle, ct_params, 2); if (err < 0) error_exit("Channels count (%i) not available for %s: %s", 2, cdevice, snd_strerror(err)); /* Apply settings to sound device */ err = snd_pcm_hw_params(chandle, ct_params); if (err < 0) error_exit("Could not apply settings to sound device! %s", snd_strerror(err)); return 0; } #define order(a, b) (((a) == (b)) ? -1 : (((a) > (b)) ? 1 : 0)) void help(const char *cdevice) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-d dev audio-device, default %s\n", cdevice); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } void recover_sound_dev(snd_pcm_t **chandle, bool is_open, const char *cdevice, snd_pcm_format_t *format) { if (is_open) snd_pcm_close(*chandle); int err = -1; while ((err = snd_pcm_open(chandle, cdevice, SND_PCM_STREAM_CAPTURE, 0)) < 0 && !do_exit) { dolog(LOG_WARNING, "snd_pcm_open open error: %s (retrying)", snd_strerror(err)); sleep(1); } if (!do_exit) setparams(*chandle, DEFAULT_SAMPLE_RATE, format, cdevice); } void main_loop(std::vector * hosts, char *bytes_file, char show_bps, std::string username, std::string password, const char *cdevice) { int n_to_do, bits_out=0, loop; char *dummy; static short psl=0, psr=0; /* previous samples */ static char a=1; /* alternater */ unsigned char byte_out=0; int input_buffer_size; char *input_buffer; snd_pcm_t *chandle; snd_pcm_format_t format; int err; unsigned char bytes[4096]; // 4096 * 8: 9992, must be less then 9999 int bytes_out = 0; char server_type[128]; snprintf(server_type, sizeof server_type, "eb_server_audio v" VERSION " %s", cdevice); protocol *p = NULL; if (!hosts -> empty()) p = new protocol(hosts, username, password, true, server_type, DEFAULT_COMM_TO); lock_mem(bytes, sizeof bytes); recover_sound_dev(&chandle, false, cdevice, &format); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { char got_any = 0; input_buffer_size = snd_pcm_frames_to_bytes(chandle, DEFAULT_SAMPLE_RATE * 2); input_buffer = reinterpret_cast(malloc_locked(input_buffer_size)); if (!input_buffer) error_exit("problem allocating %d bytes of memory", input_buffer_size); /* Discard the first data read */ /* it often contains weird looking data - probably a click from */ /* driver loading / card initialisation */ snd_pcm_sframes_t garbage_frames_read = snd_pcm_readi(chandle, input_buffer, DEFAULT_SAMPLE_RATE); /* Make sure we aren't hitting a disconnect/suspend case */ if (garbage_frames_read < 0) { dolog(LOG_INFO, "snd_pcm_readi: failed retrieving audio", snd_strerror(garbage_frames_read)); // FIXME if ((err = snd_pcm_recover(chandle, garbage_frames_read, 0)) < 0) { dolog(LOG_INFO, "snd_pcm_recover fail : %s", snd_strerror(err)); dolog(LOG_INFO, "Failure retrieving sound from soundcard, re-opening device"); recover_sound_dev(&chandle, true, cdevice, &format); } } /* Read a buffer of audio */ n_to_do = DEFAULT_SAMPLE_RATE * 2; dummy = input_buffer; while (n_to_do > 0 && !do_exit) { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do); /* Make sure we aren't hitting a disconnect/suspend case */ if (frames_read < 0) frames_read = snd_pcm_recover(chandle, frames_read, 0); /* Nope, something else is wrong. Bail. */ if (frames_read == -1) { if ((err = snd_pcm_recover(chandle, frames_read, 0)) < 0) { dolog(LOG_INFO, "snd_pcm_recover fail : %s", snd_strerror(err)); dolog(LOG_INFO, "Failure retrieving sound from soundcard, re-opening device"); recover_sound_dev(&chandle, true, cdevice, &format); } } else { n_to_do -= frames_read; dummy += frames_read; } } /* de-biase the data */ for(loop=0; loop<(DEFAULT_SAMPLE_RATE * 2/*16bits*/ * 2/*stereo*/ * 2) && !do_exit; loop+=8) { int w1, w2, w3, w4, o1, o2; if (format == SND_PCM_FORMAT_S16_BE) { w1 = (input_buffer[loop+0]<<8) + input_buffer[loop+1]; w2 = (input_buffer[loop+2]<<8) + input_buffer[loop+3]; w3 = (input_buffer[loop+4]<<8) + input_buffer[loop+5]; w4 = (input_buffer[loop+6]<<8) + input_buffer[loop+7]; } else { w1 = (input_buffer[loop+1]<<8) + input_buffer[loop+0]; w2 = (input_buffer[loop+3]<<8) + input_buffer[loop+2]; w3 = (input_buffer[loop+5]<<8) + input_buffer[loop+4]; w4 = (input_buffer[loop+7]<<8) + input_buffer[loop+6]; } /* Determine order of channels for each sample, subtract previous sample * to compensate for unbalanced audio devices */ o1 = order(w1-psl, w2-psr); o2 = order(w3-psl, w4-psr); if (a > 0) { psl = w3; psr = w4; } else { psl = w1; psr = w2; } /* If both samples have the same order, there is bias in the samples, so we * discard them; if both channels are equal on either sample, we discard * them too; additionally, alternate the sample we'll use next (even more * bias removal) */ if (o1 == o2 || o1 < 0 || o2 < 0) { a = -a; } else { /* We've got a random bit; the bit is either the order from the first or * the second sample, determined by the alternator 'a' */ char bit = (a > 0) ? o1 : o2; byte_out <<= 1; byte_out += bit; bits_out++; got_any = 1; if (bits_out>=8) { bytes[bytes_out++] = byte_out; if (bytes_out == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, bytes_out); if (p && p -> message_transmit_entropy_data(bytes, bytes_out) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); bytes_out = 0; } bits_out = 0; } } } if (!got_any) dolog(LOG_WARNING, "no bits in audio-stream, please make sure the recording channel is not muted"); free_locked(input_buffer, input_buffer_size); } unlock_mem(bytes, sizeof bytes); if (!do_exit) snd_pcm_close(chandle); delete p; } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; const char *cdevice = "hw:1"; /* capture device */ std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "eb_server_audio v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "I:hX:P:So:d:L:l:sn")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 'd': cdevice = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(cdevice); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); main_loop(&hosts, bytes_file, show_bps, username, password, cdevice); unlink(pid_file); fprintf(stderr, "program terminated\n"); return 0; } entropybroker-2.9/server_cycle_count.cpp000066400000000000000000000133301305163522000206670ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_cycle_count v" VERSION; const char *pid_file = PID_DIR "/server_cycle_count.pid"; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" bool do_exit = false; inline unsigned long long GetCC(void) { unsigned a, d; asm volatile("rdtsc" : "=a" (a), "=d" (d)); return ((unsigned long long)a) | (((unsigned long long)d) << 32LL); } typedef struct { char *buffer; volatile int index; int cache_size, cache_line_size; volatile int a; } fiddle_state_t; void fiddle(fiddle_state_t *p) { // trigger cache misses etc p -> a += (p -> buffer)[p -> index]++; p -> index += p -> cache_line_size; while(p -> index >= p -> cache_size * 3) p -> index -= p -> cache_size * 3; } int get_cache_size() { const char *cache_size_file = "/sys/devices/system/cpu/cpu0/cache/index0/size"; FILE *fh = fopen(cache_size_file, "r"); if (!fh) return 1024*1024; // my laptop has 32KB data l1 cache unsigned int s = 0; if (fscanf(fh, "%d", &s) != 1) error_exit("Tried to obtain 1 field from %s, failed doing that", cache_size_file); fclose(fh); return s; } int get_cache_line_size() { const char *cache_line_size_file = "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"; FILE *fh = fopen(cache_line_size_file, "r"); if (!fh) return 1; unsigned int s = 0; if (fscanf(fh, "%d", &s) != 1) error_exit("Tried to obtain 1 field from %s, failed doing that", cache_line_size_file); fclose(fh); return s; } void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { int sw; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((sw = getopt(argc, argv, "I:hX:P:So:L:l:sn")) != -1) { switch(sw) { case 'I': hosts.push_back(optarg); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); fiddle_state_t fs; fs.index = 0; fs.cache_size = get_cache_size(); dolog(LOG_INFO, "cache size: %dKB", fs.cache_size); fs.buffer = reinterpret_cast(malloc(fs.cache_size * 3)); fs.cache_line_size = get_cache_line_size(); dolog(LOG_INFO, "cache-line size: %d bytes", fs.cache_line_size); if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); unsigned char bytes[4096]; lock_mem(bytes, sizeof bytes); unsigned char cur_byte = 0; int bits = 0; int index = 0; init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { fiddle(&fs); unsigned long long int a = GetCC(); fiddle(&fs); unsigned long long int b = GetCC(); fiddle(&fs); unsigned long long int c = GetCC(); fiddle(&fs); unsigned long long int d = GetCC(); int A = int(b - a); int B = int(d - c); cur_byte <<= 1; if (A >= B) cur_byte |= 1; bits++; if (bits == 8) { bytes[index++] = cur_byte; bits = 0; if (index == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p && p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } index = 0; set_showbps_start_ts(); } } } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_egd.cpp000066400000000000000000000160551305163522000171260ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" const char *pid_file = PID_DIR "/server_egd.pid"; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } int open_tcp_socket(char *host, int port) { return connect_to(host, port); } int open_unixdomain_socket(char *path) { int len; struct sockaddr_un addr; int fd = -1; if (strlen(path) >= sizeof addr.sun_path) error_exit("Path %s too large (%d limit)", path, sizeof addr.sun_path); memset(&addr, 0x00, sizeof addr); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path); len = offsetof(struct sockaddr_un, sun_path) + strlen(path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) error_exit("Failed to create socket"); if (connect(fd, (struct sockaddr *)&addr, len) == 0) return fd; error_exit("Failed to connect to %s", path); return -1; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-d path egd unix domain socket to read from\n"); printf("-t host egd tcp host to read from (mutually exclusive from width -d)\n"); printf("-T port egd tcp port to read from\n"); printf("-o file file to write entropy data to (mututally exclusive with -i)\n"); printf("-a x bytes per interval to read from egd\n"); printf("-b x interval for reading data\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int read_fd = -1; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *device = NULL; char *bytes_file = NULL; double read_interval = 5.0; unsigned int read_bytes_per_interval = 16; int index = 0; int verbose = 0; char server_type[128]; bool show_bps = false; std::string username, password; char *egd_host = NULL; int egd_port = -1; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "eb_server_egd v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "I:t:T:hSX:P:a:b:o:d:L:l:snv")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 't': egd_host = optarg; break; case 'T': egd_port = atoi(optarg); if (egd_port < 1) error_exit("-T requires a value >= 1"); break; case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'v': verbose++; break; case 'a': read_bytes_per_interval = atoi(optarg); if (read_bytes_per_interval > sizeof bytes) error_exit("-a: parameter must be %d or less", sizeof bytes); break; case 'b': read_interval = atof(optarg); break; case 'o': bytes_file = optarg; break; case 'd': device = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (username.length() == 0 || password.length() == 0) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to given, also no file to write to given"); if (!device && !egd_host) error_exit( "No egd source specified: use -d or -t (and -T)" ); if (device != NULL && egd_host != NULL) error_exit("-d and -t are mutually exclusive"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); snprintf(server_type, sizeof server_type, "server_egd v" VERSION " %s", device); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); if (device) { read_fd = open_unixdomain_socket(device); if (read_fd == -1) error_exit("error opening %s", device); } else { read_fd = open_tcp_socket(egd_host, egd_port); if (read_fd == -1) error_exit("Failed to connect to %s:%d", egd_host, egd_port); } if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { unsigned char request[2], reply[1]; int bytes_to_read = std::min(255u, std::min((unsigned int)(sizeof bytes - index), read_bytes_per_interval)); // gather random data from EGD request[0] = 1; request[1] = bytes_to_read; if (WRITE(read_fd, request, sizeof request, &do_exit) != 2) error_exit("Problem sending request to EGD"); if (do_exit) break; if (READ(read_fd, reply, 1, &do_exit) != 1) error_exit("Problem receiving reply header from EGD"); if (do_exit) break; bytes_to_read = reply[0]; if (READ(read_fd, &bytes[index], bytes_to_read, &do_exit) != bytes_to_read) error_exit("Problem receiving reply-data from EGD"); if (do_exit) break; index += bytes_to_read; dolog(LOG_DEBUG, "Got %d bytes from EGD", bytes_to_read); //////// if (index == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p) { if (p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } if (read_interval > 0.0 && p -> sleep_interruptable(read_interval, &do_exit) != 0) { dolog(LOG_INFO, "connection closed"); p -> drop(); } } else if (read_interval > 0.0) { usleep(read_interval * 1000000.0); } set_showbps_start_ts(); index = 0; } } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_ext_proc.cpp000066400000000000000000000122241305163522000202040ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SHELL "/bin/bash" #define DEFAULT_SLEEP 0 const char *server_type = "server_ext_proc v" VERSION; const char *pid_file = PID_DIR "/server_ext_proc.pid"; bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-c command command to execute\n"); printf("-Z shell shell to use. default is " SHELL "\n"); printf("-b x how long to sleep between invocations (default: %ds)\n", DEFAULT_SLEEP); printf("-o file file to write entropy data to\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S show bps\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; const char *cmd = NULL, *shell = SHELL; std::string username, password; int slp = DEFAULT_SLEEP; char *bytes_file = NULL; bool show_bps = false; int idle = 0; int log_level = LOG_INFO; std::vector hosts; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "b:I:So:hc:Z:X:P:o:p:d:L:l:sn")) != -1) { switch(c) { case 'b': idle = atoi(optarg); break; case 'o': bytes_file = optarg; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'c': cmd = optarg; break; case 'S': show_bps = true; break; case 'Z': shell = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); if (!cmd) error_exit("no command to execute"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); signal(SIGCHLD, SIG_IGN); bool data = false; int got_bytes = -1; pid_t child_pid; int child_fd = -1; char buffer[32768]; lock_mem(buffer, sizeof buffer); bool first = true; init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { if (child_fd == -1) { if (first) first = false; else if (sleep > 0) sleep(slp); dolog(LOG_DEBUG, "Starting %s", cmd); start_process(shell, cmd, &child_fd, &child_pid); } // gather random data if (!data) { got_bytes = read(child_fd, buffer, sizeof buffer); if (got_bytes <= 0) { dolog(LOG_DEBUG, "Process stopped"); close(child_fd); child_fd = -1; int status = 0; wait(&status); continue; } data = true; } if (data) { if (show_bps) update_showbps(got_bytes); if (bytes_file) emit_buffer_to_file(bytes_file, reinterpret_cast(buffer), got_bytes); if (p) { unsigned char *pnt = reinterpret_cast(buffer); while(got_bytes > 0) { int cur_count = std::min(got_bytes, 4096); if (p -> message_transmit_entropy_data(pnt, cur_count, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } pnt += cur_count; got_bytes -= cur_count; } } set_showbps_start_ts(); data = false; } if (idle > 0) sleep(idle); } unlink(pid_file); memset(buffer, 0x00, sizeof buffer); delete p; return 0; } entropybroker-2.9/server_linux_kernel.cpp000066400000000000000000000105401305163522000210570ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_kernel v" VERSION; const char *pid_file = PID_DIR "/server_kernel.pid"; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #include "kernel_prng_io.h" #include "kernel_prng_rw.h" bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); printf("Please note: this program RETRIEVES entropy data from the kernel and feeds that to the entropybroker!\n"); printf("If you want to ADD data to the kernel entropy buffer instead (which is what you most likely want to do), then use eb_client_linux_kernel\n"); while((c = getopt(argc, argv, "I:hX:P:So:L:l:sn")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); unsigned char bytes[4096]; lock_mem(bytes, sizeof bytes); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { dolog(LOG_DEBUG, "Bits available: %d", kernel_rng_get_entropy_count()); if (kernel_rng_read_blocking(bytes, sizeof bytes) == -1) { dolog(LOG_WARNING, "Problem reading from kernel entropy buffer!"); if (p != NULL && p -> sleep_interruptable(5.0) != 0) { dolog(LOG_INFO, "connection closed"); p -> drop(); continue; } } if (do_exit) break; if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, sizeof bytes); if (p && p -> message_transmit_entropy_data(bytes, sizeof bytes, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); continue; } set_showbps_start_ts(); } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_push_file.cpp000066400000000000000000000101521305163522000203350ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_push_file v" VERSION; const char *pid_file = PID_DIR "/server_push_file.pid"; bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-f file file to read from\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *file = NULL; std::string username, password; char *bytes_file = NULL; bool show_bps = false; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "S:I:f:hX:P:o:p:d:L:l:sn")) != -1) { switch(c) { case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'f': file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); if (!file) error_exit("no file to read from selected"); (void)umask(0177); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); FILE *fh = fopen(file, "rb"); if (!fh) error_exit("Failed to open file %s", file); (void)umask(0177); no_core(); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); bool data = false; int got_bytes = -1; init_showbps(); set_showbps_start_ts(); for(;!feof(fh) && !do_exit;) { // gather random data if (!data) { got_bytes = fread(bytes, 1, sizeof bytes, fh); if (got_bytes <= 0) break; data = true; } if (data) { if (show_bps) update_showbps(got_bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, got_bytes); if (p && p -> message_transmit_entropy_data(bytes, got_bytes, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); data = false; } } fclose(fh); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_qwqng.cpp000066400000000000000000000111131305163522000175120ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" const char *pid_file = PID_DIR "/server_qwqng.pid"; bool do_exit = false; void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to (mututal exclusive with -i)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; int index = 0; int verbose = 0; char server_type[128]; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "eb_server_QNG_PQ4000KU v" VERSION ", (C) 2009-2015 by folkert@vanheusden.com\n"); while((c = getopt(argc, argv, "I:hSX:P:o:L:l:snv")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'v': verbose++; break; case 'o': bytes_file = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); QWQNG *q = new QWQNG(); if (!q -> DeviceID()) error_exit("Could not find a device? (2)"); lock_mem(q, sizeof *q); snprintf(server_type, sizeof server_type, "eb_server_qwqng v" VERSION " %s", q -> DeviceID()); dolog(LOG_INFO, server_type); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); bool stats_error_reported = false; for(;!do_exit;) { int rc = q -> RandBytes(reinterpret_cast(bytes), 4096); if (rc != QNG_S_OK && rc != S_OK) { if (rc == QNG_E_STATS_EXCEPTION) { if (!stats_error_reported) { dolog(LOG_WARNING, "Device reports a statistics test exception"); stats_error_reported = true; } usleep(10000); // do not hog cpu continue; } error_exit("Failed to retrieve random bytes from device %x", rc); } stats_error_reported = false; if (show_bps) update_showbps(4096); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p && p -> message_transmit_entropy_data(bytes, 4096, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); index = 0; } delete p; memset(bytes, 0x00, sizeof bytes); unlink(pid_file); return 0; } entropybroker-2.9/server_smartcard.cpp000066400000000000000000000151221305163522000203410ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_smartcard v" VERSION; const char *pid_file = PID_DIR "/server_smartcard.pid"; bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } double gen_entropy_data(void) { double start; start = get_ts(); /* arbitrary value: * not too small so that there's room for noise * not too large so that we don't sleep unnecessary */ usleep(100); return get_ts() - start; } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int index = 0; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "hX:P:So:I:L:l:sn")) != -1) { switch(c) { case 'I': hosts.push_back(optarg); break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 'i': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); DWORD rv = -1; SCARDCONTEXT hContext; if (SCARD_S_SUCCESS != (rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext))) error_exit("SCardEstablishContext: %s", pcsc_stringify_error(rv)); LPTSTR mszReaders; DWORD dwReaders, dwActiveProtocol; #ifdef SCARD_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; if (SCARD_S_SUCCESS != (rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders))) error_exit("SCardListReaders: %s", pcsc_stringify_error(rv)); #else if (SCARD_S_SUCCESS != (rv = SCardListReaders(hContext, NULL, NULL, &dwReaders))) error_exit("SCardListReaders: %s", pcsc_stringify_error(rv)); mszReaders = calloc(dwReaders, sizeof char); if (SCARD_S_SUCCESS != (rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders))) error_exit("SCardListReaders %s", pcsc_stringify_error(rv)); #endif dolog(LOG_INFO, "reader name: %s", mszReaders); SCARDHANDLE hCard; if (SCARD_S_SUCCESS != (rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol))) error_exit("SCardConnect %s", pcsc_stringify_error(rv)); SCARD_IO_REQUEST pioSendPci; switch(dwActiveProtocol) { case SCARD_PROTOCOL_T0: pioSendPci = *SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = *SCARD_PCI_T1; break; } if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); init_showbps(); set_showbps_start_ts(); for(; !do_exit;) { BYTE pbRecvBuffer[258]; BYTE cmdGET_CHALLENGE[] = { 0x00, 0x84, 0x00, 0x00, 0x08 }; DWORD dwRecvLength = sizeof pbRecvBuffer; if (SCARD_S_SUCCESS != (rv = SCardTransmit(hCard, &pioSendPci, cmdGET_CHALLENGE, sizeof cmdGET_CHALLENGE, NULL, pbRecvBuffer, &dwRecvLength))) error_exit("SCardTransmit %s", pcsc_stringify_error(rv)); if (dwRecvLength == 2) { short code = (pbRecvBuffer[0] << 8) + pbRecvBuffer[1]; if (code == 0x9000) // all fine, just no data { dolog(LOG_WARNING, "No data from card?!"); continue; } error_exit("ISO 7816 error code: %04x", code); } else if (dwRecvLength == 10) { int code = (pbRecvBuffer[8] << 8) + pbRecvBuffer[9]; if (code != 0x9000) // got data but also an error? error_exit("Got data but also an ISO 7816 error code: %04x", code); } int n_to_add = std::min(sizeof bytes - index, (size_t)8); memcpy(&bytes[index], pbRecvBuffer, n_to_add); index += n_to_add; if (index == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p && p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); index = 0; // skip header } } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_stream.cpp000066400000000000000000000154421305163522000176610ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_stream v" VERSION; const char *pid_file = PID_DIR "/server_stream.pid"; #define BLOCK_SIZE 4096 bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void set_serial_parameters(int fd, char *pars_in) { struct termios newtio; char **pars = NULL; int n_pars = 0; int bps = B9600; int bits = CS8; split_string(pars_in, ",", &pars, &n_pars); // bps,bits if (n_pars != 2) error_exit("set serial: missing parameter"); switch(atoi(pars[0])) { case 50: bps = B50; break; case 75: bps = B75; break; case 110: bps = B110; break; case 134: bps = B134; break; case 150: bps = B150; break; case 200: bps = B200; break; case 300: bps = B300; break; case 600: bps = B600; break; case 1200: bps = B1200; break; case 1800: bps = B1800; break; case 2400: bps = B2400; break; case 4800: bps = B4800; break; case 9600: bps = B9600; break; case 19200: bps = B19200; break; case 38400: bps = B38400; break; case 57600: bps = B57600; break; case 115200: bps = B115200; break; case 230400: bps = B230400; break; #ifdef linux case 460800: bps = B460800; break; case 500000: bps = B500000; break; case 576000: bps = B576000; break; case 921600: bps = B921600; break; case 1000000: bps = B1000000; break; case 1152000: bps = B1152000; break; case 1500000: bps = B1500000; break; case 2000000: bps = B2000000; break; /* not all of these constants are available on all architectures */ #ifdef B2500000 case 2500000: bps = B2500000; break; #endif #ifdef B3000000 case 3000000: bps = B3000000; break; #endif #ifdef B3500000 case 3500000: bps = B3500000; break; #endif #ifdef B4000000 case 4000000: bps = B4000000; break; #endif #endif default: error_exit("baudrate %s is not understood", pars[0]); } switch(atoi(pars[1])) { case 5: bits = CS5; break; case 6: bits = CS6; break; case 7: bits = CS7; break; case 8: bits = CS8; break; } if (tcgetattr(fd, &newtio) == -1) error_exit("tcgetattr failed"); newtio.c_iflag = IGNBRK; // | ISTRIP; newtio.c_oflag = 0; newtio.c_cflag = bps | bits | CREAD | CLOCAL | CSTOPB; newtio.c_lflag = 0; newtio.c_cc[VMIN] = 1; newtio.c_cc[VTIME] = 0; tcflush(fd, TCIFLUSH); if (tcsetattr(fd, TCSANOW, &newtio) == -1) error_exit("tcsetattr failed"); } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-d dev device to retrieve from\n"); printf("-o file file to write entropy data to (mututal exclusive with -d)\n"); printf("-p pars if the device is a serial device, then with -p\n"); printf(" you can set its parameters: bps,bits\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[BLOCK_SIZE]; int read_fd = -1; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *device = NULL; char *serial = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "hSX:P:o:p:I:d:L:l:sn")) != -1) { switch(c) { case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'o': bytes_file = optarg; break; case 'p': serial = optarg; break; case 'I': hosts.push_back(optarg); break; case 'd': device = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (device) read_fd = open(device, O_RDONLY); if (read_fd == -1) error_exit("error opening %s", device); if (serial) set_serial_parameters(read_fd, serial); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed"); } protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); init_showbps(); set_showbps_start_ts(); for(;!do_exit;) { if (READ(read_fd, bytes, BLOCK_SIZE, &do_exit) != BLOCK_SIZE) error_exit("error reading from input"); if (show_bps) update_showbps(BLOCK_SIZE); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, BLOCK_SIZE); if (p && p -> message_transmit_entropy_data(bytes, BLOCK_SIZE, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_timers.cpp000066400000000000000000000112571305163522000176710ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include const char *server_type = "server_timers v" VERSION; const char *pid_file = PID_DIR "/server_timers.pid"; bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" #define SLEEP_CLOCK CLOCK_MONOTONIC void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int get_clock_res() { struct timespec ts; if (clock_getres(SLEEP_CLOCK, &ts) == -1) error_exit("clock_getres failed"); return ts.tv_nsec; } inline double gen_entropy_data(int sl) { double start = get_ts_ns(); const struct timespec ts = { 0, sl }; clock_nanosleep(SLEEP_CLOCK, 0, &ts, NULL); return get_ts_ns() - start; } int main(int argc, char *argv[]) { unsigned char bytes[4096]; int bits = 0, index = 0; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "I:hX:P:So:L:l:sn")) != -1) { switch(c) { case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); int slp = get_clock_res(); dolog(LOG_INFO, "resolution of clock is %dns", slp); init_showbps(); set_showbps_start_ts(); unsigned char cur_byte = 0; int equal_cnt = 0; for(;!do_exit;) { // gather random data double t1 = gen_entropy_data(slp), t2 = gen_entropy_data(slp); if (t1 == t2) { equal_cnt++; if (equal_cnt > 5 && slp < 1000) { dolog(LOG_DEBUG, "increasing sleep to %dns", slp); slp++; } continue; } equal_cnt = 0; cur_byte <<= 1; if (t1 >= t2) cur_byte |= 1; if (++bits == 8) { bytes[index++] = cur_byte; bits = 0; if (index == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p && p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); index = 0; // skip header } } } memset(bytes, 0x00, sizeof bytes); unlink(pid_file); delete p; return 0; } entropybroker-2.9/server_usb.cpp000066400000000000000000000134661305163522000171630ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include } const char *server_type = "server_usb v" VERSION; const char *pid_file = PID_DIR "/server_usb.pid"; bool do_exit = false; #include "defines.h" #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" void poke(libusb_device_handle *dev) { unsigned char buffer[256]; (void)libusb_get_descriptor(dev, 0, 0, buffer, sizeof buffer); } long int timed_poke(libusb_device_handle *dev) { struct timespec t1, t2; clock_gettime(CLOCK_REALTIME, &t1); poke(dev); clock_gettime(CLOCK_REALTIME, &t2); long int dummy = t2.tv_sec - t1.tv_sec; return (dummy * 1000000000 + t2.tv_nsec) - t1.tv_nsec; } double gen_entropy_data(libusb_device_handle *dev) { return double(timed_poke(dev)); } void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-o file file to write entropy data to\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { unsigned char bytes[4096]; unsigned char cur_byte = 0; int bits = 0; int c; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *bytes_file = NULL; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "hX:P:So:I:L:l:sn")) != -1) { switch(c) { case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'S': show_bps = true; break; case 'o': bytes_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; case 'h': help(); return 0; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); (void)umask(0177); no_core(); lock_mem(bytes, sizeof bytes); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); if (!do_not_fork && !show_bps) { if (daemon(0, 0) == -1) error_exit("fork failed"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); struct libusb_device **devs = NULL; libusb_device_handle **devhs; int index = 0, n = 0, use_n = 0; if (libusb_init(NULL) < 0) error_exit("cannot init libusb"); if (libusb_get_device_list(NULL, &devs) < 0) error_exit("cannot retrieve usb devicelist"); while(devs[n] != NULL) { n++; } dolog(LOG_INFO, "Found %d devices", n); devhs = (libusb_device_handle **)malloc(sizeof(libusb_device_handle *) * n); for(index=0; index= use_n) dev_index = 0; if (t1 == t2) continue; cur_byte <<= 1; if (t1 > t2) cur_byte |= 1; if (++bits == 8) { bytes[index++] = cur_byte; bits = 0; if (index == sizeof bytes) { if (show_bps) update_showbps(sizeof bytes); if (bytes_file) emit_buffer_to_file(bytes_file, bytes, index); if (p && p -> message_transmit_entropy_data(bytes, index, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); } set_showbps_start_ts(); index = 0; // skip header } } } memset(bytes, 0x00, sizeof bytes); for(index=0; index #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "utils.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" long int byte_cnt = 0, total_byte_cnt = 0; double total_time = 0.0, last_ts = 0.0, last_emit_ts = 0.0; void emit_buffer_to_file(char *file, unsigned char *data, size_t n_bytes) { FILE *fh = fopen(file, "a+"); if (!fh) error_exit("Error opening %s for append access", file); if (fwrite(data, 1, n_bytes, fh) != n_bytes) error_exit("Short write to %s", file); fclose(fh); } void init_showbps() { byte_cnt = total_byte_cnt = 0; total_time = 0.0; last_emit_ts = get_ts(); } void set_showbps_start_ts() { last_ts = get_ts(); } void update_showbps(int count) { double now_ts = get_ts(); double diff_ts = now_ts - last_ts; byte_cnt += count; total_byte_cnt += count; total_time += diff_ts; if (now_ts - last_emit_ts >= 1.0) { dolog(LOG_INFO, "Total # bytes: %ld, global avg/s: %f, run time: %fs, interval: %fs, avg/s: %f", total_byte_cnt, double(total_byte_cnt) / total_time, total_time, diff_ts, double(byte_cnt) / diff_ts); byte_cnt = 0; last_emit_ts = now_ts; } } entropybroker-2.9/server_utils.h000066400000000000000000000002361305163522000171660ustar00rootroot00000000000000void emit_buffer_to_file(char *file, unsigned char *data, size_t n_bytes); void init_showbps(); void set_showbps_start_ts(); void update_showbps(int count); entropybroker-2.9/server_v4l.cpp000066400000000000000000000224271305163522000170740ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defines.h" #include "error.h" #include "random_source.h" #include "log.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #include "server_utils.h" #include "utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "auth.h" const char *server_type = "server_v4l v" VERSION; const char *pid_file = PID_DIR "/server_v4l.pid"; bool do_exit = false; #define RES_LOW 0 #define RES_HIGH 127 void sig_handler(int sig) { fprintf(stderr, "Exit due to signal %d\n", sig); do_exit = true; } void open_dev(char *dev_name, int *fd, unsigned char **io_buffer, int *io_buffer_len) { *fd = open(dev_name, O_RDWR); if (*fd == -1) return; struct v4l2_capability cap; memset(&cap, 0x00, sizeof cap); if (ioctl(*fd, VIDIOC_QUERYCAP, &cap) == -1) error_exit("Cannot VIDIOC_QUERYCAP"); else { dolog(LOG_DEBUG, "Device %s is:", dev_name); dolog(LOG_DEBUG, " %s %s %s", cap.driver, cap.card, cap.bus_info); dolog(LOG_DEBUG, " version: %d %d %d", (cap.version >> 16) & 255, (cap.version >> 8) & 255, cap.version & 255); if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) error_exit("Video4linux device cannot capture video"); } struct v4l2_format fmt; memset(&fmt, 0x00, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; if (ioctl(*fd, VIDIOC_G_FMT, &fmt) == -1) error_exit("ioctl(VIDIOC_G_FMT) failed"); char format[5]; memcpy(format, &fmt.fmt.pix.pixelformat, 4); format[4]=0x00; dolog(LOG_DEBUG, " %dx%d: %d/%s\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.type, format); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(*fd, VIDIOC_S_FMT, &fmt) == -1) error_exit("ioctl(VIDIOC_S_FMT) failed"); struct v4l2_requestbuffers req; memset(&req, 0x00, sizeof req); req.count = 1; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(*fd, VIDIOC_REQBUFS, &req) == -1) error_exit("ioctl(VIDIOC_REQBUFS) failed"); struct v4l2_buffer buf; memset(&buf, 0x00, sizeof buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; if (ioctl(*fd, VIDIOC_QUERYBUF, &buf) == -1) error_exit("ioctl(VIDIOC_QUERYBUF) failed"); if (ioctl(*fd, VIDIOC_QBUF, &buf) == -1) error_exit("ioctl(VIDIOC_QBUF) failed"); enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(*fd, VIDIOC_STREAMON, &buf_type) == -1) error_exit("ioctl(VIDIOC_STREAMON) failed"); *io_buffer_len = buf.length; dolog(LOG_DEBUG, "%d bytes", *io_buffer_len); *io_buffer = static_cast(mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, buf.m.offset)); if (!*io_buffer) dolog(LOG_CRIT, "mmap() failed %s", strerror(errno)); } void close_device(int fd, unsigned char *p, int p_len) { munmap(p, p_len); close(fd); } void take_picture(int fd, struct v4l2_buffer *buf) { if (ioctl(fd, VIDIOC_DQBUF, buf) == -1) dolog(LOG_CRIT, "VIDIOC_DQBUF failed %s", strerror(errno)); } void untake_picture(int fd, struct v4l2_buffer *buf) { if (ioctl(fd, VIDIOC_QBUF, buf) == -1) dolog(LOG_CRIT, "VIDIOC_QBUF failed %s", strerror(errno)); } void help(void) { printf("-I host entropy_broker host to connect to\n"); printf(" e.g. host\n"); printf(" host:port\n"); printf(" [ipv6 literal]:port\n"); printf(" you can have multiple entries of this\n"); printf("-d x device to use\n"); printf("-o file file to write entropy data to (mututal exclusive with -d)\n"); printf("-f x skip x frames before processing images (in case the device\n"); printf(" needs a few frames to settle)\n"); printf("-l file log to file 'file'\n"); printf("-L x log level, 0=nothing, 255=all\n"); printf("-s log to syslog\n"); printf("-n do not fork\n"); printf("-S show bps (mutual exclusive with -n)\n"); printf("-P file write pid to file\n"); printf("-X file read username+password from file\n"); } int main(int argc, char *argv[]) { int device_settle = 25; int c; unsigned char *img1, *img2, *unbiased; bool do_not_fork = false, log_console = false, log_syslog = false; char *log_logfile = NULL; char *device = NULL; char *bytes_file = NULL; int loop; bool show_bps = false; std::string username, password; std::vector hosts; int log_level = LOG_INFO; fprintf(stderr, "%s, (C) 2009-2015 by folkert@vanheusden.com\n", server_type); while((c = getopt(argc, argv, "hSX:P:f:o:I:d:L:l:sn")) != -1) { switch(c) { case 'S': show_bps = true; break; case 'X': get_auth_from_file(optarg, username, password); break; case 'P': pid_file = optarg; break; case 'f': device_settle = atoi(optarg); if (device_settle < 0) error_exit("-f requires a value >= 0"); break; case 'o': bytes_file = optarg; break; case 'I': hosts.push_back(optarg); break; case 'd': device = optarg; break; case 's': log_syslog = true; break; case 'L': log_level = atoi(optarg); break; case 'l': log_logfile = optarg; break; case 'n': do_not_fork = true; log_console = true; break; default: help(); return 1; } } if (!hosts.empty() && (username.length() == 0 || password.length() == 0)) error_exit("please select a file with authentication parameters (username + password) using the -X switch"); if (hosts.empty() && !bytes_file) error_exit("no host to connect to or file to write to given"); if (!device) error_exit("Please select a video4linux video device (a webcam, tv-card, etc.)\ne.g.: -d /dev/vide0"); (void)umask(0177); no_core(); set_logging_parameters(log_console, log_logfile, log_syslog, log_level); signal(SIGHUP , SIG_IGN); signal(SIGTERM, sig_handler); signal(SIGINT , sig_handler); signal(SIGQUIT, sig_handler); signal(SIGPIPE, SIG_IGN); if (!do_not_fork) { if (daemon(0, 0) == -1) error_exit("fork failed - out of resources?"); } write_pid(pid_file); protocol *p = NULL; if (!hosts.empty()) p = new protocol(&hosts, username, password, true, server_type, DEFAULT_COMM_TO); /* open device */ int fd = -1; unsigned char *io_buffer = NULL; int io_buffer_len = -1; open_dev(device, &fd, &io_buffer, &io_buffer_len); if (fd == -1) error_exit("failure opening %s", device); /* let device settle */ dolog(LOG_DEBUG, "waiting for device to settle"); for(loop=0; loop(malloc_locked(io_buffer_len)); img2 = reinterpret_cast(malloc_locked(io_buffer_len)); unbiased = reinterpret_cast(malloc_locked(io_buffer_len)); if (!img1 || !img2 || !unbiased) error_exit("out of memory"); struct v4l2_buffer buf; /* take pictures */ dolog(LOG_DEBUG, "Smile!"); memset(&buf, 0x00, sizeof buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; take_picture(fd, &buf); memcpy(img1, io_buffer, io_buffer_len); untake_picture(fd, &buf); // memset(&buf, 0x00, sizeof buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; take_picture(fd, &buf); memcpy(img2, io_buffer, io_buffer_len); untake_picture(fd, &buf); /* unbiase */ dolog(LOG_DEBUG, "Filtering..."); int nunbiased=0, nbits = 0; for(loop=0; loop 0) { if (show_bps) update_showbps(nunbiased); if (bytes_file) emit_buffer_to_file(bytes_file, unbiased, nunbiased); if (p) { unsigned char *tempp = unbiased; int count = nunbiased; while(count > 0) { int n_to_do = std::min(count, 4096); if (p -> message_transmit_entropy_data(tempp, n_to_do, &do_exit) == -1) { dolog(LOG_INFO, "connection closed"); p -> drop(); break; } tempp += n_to_do; count -= n_to_do; } } set_showbps_start_ts(); } free_locked(unbiased, io_buffer_len); } dolog(LOG_DEBUG, "Cleaning up"); close_device(fd, io_buffer, io_buffer_len); delete p; unlink(pid_file); return 0; } entropybroker-2.9/signals.cpp000066400000000000000000000022651305163522000164370ustar00rootroot00000000000000#include #include #include #include #include "error.h" static int signal_hup = 0, signal_exit = 0; void signal_handler(int sig) { if (sig == SIGHUP) signal_hup = 1; if (sig == SIGTERM || sig == SIGQUIT || sig == SIGINT) signal_exit = 1; if (sig == SIGBUS) error_exit("hardware issue, terminating"); if (sig == SIGUSR2) exit(0); signal(sig, signal_handler); } int is_SIGHUP(void) { return signal_hup; } void reset_SIGHUP(void) { signal_hup = 0; } int is_SIGEXIT(void) { return signal_exit; } #ifdef HELGRIND void sigsegv_handler(int sig) { void *trace[128]; int trace_size = backtrace(trace, 128); char **messages = backtrace_symbols(trace, trace_size); fprintf(stderr, "SIGSEGV\n"); for(int index=0; index #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "statistics.h" statistics::statistics() { pthread_check(pthread_mutex_init(&recv_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&sent_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(×_empty_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(×_full_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(×_quota_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&disconnects_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&timeouts_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&msg_cnt_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&time_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&submit_while_full_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&network_error_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&protocol_error_lck, &global_mutex_attr), "pthread_mutex_init"); pthread_check(pthread_mutex_init(&misc_errors_lck, &global_mutex_attr), "pthread_mutex_init"); bps_cur = 0; total_recv = total_recv_sd = total_recv_in = total_recv_in_sd = 0; total_sent = total_sent_sd = 0; total_recv_requests = 0; total_sent_requests = 0; n_times_empty = 0; n_times_full = 0; n_times_quota = 0; disconnects = 0; timeouts = 0; submit_while_full = 0; misc_errors = protocol_error = network_error = 0; msg_cnt = 0; last_message = last_put_message = last_get_message = 0; } statistics::~statistics() { pthread_check(pthread_mutex_destroy(&recv_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&sent_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(×_empty_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(×_full_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(×_quota_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&disconnects_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&timeouts_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&msg_cnt_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&time_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&submit_while_full_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&network_error_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&protocol_error_lck), "pthread_mutex_destroy"); pthread_check(pthread_mutex_destroy(&misc_errors_lck), "pthread_mutex_destroy"); } void statistics::inc_disconnects() { my_mutex_lock(&disconnects_lck); disconnects++; my_mutex_unlock(&disconnects_lck); } int statistics::get_disconnects() { my_mutex_lock(&disconnects_lck); int dummy = disconnects; my_mutex_unlock(&disconnects_lck); return dummy; } void statistics::inc_timeouts() { my_mutex_lock(&timeouts_lck); timeouts++; my_mutex_unlock(&timeouts_lck); } void statistics::inc_n_times_empty() { my_mutex_lock(×_empty_lck); n_times_empty++; my_mutex_unlock(×_empty_lck); } void statistics::inc_n_times_quota() { my_mutex_lock(×_quota_lck); n_times_quota++; my_mutex_unlock(×_quota_lck); } void statistics::inc_n_times_full() { my_mutex_lock(×_full_lck); n_times_full++; my_mutex_unlock(×_full_lck); } void statistics::track_sents(int cur_n_bits) { my_mutex_lock(&sent_lck); bps_cur += cur_n_bits; total_sent += cur_n_bits; total_sent_sd += cur_n_bits * cur_n_bits; total_sent_requests++; my_mutex_unlock(&sent_lck); } void statistics::track_recvs(int n_bits_added, int n_bits_in) { my_mutex_lock(&recv_lck); total_recv += n_bits_added; total_recv_sd += n_bits_added * n_bits_added; total_recv_in += n_bits_in; total_recv_in_sd += n_bits_in * n_bits_in; total_recv_requests++; my_mutex_unlock(&recv_lck); } int statistics::get_times_empty() { my_mutex_lock(×_empty_lck); int dummy = n_times_empty; my_mutex_unlock(×_empty_lck); return dummy; } int statistics::get_times_full() { my_mutex_lock(×_full_lck); int dummy = n_times_full; my_mutex_unlock(×_full_lck); return dummy; } int statistics::get_times_quota() { my_mutex_lock(×_quota_lck); int dummy = n_times_quota; my_mutex_unlock(×_quota_lck); return dummy; } void statistics::get_recvs(long long int *total_bits, int *n_reqs, long long int *total_bits_in) { my_mutex_lock(&recv_lck); *total_bits = total_recv; *total_bits_in = total_recv_in; *n_reqs = total_recv_requests; my_mutex_unlock(&recv_lck); } void statistics::get_sents(long long int *total_bits, int *n_sents) { my_mutex_lock(&sent_lck); *total_bits = total_sent; *n_sents = total_sent_requests; my_mutex_unlock(&sent_lck); } void statistics::inc_msg_cnt() { my_mutex_lock(&msg_cnt_lck); msg_cnt++; my_mutex_unlock(&msg_cnt_lck); } int statistics::get_msg_cnt() { my_mutex_lock(&msg_cnt_lck); int dummy = msg_cnt; my_mutex_unlock(&msg_cnt_lck); return dummy; } void statistics::register_msg(bool is_put) { double now = get_ts(); my_mutex_lock(&time_lck); last_message = now; if (is_put) last_put_message = now; else last_get_message = now; my_mutex_unlock(&time_lck); } double statistics::get_last_msg_ts() { my_mutex_lock(&time_lck); double dummy = last_message; my_mutex_unlock(&time_lck); return dummy; } double statistics::get_last_put_msg_ts() { my_mutex_lock(&time_lck); double dummy = last_put_message; my_mutex_unlock(&time_lck); return dummy; } double statistics::get_last_get_msg_ts() { my_mutex_lock(&time_lck); double dummy = last_get_message; my_mutex_unlock(&time_lck); return dummy; } void statistics::get_sent_avg_sd(double *avg, double *sd) { *avg = double(total_sent) / double(total_sent_requests); *sd = sqrt((double(total_sent_sd) / double(total_sent_requests)) - pow(*avg, 2.0)); } void statistics::get_recv_avg_sd(double *avg, double *sd) { *avg = double(total_recv) / double(total_recv_requests); *sd = sqrt((double(total_recv_sd) / double(total_recv_requests)) - pow(*avg, 2.0)); } void statistics::get_recv_in_avg_sd(double *avg, double *sd) { *avg = double(total_recv_in) / double(total_recv_requests); *sd = sqrt((double(total_recv_in_sd) / double(total_recv_requests)) - pow(*avg, 2.0)); } int statistics::get_reset_bps_cur() { my_mutex_lock(&sent_lck); int dummy = bps_cur; bps_cur = 0; my_mutex_unlock(&sent_lck); return dummy; } void statistics::inc_submit_while_full() { my_mutex_lock(&submit_while_full_lck); submit_while_full++; my_mutex_unlock(&submit_while_full_lck); } int statistics::get_submit_while_full() { my_mutex_lock(&submit_while_full_lck); int dummy = submit_while_full; my_mutex_unlock(&submit_while_full_lck); return dummy; } void statistics::inc_network_error() { my_mutex_lock(&network_error_lck); network_error++; my_mutex_unlock(&network_error_lck); } int statistics::get_network_error() { my_mutex_lock(&network_error_lck); int dummy = network_error; my_mutex_unlock(&network_error_lck); return dummy; } void statistics::inc_protocol_error() { my_mutex_lock(&protocol_error_lck); protocol_error++; my_mutex_unlock(&protocol_error_lck); } int statistics::get_protocol_error() { my_mutex_lock(&protocol_error_lck); int dummy = protocol_error; my_mutex_unlock(&protocol_error_lck); return dummy; } void statistics::inc_misc_errors() { my_mutex_lock(&misc_errors_lck); misc_errors++; my_mutex_unlock(&misc_errors_lck); } int statistics::get_misc_errors() { my_mutex_lock(&misc_errors_lck); int dummy = misc_errors; my_mutex_unlock(&misc_errors_lck); return dummy; } entropybroker-2.9/statistics.h000066400000000000000000000036531305163522000166400ustar00rootroot00000000000000class statistics { protected: pthread_mutex_t recv_lck; long long int total_recv, total_recv_sd, total_recv_in, total_recv_in_sd; int total_recv_requests; pthread_mutex_t sent_lck; long long int total_sent, total_sent_sd; int total_sent_requests; int bps_cur; pthread_mutex_t times_empty_lck; int n_times_empty; pthread_mutex_t times_full_lck; int n_times_full; pthread_mutex_t times_quota_lck; int n_times_quota; pthread_mutex_t disconnects_lck; int disconnects; pthread_mutex_t timeouts_lck; int timeouts; pthread_mutex_t msg_cnt_lck; int msg_cnt; pthread_mutex_t submit_while_full_lck; int submit_while_full; pthread_mutex_t network_error_lck; int network_error; pthread_mutex_t protocol_error_lck; int protocol_error; pthread_mutex_t misc_errors_lck; int misc_errors; pthread_mutex_t time_lck; double last_message, last_put_message, last_get_message; public: statistics(); virtual ~statistics(); void inc_disconnects(); void inc_timeouts(); void inc_n_times_empty(); void inc_n_times_quota(); void inc_n_times_full(); void inc_msg_cnt(); void inc_submit_while_full(); void inc_network_error(); void inc_protocol_error(); void inc_misc_errors(); void track_sents(int cur_n_bits); void track_recvs(int n_bits_added, int n_bits_added_in); void register_msg(bool is_put); int get_reset_bps_cur(); int get_msg_cnt(); int get_disconnects(); int get_times_empty(); int get_times_full(); int get_times_quota(); int get_submit_while_full(); int get_network_error(); int get_protocol_error(); int get_misc_errors(); void get_recvs(long long int *total_bits, int *n_reqs, long long int *total_bits_in); void get_sents(long long int *total_bits, int *n_sents); double get_last_msg_ts(); double get_last_put_msg_ts(); double get_last_get_msg_ts(); void get_sent_avg_sd(double *avg, double *sd); void get_recv_avg_sd(double *avg, double *sd); void get_recv_in_avg_sd(double *avg, double *sd); }; entropybroker-2.9/statistics_global.cpp000066400000000000000000000025121305163522000205040ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" double start_ts = get_ts(); double get_start_ts() { return start_ts; } statistics_global::statistics_global() { pthread_check(pthread_mutex_init(&logins_lck, &global_mutex_attr), "pthread_mutex_init"); } statistics_global::~statistics_global() { pthread_check(pthread_mutex_destroy(&logins_lck), "pthread_mutex_destroy"); } void statistics_global::put_history_log(hl_type_t hl_in, std::string host_in, std::string type_in, std::string user_in, double start_ts_in, double duration_in, std::string details_in) { history_logins entry; entry.hl = hl_in; entry.host = host_in; entry.type = type_in; entry.user = user_in; entry.time_logged_in = start_ts_in; entry.duration = duration_in; entry.details = details_in; entry.event_ts = get_ts(); my_mutex_lock(&logins_lck); logins.push_back(entry); while(logins.size() > HISTORY_REMEMBER_N) logins.erase(logins.begin() + 0); my_mutex_unlock(&logins_lck); } std::vector statistics_global::get_login_history() { my_mutex_lock(&logins_lck); std::vector result = logins; my_mutex_unlock(&logins_lck); return result; } entropybroker-2.9/statistics_global.h000066400000000000000000000013221305163522000201470ustar00rootroot00000000000000#define HISTORY_REMEMBER_N 128 typedef enum { HL_LOGIN_OK, HL_LOGOUT_OK, HL_LOGIN_USER_FAIL, HL_LOGIN_PW_FAIL, HL_LOGIN_OTHER } hl_type_t; extern double start_ts; double get_start_ts(); class history_logins { public: hl_type_t hl; std::string host, type, user; double time_logged_in, duration, event_ts; std::string details; }; class statistics_global : public statistics { protected: pthread_mutex_t logins_lck; std::vector logins; public: statistics_global(); ~statistics_global(); void put_history_log(hl_type_t, std::string host_in, std::string type_in, std::string user_in, double start_ts, double duration_in, std::string details); std::vector get_login_history(); }; entropybroker-2.9/statistics_log.cpp000066400000000000000000000052371305163522000200340ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "error.h" #include "random_source.h" #include "log.h" #include "math.h" #include "hasher.h" #include "stirrer.h" #include "fips140.h" #include "hasher_type.h" #include "stirrer_type.h" #include "encrypt_stream.h" #include "encrypt_stream_blowfish.h" #include "pool_crypto.h" #include "pool.h" #include "config.h" #include "scc.h" #include "pools.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "utils.h" #include "auth.h" void emit_statistics_file(std::string file, statistics *s, pools *ppools, scc *pscc, int n_clients) { FILE *fh = fopen(file.c_str(), "a+"); if (!fh) error_exit("cannot access file %s", file.c_str()); struct rusage usage; if (getrusage(RUSAGE_SELF, &usage) == -1) error_exit("getrusage() failed"); double proc_usage = double(usage.ru_utime.tv_sec) + double(usage.ru_utime.tv_usec) / 1000000.0 + double(usage.ru_stime.tv_sec) + double(usage.ru_stime.tv_usec) / 1000000.0; double now = get_ts(); int total_n_bits = ppools -> get_bit_sum(1.0); long long int total_recv = 0, total_sent = 0, dummy; int total_recv_requests = 0, total_sent_requests = 0; s -> get_recvs(&total_recv, &total_recv_requests, &dummy); s -> get_sents(&total_sent, &total_sent_requests); fprintf(fh, "%f %lld %lld %d %d %d %d %f %s\n", now, total_recv, total_sent, total_recv_requests, total_sent_requests, n_clients, total_n_bits, proc_usage, pscc -> stats().c_str()); fclose(fh); } void emit_statistics_log(statistics *s, int n_clients, bool force_stats, int reset_counters_interval, pools *ppools, fips140 *pfips140, scc *pscc) { int total_n_bits = ppools -> get_bit_sum(1.0); double now = get_ts(); double runtime = now - start_ts; long long int total_recv = 0, total_sent = 0, dummy; int total_recv_requests = 0, total_sent_requests = 0; s -> get_recvs(&total_recv, &total_recv_requests, &dummy); s -> get_sents(&total_sent, &total_sent_requests); int bps = s -> get_reset_bps_cur() / reset_counters_interval; dolog(LOG_DEBUG, "stats|client bps: %d (in last %ds interval), disconnects: %d", bps, reset_counters_interval, s -> get_disconnects()); dolog(LOG_DEBUG, "stats|total recv: %ld (%fbps), total sent: %ld (%fbps), run time: %f", total_recv, double(total_recv) / runtime, total_sent, double(total_sent) / runtime, runtime); dolog(LOG_DEBUG, "stats|recv requests: %d, sent: %d, clients/servers: %u, bits: %d", total_recv_requests, total_sent_requests, n_clients, total_n_bits); dolog(LOG_DEBUG, "stats|%s, scc: %s", pfips140, pscc); } entropybroker-2.9/statistics_log.h000066400000000000000000000003711305163522000174730ustar00rootroot00000000000000void emit_statistics_file(std::string file, statistics *s, pools *ppools, scc *pscc, int n_clients); void emit_statistics_log(statistics *s, int n_clients, bool force_stats, int reset_counters_interval, pools *ppools, fips140 *pfips140, scc *pscc); entropybroker-2.9/statistics_user.cpp000066400000000000000000000010431305163522000202200ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "statistics.h" #include "statistics_user.h" statistics_user::statistics_user() { connected_since = 0; } void statistics_user::register_msg(bool is_put) { double now = get_ts(); my_mutex_lock(&time_lck); if (connected_since == 0) connected_since = now; last_message = now; if (is_put) last_put_message = now; else last_get_message = now; my_mutex_unlock(&time_lck); } entropybroker-2.9/statistics_user.h000066400000000000000000000002221305163522000176630ustar00rootroot00000000000000class statistics_user : public statistics { protected: double connected_since; public: statistics_user(); void register_msg(bool is_put); }; entropybroker-2.9/stirrer.cpp000066400000000000000000000001061305163522000164610ustar00rootroot00000000000000#include "stirrer.h" stirrer::stirrer() { } stirrer::~stirrer() { } entropybroker-2.9/stirrer.h000066400000000000000000000004571305163522000161370ustar00rootroot00000000000000class stirrer { public: stirrer(); virtual ~stirrer(); virtual int get_ivec_size() = 0; virtual int get_stir_size() = 0; virtual void do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction) = 0; }; entropybroker-2.9/stirrer_3des.cpp000066400000000000000000000017721305163522000174110ustar00rootroot00000000000000#include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "encrypt_stream.h" #include "encrypt_stream_3des.h" #include "stirrer.h" #include "stirrer_3des.h" stirrer_3des::stirrer_3des() { } stirrer_3des::~stirrer_3des() { } int stirrer_3des::get_stir_size() { return enc.get_key_size(); } int stirrer_3des::get_ivec_size() { return enc.get_ivec_size(); } void stirrer_3des::do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction) { my_assert(target_size > 0); my_assert(data_in_size > 0); unsigned char temp_key[24] = { 0 }; if (data_in_size > get_stir_size()) error_exit("Invalid stir-size %d (expected: %d)", data_in_size, get_stir_size()); memcpy(temp_key, data_in, data_in_size); enc.init(temp_key, 24, ivec, true); enc.encrypt(target, target_size, temp_buffer); memcpy(target, temp_buffer, target_size); } entropybroker-2.9/stirrer_3des.h000066400000000000000000000005441305163522000170520ustar00rootroot00000000000000#define SET_KEY_ATTEMPTS 10 class stirrer_3des : public stirrer { private: encrypt_stream_3des enc; public: stirrer_3des(); ~stirrer_3des(); int get_ivec_size(); int get_stir_size(); void do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction); }; entropybroker-2.9/stirrer_aes.cpp000066400000000000000000000017411305163522000173170ustar00rootroot00000000000000#include #include #include #include #include "error.h" #include "utils.h" #include "encrypt_stream.h" #include "encrypt_stream_aes.h" #include "stirrer.h" #include "stirrer_aes.h" stirrer_aes::stirrer_aes() { } stirrer_aes::~stirrer_aes() { } int stirrer_aes::get_stir_size() { return enc.get_key_size(); } int stirrer_aes::get_ivec_size() { return enc.get_ivec_size(); } void stirrer_aes::do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction) { my_assert(target_size > 0); my_assert(data_in_size > 0); unsigned char temp_key[32] = { 0 }; if (data_in_size > get_stir_size()) error_exit("Invalid stir-size %d (expected: %d)", data_in_size, get_stir_size()); memcpy(temp_key, data_in, data_in_size); enc.init(temp_key, 32, ivec, true); enc.encrypt(target, target_size, temp_buffer); memcpy(target, temp_buffer, target_size); } entropybroker-2.9/stirrer_aes.h000066400000000000000000000005031305163522000167570ustar00rootroot00000000000000class stirrer_aes : public stirrer { private: encrypt_stream_aes enc; public: stirrer_aes(); ~stirrer_aes(); int get_ivec_size(); int get_stir_size(); void do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction); }; entropybroker-2.9/stirrer_blowfish.cpp000066400000000000000000000017351305163522000203670ustar00rootroot00000000000000#include #include #include #include #include #include "error.h" #include "utils.h" #include "encrypt_stream.h" #include "encrypt_stream_blowfish.h" #include "stirrer.h" #include "stirrer_blowfish.h" stirrer_blowfish::stirrer_blowfish() { } stirrer_blowfish::~stirrer_blowfish() { } int stirrer_blowfish::get_stir_size() { return enc.get_key_size(); } int stirrer_blowfish::get_ivec_size() { return enc.get_ivec_size(); } void stirrer_blowfish::do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction) { my_assert(target_size > 0); my_assert(data_in_size > 0); if (data_in_size > get_stir_size()) error_exit("Invalid stir-size %d (expected: %d)", data_in_size, get_stir_size()); enc.init(data_in, data_in_size, ivec, true); enc.encrypt(target, target_size, temp_buffer); memcpy(target, temp_buffer, target_size); } entropybroker-2.9/stirrer_blowfish.h000066400000000000000000000005271305163522000200320ustar00rootroot00000000000000class stirrer_blowfish : public stirrer { private: encrypt_stream_blowfish enc; public: stirrer_blowfish(); ~stirrer_blowfish(); int get_ivec_size(); int get_stir_size(); void do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction); }; entropybroker-2.9/stirrer_camellia.cpp000066400000000000000000000017061305163522000203170ustar00rootroot00000000000000#include #include #include #include #include "error.h" #include "utils.h" #include "encrypt_stream.h" #include "encrypt_stream_camellia.h" #include "stirrer.h" #include "stirrer_camellia.h" stirrer_camellia::stirrer_camellia() { } stirrer_camellia::~stirrer_camellia() { } int stirrer_camellia::get_stir_size() { return enc.get_key_size(); } int stirrer_camellia::get_ivec_size() { return enc.get_ivec_size();; } void stirrer_camellia::do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction) { my_assert(target_size > 0); my_assert(data_in_size > 0); if (data_in_size > get_stir_size()) error_exit("Invalid stir-size %d (expected: %d)", data_in_size, get_stir_size()); enc.init(data_in, data_in_size, ivec, true); enc.encrypt(target, target_size, temp_buffer); memcpy(target, temp_buffer, target_size); } entropybroker-2.9/stirrer_camellia.h000066400000000000000000000005261305163522000177630ustar00rootroot00000000000000class stirrer_camellia : public stirrer { private: encrypt_stream_camellia enc; public: stirrer_camellia(); ~stirrer_camellia(); int get_ivec_size(); int get_stir_size(); void do_stir(unsigned char *ivec, unsigned char *target, int target_size, unsigned char *data_in, int data_in_size, unsigned char *temp_buffer, bool direction); }; entropybroker-2.9/stirrer_type.h000066400000000000000000000000751305163522000171740ustar00rootroot00000000000000enum stirrer_type { S_BLOWFISH, S_AES, S_3DES, S_CAMELLIA }; entropybroker-2.9/test_TFO.cpp000066400000000000000000000003471305163522000164650ustar00rootroot00000000000000#include #include #include #include int main(int argc, char *argv[]) { int fd = 0; int qlen = 5; setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); return 0; } entropybroker-2.9/test_asound2.cpp000066400000000000000000000001151305163522000174010ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_cryptopp.cpp000066400000000000000000000004231305163522000177100ustar00rootroot00000000000000#include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_gcc.cpp000066400000000000000000000001401305163522000165600ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { printf("Hello, world\n"); return 0; } entropybroker-2.9/test_libftdi.cpp000066400000000000000000000001031305163522000174400ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_libgd2.cpp000066400000000000000000000001011305163522000171640ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_libpng.cpp000066400000000000000000000001021305163522000172750ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_libqwqng.cpp000066400000000000000000000001071305163522000176530ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_libusb.cpp000066400000000000000000000001201305163522000173020ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_pcsclite.cpp000066400000000000000000000001071305163522000176350ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/test_zlib.cpp000066400000000000000000000001031305163522000167630ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { return 0; } entropybroker-2.9/todo000066400000000000000000000025011305163522000151540ustar00rootroot00000000000000- rdrand server - http://www.av8n.com/turbid/paper/turbid.htm - server voor dat dingetje met die usb - client: in classes - retrieve from other eb instance (eb_proxy) - keep stats of disk-get & put to advise user of ideal number of memory pools - acls (ip) - http://en.wikipedia.org/wiki/Secure_Remote_Password_protocol - scsi-ping-entropyd - filter.cpp: - whitening 0/0 en 1/1 -> drop, 01=0bit, 10=1bit - what else? xoren met prng van openssl? - multiple hosts ^ load balance 'server' but also client - fips140 & scc in een wrapper 'verify_entropy'-class proppen - servers: work in units given by broker - dump random states to state-file(s?) - calc_time_left debuggen of 't vaak voorkomt dat time_left < 0 - webserver - constants in data logger configureerbaar? interval/keep_n - keep track of bandwidth of each user: if > avg+stddev, then alert in logfile - per user totals? store in file for longer history? - per user graphs, dan per 10 minuten of minder dagen? - hash for protocol (user password): Use bcrypt or PBKDF2 exclusively to hash anything you need to be secure. - schermpje dat alleen de users laat zien met statistics per username (die bewaren in een file?) en on-line status etc - clients/servers: logout (cleanly) when a signal has been received - move user-stats object from client_t to users-object entropybroker-2.9/users.cpp000066400000000000000000000320201305163522000161300ustar00rootroot00000000000000#include #include #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "statistics.h" #include "statistics_user.h" #include "users.h" users::users(std::string filename_in, int default_max_get_bps_in) : filename(filename_in), default_max_get_bps(default_max_get_bps_in) { pthread_check(pthread_rwlock_init(&rwlck, NULL), "pthread_rwlock_init"); user_map = NULL; load_usermap(); } users::~users() { delete user_map; pthread_check(pthread_rwlock_destroy(&rwlck), "pthread_rwlock_destroy"); } void users::list_wlock() { pthread_check(pthread_rwlock_wrlock(&rwlck), "pthread_rwlock_wrlock"); } void users::list_wunlock() { pthread_check(pthread_rwlock_unlock(&rwlck), "pthread_rwlock_unlock"); } void users::list_runlock() { pthread_check(pthread_rwlock_unlock(&rwlck), "pthread_rwlock_unlock"); } void users::list_rlock() { pthread_check(pthread_rwlock_rdlock(&rwlck), "pthread_rwlock_rdlock"); } void users::reload() { dolog(LOG_INFO, "Reload user database"); list_wlock(); std::map::iterator it; for(it = user_map -> begin(); it != user_map -> end(); it++) pthread_check(pthread_mutex_destroy(&it -> second.lck), "pthread_mutex_destroy"); delete user_map; load_usermap(); list_wunlock(); } void users::load_usermap() { user_map = new std::map(); std::ifstream fh(filename.c_str()); if (!fh.is_open()) error_exit("Cannot open %s", filename.c_str()); std::string line; int line_nr = 0; while(!fh.eof()) { std::getline(fh, line); if (line.length() == 0) break; line_nr++; std::vector pars = split_string(line, "|"); if (pars.size() == 1) error_exit("%s: separator missing at line %d (%s)", filename.c_str(), line_nr, line.c_str()); user_t u; u.password = pars[1]; if (pars.size() >= 3) u.allowance = u.max_get_bps = atoi(pars[2].c_str()); else u.allowance = u.max_get_bps = default_max_get_bps; u.last_get_message = 0.0; if (pars.size() >= 4) u.allow_rw = pars[3].compare("yes") == 0; else u.allow_rw = true; pthread_check(pthread_mutex_init(&u.lck, &global_mutex_attr), "pthread_mutex_init"); std::string username = pars[0]; u.username = username; if (username.length() == 0 || u.password.length() == 0) error_exit("%s: username/password cannot be empty at line %d (%s)", filename.c_str(), line_nr, line.c_str()); (*user_map)[username] = u; } fh.close(); } user_t *users::find_user(std::string username) { std::map::iterator it = user_map -> find(username); if (it == user_map -> end()) { dolog(LOG_WARNING, "User %s not known", username.c_str()); return NULL; } return &it -> second; } bool users::get_password(std::string username, std::string & password) { password.assign("DEFINITELY WRONG PASSWORd"); list_rlock(); user_t *u = find_user(username); if (u) password.assign(u -> password); list_runlock(); return u ? true : false; } // http://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm int users::calc_max_allowance(std::string username, double now, int n_requested) { list_rlock(); int n = -1; user_t *u = find_user(username); if (u) { my_mutex_lock(&u -> lck); double rate = u -> max_get_bps; // unit: messages double per = 1.0; // unit: seconds double allowance = u -> allowance; // unit: messages double last_check = u -> last_get_message; // floating-point, e.g. usec accuracy. Unit: seconds double time_passed = now - last_check; allowance += time_passed * (rate / per); if (allowance > rate) allowance = rate; // throttle if (allowance < 8.0) // 8 bits in a byte n = 0; else n = std::min(n_requested, int(allowance)); u -> allowance = allowance; } return n; } bool users::use_allowance(std::string username, int n) { user_t *u = find_user(username); if (u) { u -> allowance -= n; u -> last_get_message = get_ts(); my_mutex_unlock(&u -> lck); } list_runlock(); return u ? true : false; } bool users::cancel_allowance(std::string username) { user_t *u = find_user(username); if (u) my_mutex_unlock(&u -> lck); list_runlock(); return u ? true : false; } std::vector users::get_users() { std::vector list; std::map::iterator it = user_map -> begin(); list_rlock(); for(;it != user_map -> end(); it++) list.push_back(it -> first); list_runlock(); return list; } double users::get_last_login(std::string username) { double rc = 0.0; list_rlock(); user_t *u = find_user(username); if (u) rc = u -> last_logon; list_runlock(); return rc; } void users::set_last_login(std::string username, double when_ts) { list_rlock(); user_t *u = find_user(username); if (u) u -> last_logon = when_ts; list_runlock(); } user_t *users::find_and_lock_user(std::string username) { list_rlock(); user_t *u = find_user(username); if (!u) u = &dummy_user; my_mutex_lock(&u -> lck); return u; } void users::unlock_user(user_t *u) { my_mutex_unlock(&u -> lck); list_runlock(); } // ***** user statistics ***** void users::inc_disconnects(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_disconnects(); unlock_user(u); } } void users::inc_timeouts(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_timeouts(); unlock_user(u); } } void users::inc_n_times_empty(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_n_times_empty(); unlock_user(u); } } void users::inc_n_times_quota(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_n_times_quota(); unlock_user(u); } } void users::inc_n_times_full(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_n_times_full(); unlock_user(u); } } void users::inc_msg_cnt(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_msg_cnt(); unlock_user(u); } } void users::inc_submit_while_full(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_submit_while_full(); unlock_user(u); } } void users::inc_network_error(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_network_error(); unlock_user(u); } } void users::inc_protocol_error(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_protocol_error(); unlock_user(u); } } void users::inc_misc_errors(std::string username) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> inc_misc_errors(); unlock_user(u); } } void users::track_sents(std::string username, int cur_n_bits) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> track_sents(cur_n_bits); unlock_user(u); } } void users::track_recvs(std::string username, int n_bits_added, int n_bits_added_in) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> track_recvs(n_bits_added, n_bits_added_in); unlock_user(u); } } void users::register_msg(std::string username, bool is_put) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> register_msg(is_put); unlock_user(u); } } int users::get_reset_bps_cur(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_reset_bps_cur(); unlock_user(u); } return rc; } int users::get_msg_cnt(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_msg_cnt(); unlock_user(u); } return rc; } int users::get_disconnects(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_disconnects(); unlock_user(u); } return rc; } int users::get_times_empty(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_times_empty(); unlock_user(u); } return rc; } int users::get_times_full(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_times_full(); unlock_user(u); } return rc; } int users::get_times_quota(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_times_quota(); unlock_user(u); } return rc; } int users::get_submit_while_full(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_submit_while_full(); unlock_user(u); } return rc; } int users::get_network_error(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_network_error(); unlock_user(u); } return rc; } int users::get_protocol_error(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_protocol_error(); unlock_user(u); } return rc; } int users::get_misc_errors(std::string username) { int rc = -1; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_misc_errors(); unlock_user(u); } return rc; } void users::get_recvs(std::string username, long long int *total_bits, int *n_reqs, long long int *total_bits_in) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> get_recvs(total_bits, n_reqs, total_bits_in); unlock_user(u); } } void users::get_sents(std::string username, long long int *total_bits, int *n_sents) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> get_sents(total_bits, n_sents); unlock_user(u); } } double users::get_last_msg_ts(std::string username) { double rc = -1.0; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_last_msg_ts(); unlock_user(u); } return rc; } double users::get_last_put_msg_ts(std::string username) { double rc = -1.0; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_last_put_msg_ts(); unlock_user(u); } return rc; } double users::get_last_get_msg_ts(std::string username) { double rc = -1.0; user_t *u = find_and_lock_user(username); if (u) { rc = u -> stats_user() -> get_last_get_msg_ts(); unlock_user(u); } return rc; } void users::get_sent_avg_sd(std::string username, double *avg, double *sd) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> get_sent_avg_sd(avg, sd); unlock_user(u); } } void users::get_recv_avg_sd(std::string username, double *avg, double *sd) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> get_recv_avg_sd(avg, sd); unlock_user(u); } } void users::get_recv_in_avg_sd(std::string username, double *avg, double *sd) { user_t *u = find_and_lock_user(username); if (u) { u -> stats_user() -> get_recv_in_avg_sd(avg, sd); unlock_user(u); } } bool users::get_is_rw(const std::string & username) { bool allow = false; user_t *u = find_and_lock_user(username); if (u) { allow = u -> allow_rw; unlock_user(u); } return allow; } entropybroker-2.9/users.h000066400000000000000000000054271305163522000156100ustar00rootroot00000000000000class user_t { public: pthread_mutex_t lck; std::string username, password; int max_get_bps; statistics_user stats; statistics *stats_user() { return &stats; } double last_get_message, allowance; double last_logon; bool allow_rw; }; class users { private: std::string filename; int default_max_get_bps; std::map *user_map; pthread_rwlock_t rwlck; user_t dummy_user; void list_wlock(); void list_wunlock(); void list_rlock(); void list_runlock(); void load_usermap(); user_t *find_user(std::string username); public: users(std::string filename, int default_max_get_bps); ~users(); void reload(); bool get_password(std::string username, std::string & password); int calc_max_allowance(std::string username, double now, int n_requested); bool use_allowance(std::string username, int n); bool cancel_allowance(std::string username); user_t *find_and_lock_user(std::string username); void unlock_user(user_t *u); std::vector get_users(); void set_last_login(std::string username, double when_ts); double get_last_login(std::string username); // user statistics void register_msg(std::string username, bool is_put); void inc_disconnects(std::string username); void inc_timeouts(std::string username); void inc_n_times_empty(std::string username); void inc_n_times_quota(std::string username); void inc_n_times_full(std::string username); void inc_msg_cnt(std::string username); void inc_submit_while_full(std::string username); void inc_network_error(std::string username); void inc_protocol_error(std::string username); void inc_misc_errors(std::string username); void track_sents(std::string username, int cur_n_bits); void track_recvs(std::string username, int n_bits_added, int n_bits_added_in); int get_reset_bps_cur(std::string username); int get_msg_cnt(std::string username); int get_disconnects(std::string username); int get_times_empty(std::string username); int get_times_full(std::string username); int get_times_quota(std::string username); int get_submit_while_full(std::string username); int get_network_error(std::string username); int get_protocol_error(std::string username); int get_misc_errors(std::string username); void get_recvs(std::string username, long long int *total_bits, int *n_reqs, long long int *total_bits_in); void get_sents(std::string username, long long int *total_bits, int *n_sents); double get_last_msg_ts(std::string username); double get_last_put_msg_ts(std::string username); double get_last_get_msg_ts(std::string username); void get_sent_avg_sd(std::string username, double *avg, double *sd); void get_recv_avg_sd(std::string username, double *avg, double *sd); void get_recv_in_avg_sd(std::string username, double *avg, double *sd); bool get_is_rw(const std::string & username); }; entropybroker-2.9/users.txt000066400000000000000000000001341305163522000161660ustar00rootroot00000000000000joe_user|my_password1234123492348|3072 folkert|test|2048 another user|some password bla|blo entropybroker-2.9/utils.cpp000066400000000000000000000416421305163522000161410ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef linux #include #endif #include "defines.h" #include "error.h" #include "utils.h" #include "log.h" #include "kernel_prng_rw.h" #include "my_pty.h" #include "encrypt_stream.h" #include "hasher.h" #include "protocol.h" #define MAX_LRAND48_GETS 250 pthread_mutexattr_t global_mutex_attr; long double get_ts_ns() { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == -1) error_exit("clock_gettime() failed"); // start time is removed to allow more bits 'behind the dot' return (long double)(ts.tv_sec) + (long double)(ts.tv_nsec) / 1000000000.0; } double get_ts() { struct timeval ts; if (gettimeofday(&ts, NULL) == -1) error_exit("gettimeofday failed"); return double(ts.tv_sec) + double(ts.tv_usec) / 1000000.0; } int READ(int fd, char *whereto, size_t len, bool *do_exit) { ssize_t cnt=0; while(len>0) { ssize_t rc; rc = read(fd, whereto, len); if (rc == -1) { if (do_exit && *do_exit) return -1; if (errno != EINTR && errno != EINPROGRESS && errno != EAGAIN) return -1; } else if (rc == 0) { break; } else { whereto += rc; len -= rc; cnt += rc; } } return cnt; } int READ(int fd, unsigned char *whereto, size_t len, bool *do_exit) { return READ(fd, reinterpret_cast(whereto), len, do_exit); } int READ_TO(int fd, char *whereto, size_t len, double to, bool *do_exit) { double end_ts = get_ts() + to; ssize_t cnt=0; while(len>0) { pollfd fds[1]; double now_ts = get_ts(); double time_left = end_ts - now_ts; ssize_t rc; if (time_left <= 0.0) return -1; fds[0].fd = fd; fds[0].events = POLLIN; int tv = time_left * 1000.0; rc = poll(fds, 1, tv); if (rc == -1) { if (do_exit && *do_exit) return -1; if (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN) continue; return -1; } else if (rc == 0) { return 0; } if (fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) { return -1; } if (fds[0].revents & POLLIN) { rc = read(fd, whereto, len); if (rc == -1) { if (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN) continue; return -1; } else if (rc == 0) { return -1; } whereto += rc; len -= rc; cnt += rc; } } return cnt; } int READ_TO(int fd, unsigned char *whereto, size_t len, double to, bool *do_exit) { return READ_TO(fd, reinterpret_cast(whereto), len, to, do_exit); } int WRITE(int fd, const char *whereto, size_t len, bool *do_exit) { ssize_t cnt=0; while(len>0) { ssize_t rc; rc = write(fd, whereto, len); if (rc == -1) { if (do_exit && *do_exit) return -1; if (errno != EINTR && errno != EINPROGRESS && errno != EAGAIN) return -1; } else if (rc == 0) { return -1; } else { whereto += rc; len -= rc; cnt += rc; } } return cnt; } int WRITE(int fd, const unsigned char *whereto, size_t len, bool *do_exit) { return WRITE(fd, reinterpret_cast(whereto), len, do_exit); } int WRITE_TO(int fd, const char *whereto, size_t len, double to, bool *do_exit) { double end_ts = get_ts() + to; ssize_t cnt=0; while(len>0) { pollfd fds[1]; double now_ts = get_ts(); double time_left = end_ts - now_ts; ssize_t rc; if (time_left <= 0.0) return -1; fds[0].fd = fd; fds[0].events = POLLOUT; int tv = time_left * 1000.0; rc = poll(fds, 1, tv); if (rc == -1) { if (do_exit && *do_exit) return -1; if (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN) continue; return -1; } else if (rc == 0) { return -1; } if (fds[0].revents & POLLOUT) // should always evaluate to true at this point { rc = write(fd, whereto, len); if (rc == -1) { if (errno != EINTR && errno != EINPROGRESS && errno != EAGAIN) return -1; } else if (rc == 0) { return -1; } else { whereto += rc; len -= rc; cnt += rc; } } } return cnt; } int WRITE_TO(int fd, const unsigned char *whereto, size_t len, double to, bool *do_exit) { return WRITE_TO(fd, reinterpret_cast(whereto), len, to, do_exit); } int connect_to(const char *host, int portnr) { struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // For wildcard IP address hints.ai_protocol = 0; // Any protocol hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; char portnr_str[8]; snprintf(portnr_str, sizeof portnr_str, "%d", portnr); struct addrinfo *result; int rc = getaddrinfo(host, portnr_str, &hints, &result); if (rc != 0) error_exit("Problem resolving %s: %s\n", host, gai_strerror(rc)); for(struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) { int fd = socket(rp -> ai_family, rp -> ai_socktype, rp -> ai_protocol); if (fd == -1) continue; if (connect(fd, rp -> ai_addr, rp -> ai_addrlen) == 0) { freeaddrinfo(result); return fd; } close(fd); } freeaddrinfo(result); return -1; } void disable_nagle(int fd) { int disable = 1; // EBADF might happen if a connection was closed just before this call if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&disable), sizeof disable) == -1 && errno != EBADF) error_exit("setsockopt(IPPROTO_TCP, TCP_NODELAY) failed (fd: %d)", fd); } void enable_tcp_keepalive(int fd) { int keep_alive = 1; // EBADF might happen if a connection was closed just before this call if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast(&keep_alive), sizeof keep_alive) == -1 && errno != EBADF) error_exit("problem setting KEEPALIVE (fd: %d)", fd); } void check_rand_state() { static int n_random_retrieved = 0; if (--n_random_retrieved < 0) { unsigned short seed16v[3]; kernel_rng_read_non_blocking(reinterpret_cast(seed16v), sizeof seed16v); seed48(seed16v); n_random_retrieved = MAX_LRAND48_GETS; } } double mydrand() { check_rand_state(); return drand48(); } int myrand() { check_rand_state(); return lrand48(); } int myrand(int max) { check_rand_state(); return int(drand48() * double(max)); } void write_pid(const char *file) { FILE *fh = fopen(file, "w"); if (!fh) error_exit("Failed to write PID-file %s", file); fprintf(fh, "%d\n", getpid()); fclose(fh); } void close_fds() { for(int fd=3; fd<50; fd++) close(fd); } void start_process(const char *shell, const char *cmd, int *fd, pid_t *pid) { int fd_slave; /* allocate pseudo-tty & fork*/ *pid = get_pty_and_fork(fd, &fd_slave); if (*pid == -1) error_exit("Cannot fork and allocate pty"); /* child? */ if (*pid == 0) { setsid(); /* reset signal handler for SIGTERM */ signal(SIGTERM, SIG_DFL); /* connect slave-fd to stdin/out/err */ close(0); close(1); close(2); dup(fd_slave); dup(fd_slave); dup(fd_slave); close_fds(); /* start process */ if (-1 == execlp(shell, shell, "-c", cmd, NULL)) error_exit("cannot execlp(%s -c '%s')", shell, cmd); exit(1); } close(fd_slave); } void no_core() { #ifndef _DEBUG struct rlimit rlim = { 0, 0 }; if (setrlimit(RLIMIT_CORE, &rlim) == -1) error_exit("setrlimit(RLIMIT_CORE) failed"); #endif } void lock_mem(void *p, int size) { static bool notified_err = false; if (mlock(p, size) == -1) { if (!notified_err) { dolog(LOG_WARNING, "mlock failed"); notified_err = true; } } } void unlock_mem(void *p, int size) { static bool notified_err = false; if (munlock(p, size) == -1) { if (!notified_err) { dolog(LOG_CRIT, "mlock failed"); notified_err = true; } } } void hexdump(unsigned char *in, int n) { for(int index=0; index 15) { dolog(LOG_DEBUG, "Truncating thread name '%s' to 16 characters", dummy); dummy[16] = 0x00; } // ignore pthread errors: at least under helgrind this would always fail int rc = pthread_setname_np(pthread_self(), dummy); if (rc) dolog(LOG_WARNING, "set_thread_name(%s) failed: %s (%d)", dummy, strerror(rc), rc); free(dummy); #endif } // *BSD need a different implemenation for this std::string get_thread_name(pthread_t *thread) { //#ifdef linux #if 0 // on ubuntu 10.04.4 this does not work (pthread_setname_np unknown) char buffer[4096]; pthread_check(pthread_getname_np(*thread, buffer, sizeof buffer), "pthread_getname_np"); return std::string(buffer); #endif return std::string("?"); } std::string get_current_thread_name() { pthread_t tid = pthread_self(); return get_thread_name(&tid); } void my_yield() { // sched_yield pthread_check(pthread_yield(), "pthread_yield"); } bool file_exist(const char *file) { struct stat st; if (stat(file, &st) == -1) { if (errno == ENOENT) return false; error_exit("stat on %s failed", file); } return true; } void split_string(const char *in, const char *split, char ***out, int *n_out) { int split_len = strlen(split); char *copy_in = strdup(in), *dummy = copy_in; for(;;) { char *next = NULL; (*n_out)++; *out = reinterpret_cast(realloc(*out, *n_out * sizeof(char *))); next = strstr(copy_in, split); if (!next) { (*out)[*n_out - 1] = strdup(copy_in); break; } *next = 0x00; (*out)[*n_out - 1] = strdup(copy_in); copy_in = next + split_len; } free(dummy); } std::vector split_string(std::string in, std::string split) { char **out = NULL; int n_out = 0; split_string(in.c_str(), split.c_str(), &out, &n_out); std::vector list_out; for(int index=0; index> 24) & 255; out[1] = (value >> 16) & 255; out[2] = (value >> 8) & 255; out[3] = (value ) & 255; } bool send_uint(int fd, unsigned int value, double to) { unsigned char buffer[4]; uint_to_uchar(value, buffer); if (WRITE_TO(fd, buffer, 4, to) != 4) return false; return true; } #ifdef linux pid_t gettid() { pid_t tid = (pid_t) syscall (SYS_gettid); return tid; } #else #define gettid() 0 #endif void *malloc_locked(size_t n) { void *p = malloc(n); if (p) lock_mem(p, n); return p; } void free_locked(void *p, size_t n) { if (p) { memset(p, 0x00, n); unlock_mem(p, n); } free(p); } std::string format(const char *fmt, ...) { char *buffer = NULL; va_list ap; va_start(ap, fmt); (void)vasprintf(&buffer, fmt, ap); va_end(ap); std::string result = buffer; free(buffer); return result; } std::string time_to_str(time_t t) { if (t == 0) return "n/a"; struct tm *tm = localtime(&t); char time_buffer[128]; strftime(time_buffer, sizeof time_buffer, "%a, %d %b %Y %T %z", tm); return std::string(time_buffer); } bool get_bool(FILE *fh, bool *value) { int rc = fgetc(fh); if (rc < 0) return false; if (rc) *value = true; else *value = false; return true; } bool get_int(FILE *fh, int *value) { unsigned char buffer[4]; if (fread((char *)buffer, 4, 1, fh) != 1) return false; *value = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; return true; } // assuming 2x 32bit ints and 64bit long long int bool get_long_long_int(FILE *fh, long long int *value) { unsigned int i1, i2; if (!get_int(fh, (int *)&i1)) return false; if (!get_int(fh, (int *)&i2)) return false; *value = ((long long int)i1 << 32) + i2; return true; } void put_bool(FILE *fh, bool value) { fputc(value ? 1 : 0, fh); } void put_int(FILE *fh, int value) { unsigned char buffer[4]; buffer[0] = (value >> 24) & 255; buffer[1] = (value >> 16) & 255; buffer[2] = (value >> 8) & 255; buffer[3] = (value ) & 255; if (fwrite((char *)buffer, 4, 1, fh) != 1) error_exit("problem writing to data_store_int dump-file"); } void put_long_long_int(FILE *fh, long long int value) { put_int(fh, value >> 32); put_int(fh, value & 0xffffffff); } int start_listen(const char *adapter, int portnr, int listen_queue_size) { int fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd == -1) error_exit("failed creating socket"); #ifdef TCP_TFO int qlen = listen_queue_size; if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)) == -1) error_exit("Setting TCP_FASTOPEN on server socket failed"); #endif int reuse_addr = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reuse_addr), sizeof reuse_addr) == -1) error_exit("setsockopt(SO_REUSEADDR) failed"); struct sockaddr_in6 server_addr; int server_addr_len = sizeof server_addr; memset(reinterpret_cast(&server_addr), 0x00, server_addr_len); server_addr.sin6_family = AF_INET6; server_addr.sin6_port = htons(portnr); if (!adapter || strcmp(adapter, "0.0.0.0") == 0) server_addr.sin6_addr = in6addr_any; else if (inet_pton(AF_INET6, adapter, &server_addr.sin6_addr) == 0) { fprintf(stderr, "\n"); fprintf(stderr, " * inet_pton(%s) failed: %s\n", adapter, strerror(errno)); fprintf(stderr, " * If you're trying to use an IPv4 address (e.g. 192.168.0.1 or so)\n"); fprintf(stderr, " * then do not forget to place ::FFFF: in front of the address,\n"); fprintf(stderr, " * e.g.: ::FFFF:192.168.0.1\n\n"); error_exit("listen socket initialisation failure: did you configure a correct listen adapter? (run with -n for details)"); } if (bind(fd, (struct sockaddr *)&server_addr, server_addr_len) == -1) error_exit("bind([%s]:%d) failed", adapter, portnr); if (listen(fd, listen_queue_size) == -1) error_exit("listen(%d) failed", listen_queue_size); return fd; } entropybroker-2.9/utils.h000066400000000000000000000053741305163522000156100ustar00rootroot00000000000000extern pthread_mutexattr_t global_mutex_attr; double get_ts(void); long double get_ts_ns(void); int READ(int fd, char *whereto, size_t len, bool *do_exit = NULL); int READ(int fd, unsigned char *whereto, size_t len, bool *do_exit = NULL); int READ_TO(int fd, char *whereto, size_t len, double to, bool *do_exit = NULL); int READ_TO(int fd, unsigned char *whereto, size_t len, double to, bool *do_exit = NULL); int WRITE(int fd, const char *whereto, size_t len, bool *do_exit = NULL); int WRITE(int fd, const unsigned char *whereto, size_t len, bool *do_exit = NULL); int WRITE_TO(int fd, const char *whereto, size_t len, double to, bool *do_exit = NULL); int WRITE_TO(int fd, const unsigned char *whereto, size_t len, double to, bool *do_exit = NULL); int start_listen(const char *adapter, int portnr, int listen_queue_size); int connect_to(const char *host, int portnr); void disable_nagle(int fd); void enable_tcp_keepalive(int fd); double mydrand(); int myrand(); int myrand(int max); void write_pid(const char *file); void start_process(const char *shell, const char *cmd, int *fd, pid_t *pid); void no_core(); void lock_mem(void *p, int size); void unlock_mem(void *p, int size); void hexdump(unsigned char *in, int n); void split_resource_location(std::string in, std::string & host, int & port); void set_fd_nonblocking(int fd); std::string get_endpoint_name(int fd); void my_mutex_lock(pthread_mutex_t *mutex); void my_mutex_unlock(pthread_mutex_t *mutex); void set_thread_name(std::string name); std::string get_thread_name(pthread_t *thread); std::string get_current_thread_name(); void my_yield(); void pthread_check(int rc, const char *name); void pthread_check(int rc, const char *name, int ok[]); bool file_exist(const char *file); void split_string(const char *in, const char *split, char ***out, int *n_out); std::vector split_string(std::string in, std::string split); unsigned int uchar_to_uint(unsigned char *in); bool recv_uint(int fd, unsigned int *value, double to); void uint_to_uchar(unsigned int value, unsigned char *out); bool send_uint(int fd, unsigned int value, double to); void *malloc_locked(size_t n); void free_locked(void *p, size_t n); std::string format(const char *fmt, ...); int get_local_port(int fd); std::string time_to_str(time_t t); bool get_bool(FILE *fh, bool *value); bool get_int(FILE *fh, int *value); bool get_long_long_int(FILE *fh, long long int *value); void put_bool(FILE *fh, bool value); void put_int(FILE *fh, int value); void put_long_long_int(FILE *fh, long long int value); void my_Assert(bool flag, int line, const char *file); #define my_assert(x) my_Assert(x, __LINE__, __FILE__) void my_Assert2(bool flag, int line, const char *file, int debug_value); #define my_assert2(x, y) my_Assert2(x, __LINE__, __FILE__, y) pid_t gettid(); entropybroker-2.9/valgrind.sh000077500000000000000000000003251305163522000164330ustar00rootroot00000000000000#! /bin/sh valgrind --show-reachable=yes --leak-check=full --read-var-info=yes --track-origins=yes --malloc-fill=93 --free-fill=b9 --error-limit=no ./entropy_broker -c ./entropy_broker.conf -n -L 255 2> err8.log entropybroker-2.9/version000066400000000000000000000000141305163522000156710ustar00rootroot00000000000000VERSION=2.8 entropybroker-2.9/web/000077500000000000000000000000001305163522000150435ustar00rootroot00000000000000entropybroker-2.9/web/404.html000066400000000000000000000000061305163522000162340ustar00rootroot000000000000004 0 4 entropybroker-2.9/web/favicon.ico000066400000000000000000000410761305163522000171740ustar00rootroot00000000000000@@ (B(@ NN//LL++11JJBBGG<<??II@@hhaallhhvvWW{{ggoommoojjcc}}eennssww||uu{{}}nn]]xxttttxxUUwwww~~nnffppqquuuu``ff||ll\\ddddWWnnddvvaakkuuttggzzjjxx{{rrggxxllxx||~~hh~~kk}}AA::5544mmSS66<<6611VVOOwwgggyyynnn|||iiiooo}}}mmm}}}dddttt}}}[[[bbbooowwwppp|||~~~wwwTTTqqq~~~mmm~~~bbbuuu^^^~~~yyy___sss|||?w|Iooouuu\\\www}}}ppp~~~~~~\\\lll44rr}}mmdd==;r\yo~myWeeeoootttooo~~~|||rrrlllcccDDii||zzxxkkII5lbm?~~~jjjRRRsssppp~~~uuueeeWWssyyss||ssSSH@oa{sa>mmm]]]eee{{{uuuyyy}}}tttsssgggTTUUllvvssddpp]][Xj}u`~I```yyy```ccczzzgggqqqqqqjjjCCwwBByyqq__@@8oyomLwooo}}}cccVVVwwwzzznnnwTTttxxhhhhwwll>>=|kndKwrrrzzzpppZZZw::zzqqooyypp~~oo}}VV//+s|vn|k/{{{{{{sss}}}nnnlllqqqccc22llllll~~ttqqII;iraugYiiimmm\\\dddiiikkkrrrbbbkkk''nn{{zz||\\**FowYlMccc~~~]]]xxxhhh___bbbvvv~~~LLL::llxxzzrrKKxxbbMyTwa=nnnwwwYYYwwwsss~~~99uuhhvvuuAAIcwmyr2gggeeeqqquuuvvv22uuttll}}``yyyyyy___}}}sss```bbbkkkeeelllccc}}}~~~{{{rrr\\\bbbcccxxx{{{{{{qqqwwwZZZuuuyyywwwSSSnnn|||}}}rrrxxxQQQqqq}}}qqqwwHH==22``))EEBBJJ<<00EEjjZZrrffXXpprr{{xxccddzzvv}}KKrrzznnzz``qqnn~~yyttkk||ddrrYYvv]]vvzzffaaggggqqqqyykkzzuukkrrttyyrrttwwTTgg~~rruumm||vvllRR__KKLL55MM RR77AA22AA}8xxxxx88xxxxx8}entropybroker-2.9/web/logfiles.png000066400000000000000000000047401305163522000173620ustar00rootroot00000000000000PNG  IHDR@@`UsRGB IDATh}\y߽3;;6@H:$4|$R5mZ)!8IK[ RQ6*R6P)$![L ^{wݵq׻wg=cήwֳЪGwyy?=|Do?RZ[+8^^~WƯoMY~+ӎBO koxeCE jw< *Kyiagy$DrI»↦,HEƲ8aHUqIERuOg )ѴN0A,ԦsY)*ΑXQ,%{(q': "A,Ԑ@?V;<__{Sb9~}2<)9L!Ų$bm^ky=갿ӣMOTO )VHCF7̐/zREK~gf^QUEM>,J$3Qa}~>-lqXK==J*^cfՁ3byV몂JVr*++ID^%.iV& /k2rY1!=XւfXJj9dij|c 5kJt='?HUg܇ZFYsڴ\'PI*ī1E A #rYXMPH*TE|EPUfe24lq nuNWT0G (9c[TcF1Ўȵ:<۷= tT*u"};}!B˥H-6HNi~ I֐T<'d0(\JyG}aU7:MxkYQF "EFTk-s K-pIQ'ÞyIOkI}6ey/(r>qg~Yh_31aq'vW7 3LS?)>$Qg6bH K>93z=H{J^_eG$RkvT^2'9=oY&gyai򕵧ͧ[֦f3Ef19?,KY;]4{uKf-P'Y?sae޵oM7:'3j;o+}o]w~7,{['B[\+{;Ay!,*IENDB`entropybroker-2.9/web/logo-bw.png000066400000000000000000000034411305163522000171210ustar00rootroot00000000000000PNG  IHDR@@`UsRGBIDATho\go#Mh`!@]* $$KVRWPT TI4Mډ=c{3se=N[T;e;ͽ=993n')G<ekg#fpՔ؜sksew]H'a7Lkkύ=5R7.(;aŊ{=`̐ktj=1@SW,͓E]@"JdGpRSǿn+4qUm@";;:Bݻ)vY gΣYvoV&"XA"n &dLUÎo8ᤊ#.;dDmT[WQWK^EK(-CDRP,"]F{Ь|wZ8oqXќTK(kCcIJD$b!a/my͂Q7L:aކ5]u!75.璸"E]9EM5eC}qG2ͺBołԐL~}"kՍ1s~/YsR B#n Z}, wKD m Б9WvȲuB^N>i]u4hj]u$:. r+aw&A*)kJFY$ bD٪HC"DR]H VP [Rq}B"׌SxH]% e Ygdrb-X▖0w܏DVoUpĂ)g9E/o[?wF&TUs;'َ7.+q@|EѢ ,z{mǛV7㵏$}M!ˆV2QW2E3'+Q*ej61WUtch9]?}Q)L|x3^߳dJ8}Ot}> T%:LxsAj7T6$,{?qkںZ@Q ]"UgeNђ)&zX$oRlxPq Jf Ӯ U[4.RȸX,:oNņw\UeEj{j!_tPbF%t%o NϢZ1#JÃ2LYvrE"a3&ie7(\,/y-S::Ѫ_\~>>_}']IENDB`entropybroker-2.9/web/logo.png000066400000000000000000000241411305163522000165130ustar00rootroot00000000000000PNG  IHDRA>sRGB(IDATxw]U.D<( !@5;B' % %P!z PCE@PQE9Q1rŹr^{90oӭ[s4Gs4Gs4Gs4Gs4Gs4Gs4Gs4s̘iio?0 q9^1|xGW]qn]q-F~xԩ^Z;䐈##:('" tӈ3h19f2W__1iRGsvEv'Gyf9w؈=8昈a"&LXuՈ#ڪL榛"6ڨv=⨣ʤz?i 7G]"f5bڴ0Cmfx衈㏏w= C^f'K.Xw݈f3?. umݻG<`9c#m1efeݶ07ѧOk?8^~lmErEw `:0 P!`DLR$S 1qGQ$y,[nqy'L/1J+EjʇVCv}7_/^&K(LBlT /k%QzkNN 9ON j[4Cȏm7޸,,:gz% H,DnlBgc0/L%'9//qHHKp3KL[0@W^FTD mY@󐪹.XG3Кx0Y~(Q'2WH:qKCb;|W Jac%-fYH&`O>)DfL2Ȗ\k=Vx2֪Rlo/l00c|RG#9FOM|yӀih `Ls4i0ň_t4{:@Wm +FsLs1O<oF\wuO>d 6,=|]wkFlmq1lcM74b_?>|{w\p1dȐxO[/7pCs1Gsfe e]6>X~gn1t'OfzƤ92OI_}|qG-]vY㎱{駟~ţ>o\rI7~g %&qĉ΋f)6x8묳p [gubW_=ƌ+Br)_w./c{,>,#mY~衇k+"Ǝ'XACRBF;Ǹqk~㪫m&N=Tn-4 +LG`?hР[?>m]-"y.({,s5ĕW^lIuQRKeV0p@sGƞ{9MxUW]5l!K/tfz*{i3wwq[`x z';' /{ٔb&l0I>3 LeqI'e9Z+1s7tSfNe4V[mA]Efm &j^$kf6Ɍ1y2^4:R: zA({#b~{p/d}:_=O>Ŝ0kv~<0"I_' Xi20`ݻw"?q?Yr%=yQFef(>:3@09ſP޽=z"$S%&Ddތ5%5VJ2 +M~K|i2d~gv=I~Hx?avs=7]v%@{hg 7ՄTSݚT'Z𼆜0ئ 0 L.`0v7#nK5 K6Luv* :#հT9&Jc:OOmRu`McdWY+IUqsǧqK,Ze*L+:iƷ3J2&Nza^n@g0&P(LHf9r.y6:X<vU?C=%8>5@.`OFZ6S**-j`*K(010] 3jd*ީ.N59&w`V S"6Oc*;Q {N4ި254ֱK=*o{e@ dg0"o+J2FfW_rؒ$j9}eq!&+>{f ~C1D?_EhicSƥZ>ϱzKSݟTpoMR]jT[Z- jTU.keO4&1kWƠ4Hc4Y bw4Ml}Ҹm,=wXl28̒ (̯# /pfp>6T\9rX _# 7|s6Oh2 3vc7SaTRq*fljlί ʾ38 ;3U*3{4`Bqst]RMqUrOU#i,\ILZM0{%gLTctuIӐ0/r>0^{-]-S,C y[OuX*GaHy*ϜjTXjR* TSR-jT+3L5> Ӹ2t;o|;jϥ^!hiI2&d`S 05\'n$$b1soVӁ;Lf" i0<CFnH/&FW*2XdT$tERy L"+]u`zUЌiH~MH~n_yz9* Dդ;f?6`l3 +3O ~ r8V[-3LkxQYdlx݃O( Iu',|z:L/@碋. rY50HCT <62O#n<{*2tP*6/T.L,œ ~"Otm+S<\yUPSej4jzoR6`sJCȍIwMGB\#ݘh}%Ń`*0S5_!P[ok[nxvTӺfR})2CNNP*&0}RIC .r\@Of_6Qyzת`Xz5YӘX~~饗os=1,ҋ4֓ ~>ҀȎfEiќq}ףR30_Ӓ)TLWH]0`@y;SOYcZcr|Z*#a ӷvuϫ4ա;+z &lo݌xl'qHSYa <1L!z m[FZ?X 뮻n!0-W<ј*ߓ81&}6 4z:1>ajy}* .0ѫM^R?ʲd7, C>VfvǺcWI"-^ֵauL}*kI,u1Qx2FU@}-",bM(dLz\Ѧ~$иc]2Ƨ `[0[}`偀vbTz'4uTd?&:t-`SIRR)tz}^-#orf\W2u_eիSfl]&V}=0뷪SgJzfo&TJ2q$ M<  "*[ZlY<$6KDί TRfrJ=ŃMEN|oyery2pM%Z ΤG0@.1N qk#{,*Lz >ջQۮJ5=]6e"F>bXoOY Mâi0p'=$or5qL [ 7XvȈ倍RgcRT(Y>gT4d TH4g=oa 3z]2.L'T#{f+,o[̀y+/3}%]ӻ 扛:ujJ&&bh92 w2QڽLEd|yL=CrSy`f|*;D6dЀo!C߸fLM5sTiYYՐyf׺q^js墨}Yʹ Ip`Lk}IԖdL>66$Ih0^ V:_#I PH06/xҗɫ]°X=R< fjT֋trfsJ曩1֒NeA:ygj.̄Oej˿gL?t[O,.̪9ӘG*9cS[ ֪݋* ^hj9k?gtۀ@evh5L,_bQһ^"E 40L06&*%o܃Y{teJL"7k0$7d/񕧑tuq/HeI@4LYhn j JX]0~]d$#jQ[UXhDW 4(oj0}2C b4Hw93K` HAR$ 9$h119Xk@*[\NFIRQDhl1Ƿ 8K*\f]+5kied[e鎚nkFWV22ƨ 5N㽺)mmT6` 3̐ɇ}/3}b%jr|ToeɉW$k2О"R[Wta,m~_y?f¸j1-IT3OemN:^% 2Q֏!_,u0WoBUTsZ]\eWclטګRFn0<fж'H7Tpb3sgZfyD؆%o, kG]^X,?Kַrb} fT"u#C_1rjRfH-#/VWݺy[ E}|DMQO r걆5$o iI mM2iy!fu@!,- o}JZcwHlJT=_;]fvc.F*V,&WxtcDj2#1<5sYmS^7N=\g`]lrt+R5Uɽj3NTgy@E֒( `,69`i@Dj_%!I xKW$<>`ZGj}ջD5ٚtgh1oi3lp}1HkV~@gf_k8JHƇw0>/aMaiHGaOĒW_Eڑl22R% y'>ԒN73`ܛa[,Z)FXd6&`_z~I !kXW~W`imP'1{) #yҁ%In>?"! $oz̬_!.-I0> V1ҥ<, >u@tkMݵH֧n}NK5@b!2Wo|yDL\TXc-6D82$=@9 0Nf <$iX#bN%bqX@vI(Ua ni%NzI䗰Pb.3Lgv1 !|@L!z;GC_E sB6КA8;a6 `Pf: N' Ⰹd1IisX d儹+3#̼b r$Qi!?1@ V=otLiIp q 1vI&/=L*R`=/-Lgtkq7Lt[o^ `Ls4i09:+z9Gݦ_n0 `:a&#=4;# nXh! //1~|3DkeE|r"v8\>/ѷo4 )9Ԉ8唈fXr lѯ_ĤIGjaE~xGO,| #&L8N(]l0w/yȏ/8#"ƍ#j"6۬sxHv1b-"n=G+h1=(r:L6)2z* :Yv`:GE^)[v0v(C *s책U>\a #^ϟJ/eiʵG+c&S9o`ywy$릛+\1{qq I[ZhDԳg|{+m[ocoq%;\Yg0ѻwq5oH%喈-,i?,Rs#G~O/;B t`Dda˸/#0͏~T|ȒTꢋ ߾}5`V/)%EoUuz/Æq_暅q朳 8wʽV\H\ 9[7cWqVҔ Ѱss< iqɓK>XLI3>twoO$c'(qA@cW^), I#_|0o,܃*r饅5|~t|csXFCN"Z| HSh 61fL1M÷`2&>4h5O>1y~L

3!x0C l<HW|La:0)ؖ6nZz.tp`]yeRǾZS[7` ϣ\w]I9,pu-Eo8^t~1 0eW cSkLU04I<`-I2Ӵl TIWRk!o `:0O?]ø=wҌ $3#oAF,D|lD€Y к"ז%OXKFX\ck'`Y&_$=t`cH;ފ"IP<˛opXR'%) t`hLŧӘ F-IENDB`entropybroker-2.9/web/statistics.png000066400000000000000000000064711305163522000177530ustar00rootroot00000000000000PNG  IHDR@@`U IDAThݙyǿoU5}1EPj rY+ЕS>_™Sb` !R`p`&Y !VM5Q]z?}`6BXX"ᕈ쯭;3I/r]e3t>g8#{#st(XyyٛP>᪷?Ё 9*7їQv@e2!}:.2"ATͥ2X Mg]g!L0Q!dL?PәbPCK] Q" , Ds* 5׮R;(Hكd%]"AZ'SzMGdj1q'hvxA\v$so> XYi ;i,0rFO22Щ4W%ڗ4y[5,y_%aOt | OG'aTtgL6б:-$}(\Bo0R'w[wi/׎x MO֜¿8kdzFpTp0ޚ3xtQN9Vp95iM$ E~!.Lulϑg8RV)-n Ĩ 9\6X v-tUi\s[?qyEDf0^Rp-ty9,I^}%jHJ1T_eC㉵#1&R968/ygȩ<0Z`9zWmv1\Gg..l]7Ҕ_c3^[YEX =eu["1+4۵.xZmr,yn wq㧗8˖CjC Öa"Ec"Hyj6JcI+υ&հ#B\*x?OX+W,B\W2Im:-W OՠXͳ;~&QSnMq˶.@ߨ䍂vX.c4k6Nquz_߅"Zɓ|*V^ 5Im 9IT\3 -a'mj!ZUt e9&?!zϰg粺eJe!ߗ~hkHGnǶj2p;ް~<ģSss(щPqP 7yDE:VEKƶo4/ %4 !A=dYİD:MK![Rz{xy)cPF8 G itGg1Lg ^] qmŖC/{Umf/-'*g~Aha$if☮\/c h =K'A!c? RVwa]6, Q(! 0 EΚh;5;"J8)*F y-|N1 TT'BYT7zg+< J!M&vPDA $?}O(hxe/oگi6*i)ٝ i$8Цx %DtC/͞%|~EډjU-례B ؀FToÃOƯlSOџDHz chРNm[6驃775U}!sD!-ϕL^ҸU}]p9+&3a/:IoX3t-\*)Fe#e(B tҤĆŽ \Z4y57"пث JC`>= NoH5DIENDB`entropybroker-2.9/web/stylesheet.css000066400000000000000000000031261305163522000177500ustar00rootroot00000000000000body { background: #282828; border: 8px solid #585858; color: #ffffff; font: 16px/1.25 "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; margin: 0; } header, footer, section { display: block; overflow: hidden; } header { background: #282828; float: left; width: 150px; } header img { clear: both; display: block; margin: 0 0 15px 5px; } section.content { padding: 10px; min-height: 650px; } section.content h1 { background: #282828; font-size: 32px; margin: 0; padding: 30px 0 10px 10px; } section.content nav img { vertical-align: middle; } .keys { width: 200px; } .timestamp { width: 240px; } td.alignright { text-align: right; } table.fullwidth { width: 100%; } section.content nav a { background: #383838; display: block; margin: 0 0 0 0; padding: 5px; } .tablemargins { margin: 1px 1px 1px 1px; padding: 1px; } .table2 { background-color: #383838; line-height: 1.25em; } .lighttable { background-color: #585858; } .lighttable2 { background-color: #484848; } .lighttable3 { background-color: #686868; } .lighttable4 { background-color: #787878; } .darkyellow { background-color: #383828; } .darkred { background-color: #382828; } footer { text-align: right; } .adsense { background-color: #ffffff; } a:link { color: #0b9a0a } a:visited { color: #018a00 } a:active { color: #007a00 } a:hover { color: #006a00 } entropybroker-2.9/web/users.png000066400000000000000000000065751305163522000167270ustar00rootroot00000000000000PNG  IHDR@@`UsRGB 7IDAThyT՝?UZ醦i@ H˾h(ƈ1&'q$e$s&'g&'ƍ$x((&nqTYeknkyG]:0@`Su߻[{t€JaCg7N$H F/w=fM_恔HĈĤ]q,;%Ʃl>o98H$CUB];p 0 L1F565܆`Al(&qjI3q4b`bE}_<.g8=?Rj-\<覟C& H,aS{V;"@$L'%D3 Tx.-|盉"H24.SƢvƴ,И'eI@OĖE |{#OI@Ha6cJ_G|KRãB@OC2 ?=( _շ.;E`8cB42nBW>/6>>Sr~`caccca (byoNG$jQB@R"O^2 )yE+*H$e| @!(x痭5xY%6. ~jM$<,H~a4Q \JU<(F@]0Q  F6G q0,xvq_&G oz::?NJ5! Le@ Æ;PCMtӍ=H\ΧZ+ϋ댌IsZb'Ɛ@!ظdH`H C1B(\l*)e$ob& p1iF%OB84aNC$ ahybc~U?]m,5NlEDD%HV9<1$8Ma x$G}\v & &Ba#P(| L>|DV'2t>}#>9P @88 EI (O`ǃcNBTO0[hRo A i$bٽeԚ'or $l" Q $EuQb[|NP TQHd2BH3%_tA9 Gl|M5>Id̉?kἏ1K'AZj9"idJM~a-rxXđq+sA ;lqum A8!깆鴐$I\~ꂛŕnٜC ><pUbQ qcњyR!&p %t3(I0>Ѯ^V @h _LO T\K7.vK[a9́wc-8ﮋi$ou$OkX}ڻ3ۛUQE:Fa!5W;,h> %qVLuӮZJ:{g,~wgΔ(Q&=D]|w|uɫJ9rw#g9mu3bcT2$u ;ރI@γIENDB`entropybroker-2.9/web_server.cpp000066400000000000000000000133071305163522000171410ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include "error.h" #include "log.h" #include "utils.h" #include "hasher.h" #include "math.h" #include "stirrer.h" #include "random_source.h" #include "fips140.h" #include "scc.h" #include "hasher_type.h" #include "stirrer_type.h" #include "pool_crypto.h" #include "pool.h" #include "pools.h" #include "config.h" #include "encrypt_stream.h" #include "statistics.h" #include "statistics_global.h" #include "statistics_user.h" #include "users.h" #include "handle_client.h" #include "data_store_int.h" #include "data_logger.h" #include "graph.h" #include "http_request_t.h" #include "http_bundle.h" #include "http_file.h" #include "http_file_file.h" #include "http_file_root.h" #include "http_file_stats.h" #include "http_file_404.h" #include "http_file_version.h" #include "http_file_graph_data_logger.h" #include "http_file_logfile.h" #include "http_file_users.h" #include "http_server.h" #include "web_server.h" typedef struct { web_server *p_server; int fd; } http_client_t; void *start_web_server_thread_wrapper(void *p) { web_server *ws = reinterpret_cast(p); ws -> run(); return NULL; } void start_web_server(config_t *config, std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, statistics_global *ps, fips140 *pfips140, scc *pscc, data_logger *dl, users *pusers) { web_server *ws = new web_server(config, clients, clients_mutex, ppools, ps, pfips140, pscc, dl, pusers); pthread_attr_t attr; pthread_check(pthread_attr_init(&attr), "pthread_attr_init"); pthread_check(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), "pthread_attr_setdetachstate"); pthread_t thread; pthread_check(pthread_create(&thread, &attr, start_web_server_thread_wrapper, ws), "pthread_create"); } web_server::web_server(config_t *config, std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, statistics_global *ps, fips140 *pfips140, scc *pscc, data_logger *dl, users *pusers) { fd = start_listen(config -> webserver_interface.c_str(), config -> webserver_port, config -> listen_queue_size); add_object(new http_file_root()); add_object(new http_file_404()); add_object(new http_file_stats(clients, clients_mutex, ppools, ps, pfips140, pscc)); add_object(new http_file_version()); add_object(new http_file_file("/stylesheet.css", "text/css", WEB_DIR "/stylesheet.css")); add_object(new http_file_file("/favicon.ico", "image/x-ico", WEB_DIR "/favicon.ico")); add_object(new http_file_file("/logo.png", "image/png", WEB_DIR "/logo.png")); add_object(new http_file_graph_data_logger(dl, config -> graph_font)); add_object(new http_file_logfile(ps)); add_object(new http_file_file("/logo-bw.png", "image/png", WEB_DIR "/logo-bw.png")); add_object(new http_file_file("/logfiles.png", "image/png", WEB_DIR "/logfiles.png")); add_object(new http_file_file("/statistics.png", "image/png", WEB_DIR "/statistics.png")); add_object(new http_file_users(pusers)); add_object(new http_file_file("/users.png", "image/png", WEB_DIR "/users.png")); } web_server::~web_server() { if (fd != -1) close(fd); std::map::iterator it = objects.begin(); while(it != objects.end()) { delete it -> second; it++; } } void web_server::add_object(http_file *p) { objects.insert(std::pair(p -> get_url(), p)); } void * thread_wrapper_http_server(void *thread_data) { http_client_t *p_data = reinterpret_cast(thread_data); http_server *hs = new http_server(p_data -> fd); // get url std::string url = hs -> get_request_url(); dolog(LOG_INFO, "Processing url: %s", url.c_str()); // get request type http_request_t request_type = hs -> get_request_type(); // get request_details http_bundle *request_details = hs -> get_request(); // lookup_url -> file http_file *obj = p_data -> p_server -> lookup_url(url); // not allocated, don't free it if (!obj) { dolog(LOG_INFO, "URL not found"); obj = p_data -> p_server -> lookup_url("/404.html"); // not allocated, don't free it } if (!obj) dolog(LOG_INFO, "No object applicable found"); else { http_bundle *response = obj -> do_request(request_type, url, request_details); std::vector headers; headers.push_back(("Content-Type: " + obj -> get_meta_type()).c_str()); headers.push_back("Connection: close"); hs -> send_response(200, &headers, response); delete response; } delete request_details; delete hs; close(p_data -> fd); delete p_data; return NULL; } void web_server::run(void) { pthread_attr_t attr; pthread_check(pthread_attr_init(&attr), "pthread_attr_init"); pthread_check(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), "pthread_attr_setdetachstate"); for(;;) { int client_fd = accept(fd, NULL, NULL); if (client_fd == -1) { dolog(LOG_INFO, "web_server: accept failed: %s", strerror(errno)); continue; } std::string host = get_endpoint_name(client_fd); dolog(LOG_INFO, "web_server: connected with %s", host.c_str()); http_client_t *p_client = new http_client_t; p_client -> p_server = this; p_client -> fd = client_fd; pthread_t thread; pthread_check(pthread_create(&thread, &attr, thread_wrapper_http_server, reinterpret_cast(p_client)), "pthread_create"); } } http_file * web_server::lookup_url(std::string url) { size_t parameters_pos = url.find('?'); if (parameters_pos != std::string::npos) url = url.substr(0, parameters_pos); std::map::iterator index = objects.find(url); if (index != objects.end()) return index -> second; return NULL; } entropybroker-2.9/web_server.h000066400000000000000000000011351305163522000166020ustar00rootroot00000000000000void start_web_server(config_t *config, std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, statistics_global *ps, fips140 *pfips140, scc *pscc, data_logger *dl, users *pusers); class web_server { private: int fd; std::map objects; void add_object(http_file *p); public: web_server(config_t *config, std::vector *clients, pthread_mutex_t *clients_mutex, pools *ppools, statistics_global *ps, fips140 *pfips140, scc *pscc, data_logger *dl, users *pusers); ~web_server(); http_file * lookup_url(std::string url); void run(); };