The following demonstrates how to use C language to download random data from a SwiftRNG device when used with Entropy Server
for Windows and utilizing a named pipe. The following code will only work when running SwiftRNG Entropy Server.
This is the recommended way for achieving maximum concurrent speed and performance.
Before using the following example, make sure the SwiftRNG device is plugged into one of USB ports available and
entropy-server.exe
is running on same system.
A C sample source code (it has been tested with Microsoft Visual Studio Community 2019) for retrieving random values from SwiftRNG device when using Entropy Server for Windows through a named pipe connection.
#include <windows.h>
#include <stdio.h>
#define ENTROPY_BUFFER_SIZE 100000
#define CMD_ENTROPY_RETRIEVE_ID 0
//
// Functions
//
int openNamedPipe();
int closeNamedPipe();
int readEntropyFromPipe(DWORD commandId, unsigned char* rcvBuff, DWORD len);
int retrieveEntropyFromServer(DWORD commandId, unsigned char* rcvBuff, DWORD len);
//
// Data section
//
typedef struct
{
DWORD cmd;
DWORD cbReqData;
} REQCMD;
REQCMD reqCmd;
HANDLE hPipe;
LPCWSTR defaultPipeEndpoint = L"\\\\.\\pipe\\SwiftRNG";
BOOL fSuccess = FALSE;
DWORD cbRead, cbWritten, cbToWrite, dwMode;
unsigned char entropyBuffer[ENTROPY_BUFFER_SIZE];
int main()
{
int status = 0;
int i;
printf("Retrieving random %d bytes from entropy server ................ ", ENTROPY_BUFFER_SIZE);
status = retrieveEntropyFromServer(CMD_ENTROPY_RETRIEVE_ID, entropyBuffer, ENTROPY_BUFFER_SIZE);
if (status == 0) {
printf("SUCCESS\n");
}
else {
printf(" failed\n");
printf("Is entropy server running?\n");
return status;
}
printf("Printing the first 10 random bytes:\n");
for (i = 1; i <= 10; i++) {
printf("rnd[% d] = %d\n", i, entropyBuffer[i]);
}
}
/*
* Retrieve entropy data from the entropy server
* @param commandId - command to send to the entropy server
* @param rcvBuff buffer for incoming data
* @param len - number of bytes to receive
* @return 0 - success
*/
int retrieveEntropyFromServer(DWORD commandId, unsigned char* rcvBuff, DWORD len) {
int status = openNamedPipe();
if (status == 0) {
status = readEntropyFromPipe(commandId, rcvBuff, len);
closeNamedPipe();
}
return status;
}
/*
* Open named pipe to the entropy server
*
* @return 0 - success
*/
int openNamedPipe() {
while (1) {
hPipe = CreateFile(
defaultPipeEndpoint, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (hPipe != INVALID_HANDLE_VALUE) {
break;
}
if (GetLastError() != ERROR_PIPE_BUSY) {
return -1;
}
if (!WaitNamedPipe(defaultPipeEndpoint, 20000)) {
return -1;
}
}
dwMode = PIPE_READMODE_BYTE;
fSuccess = SetNamedPipeHandleState(
hPipe, // pipe handle
&dwMode, // new pipe mode
NULL, // don't set maximum bytes
NULL); // don't set maximum time
if (!fSuccess) {
return -1;
}
return 0;
}
/*
* Close named pipe to the entropy server
*
* @return 0 - success
*/
int closeNamedPipe() {
CloseHandle(hPipe);
return 0;
}
/*
* Read entropy data from named pipe
* @param commandId - command to send to the entropy server
* @param rcvBuff buffer for incoming data
* @param len - number of bytes to receive
* @return 0 - success
*/
int readEntropyFromPipe(DWORD commandId, unsigned char* rcvBuff, DWORD len) {
cbToWrite = sizeof(REQCMD);
reqCmd.cmd = commandId;
reqCmd.cbReqData = len;
fSuccess = WriteFile(
hPipe, // pipe handle
&reqCmd, // bytes
cbToWrite, // bytes length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess) {
return -1;
}
do {
fSuccess = ReadFile(
hPipe, // pipe handle
rcvBuff, // buffer to receive reply
len, // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
if (!fSuccess && GetLastError() != ERROR_MORE_DATA) {
break;
}
} while (!fSuccess); // repeat loop if ERROR_MORE_DATA
if (!fSuccess) {
return -1;
}
return 0;
}