Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Lagged Fibonacci generator PRNG providing high-speed, medium-quality numbers. #556

Merged
merged 5 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ AM_LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = nwipe
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h alfg/add_lagg_fibonacci_prng.h alfg/add_lagg_fibonacci_prng.c pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG)
79 changes: 79 additions & 0 deletions src/alfg/add_lagg_fibonacci_prng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Additive Lagged Fibonacci Generator (ALFG) Implementation
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This is an implementation of the Additive Lagged Fibonacci Generator (ALFG),
* a pseudorandom number generator known for its simplicity and good statistical properties
* for a wide range of applications. ALFGs are particularly noted for their long periods
* and efficiency in generating sequences of random numbers. However, like many other PRNGs,
* they are not suitable for cryptographic purposes due to their predictability.
*
* As the author of this implementation, I, Fabian Druschke, hereby release this work into
* the public domain. I dedicate any and all copyright interest in this work to the public
* domain, making it free to use for anyone for any purpose without any conditions, unless
* such conditions are required by law.
*
* This software is provided "as is", without warranty of any kind, express or implied,
* including but not limited to the warranties of merchantability, fitness for a particular
* purpose, and noninfringement. In no event shall the authors be liable for any claim,
* damages, or other liability, whether in an action of contract, tort, or otherwise, arising
* from, out of, or in connection with the software or the use or other dealings in the software.
*
* Note: This implementation is designed for non-cryptographic applications and should not be
* used where cryptographic security is required.
*/

#include "add_lagg_fibonacci_prng.h"
#include <stdint.h>
#include <string.h>

#define STATE_SIZE 64 // Size of the state array, sufficient for a high period
#define LAG_BIG 55 // Large lag, e.g., 55
#define LAG_SMALL 24 // Small lag, e.g., 24
#define MODULUS ( 1ULL << 48 ) // Modulus for the operations, here 2^48 for simple handling

void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length )
{
// Simple initialization: Fill the state with the key values and then with a linear combination of them
for( unsigned long i = 0; i < STATE_SIZE; i++ )
{
if( i < key_length )
{
state->s[i] = init_key[i];
}
else
{
// Simple method to generate further state values. Should be improved for serious applications.
state->s[i] = ( 6364136223846793005ULL * state->s[i - 1] + 1 ) % MODULUS;
}
}
state->index = 0; // Initialize the index for the first generation
}

void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos )
{
uint64_t* buf_as_uint64 = (uint64_t*) bufpos; // Interprets bufpos as a uint64_t array for direct assignment
int64_t result; // Use signed integer to handle potential negative results from subtraction

for (int i = 0; i < 4; i++) {
// Subtract the two previous numbers in the sequence
result = (int64_t)state->s[(state->index + LAG_BIG) % STATE_SIZE] - (int64_t)state->s[(state->index + LAG_SMALL) % STATE_SIZE];

// Handle borrow if result is negative
if (result < 0) {
result += MODULUS;
// Optionally set a borrow flag or adjust the next operation based on borrow logic
}

// Store the result (after adjustment) back into the state, ensuring it's positive and within range
state->s[state->index] = (uint64_t)result;

// Write the result into buf_as_uint64
buf_as_uint64[i] = state->s[state->index];

// Update the index for the next round
state->index = (state->index + 1) % STATE_SIZE;
}
}

43 changes: 43 additions & 0 deletions src/alfg/add_lagg_fibonacci_prng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Additive Lagged Fibonacci Generator (ALFG) Implementation definitions
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This is an implementation of the Additive Lagged Fibonacci Generator (ALFG),
* a pseudorandom number generator known for its simplicity and good statistical properties
* for a wide range of applications. ALFGs are particularly noted for their long periods
* and efficiency in generating sequences of random numbers. However, like many other PRNGs,
* they are not suitable for cryptographic purposes due to their predictability.
*
* As the author of this implementation, I, Fabian Druschke, hereby release this work into
* the public domain. I dedicate any and all copyright interest in this work to the public
* domain, making it free to use for anyone for any purpose without any conditions, unless
* such conditions are required by law.
*
* This software is provided "as is", without warranty of any kind, express or implied,
* including but not limited to the warranties of merchantability, fitness for a particular
* purpose, and noninfringement. In no event shall the authors be liable for any claim,
* damages, or other liability, whether in an action of contract, tort, or otherwise, arising
* from, out of, or in connection with the software or the use or other dealings in the software.
*
* Note: This implementation is designed for non-cryptographic applications and should not be
* used where cryptographic security is required.
*/

#ifndef ADD_LAGG_FIBONACCI_PRNG_H
#define ADD_LAGG_FIBONACCI_PRNG_H

#include <stdint.h>

// State definition for the Additive Lagged Fibonacci Generator
typedef struct
{
uint64_t s[64]; // State array
unsigned int index; // Current index in the state array
} add_lagg_fibonacci_state_t;

// Function prototypes
void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length );
void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos );

#endif // ADD_LAGG_FIBONACCI_PRNG_H
61 changes: 58 additions & 3 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,10 +1599,13 @@ void nwipe_gui_prng( void )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_aes_ctr_prng;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;

extern int terminate_signal;

/* The number of implemented PRNGs. */
const int count = 3;
const int count = 4;

/* The first tabstop. */
const int tab1 = 2;
Expand Down Expand Up @@ -1636,7 +1639,10 @@ void nwipe_gui_prng( void )
{
focus = 2;
}

if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
focus = 3;
}
do
{
/* Clear the main window. */
Expand All @@ -1651,6 +1657,7 @@ void nwipe_gui_prng( void )
mvwprintw( main_window, yy++, tab1, " %s", nwipe_twister.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac64.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_add_lagg_fibonacci_prng.label );
yy++;

/* Print the cursor. */
Expand Down Expand Up @@ -1733,8 +1740,52 @@ void nwipe_gui_prng( void )
tab1,
"Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " );
break;
case 3:

} /* switch */
mvwprintw( main_window,
yy++,
tab1,
"ALFG (Additive Lagged Fibonacci Generator), is a class of PRNGs utilizing" );
mvwprintw( main_window,
yy++,
tab1,
"the Fibonacci sequence with additive operations between lagged values. While" );
mvwprintw( main_window,
yy++,
tab1,
"they offer a good balance between speed and randomness, it's important to note" );
mvwprintw( main_window,
yy++,
tab1,
"that they provide lower levels of security, making them less suitable for" );
mvwprintw( main_window,
yy++,
tab1,
"cryptographic applications. Their periodicity depends on the choice of lags" );
mvwprintw( main_window,
yy++,
tab1,
"and arithmetic operations, potentially achieving large values, often 2^N or" );
mvwprintw( main_window,
yy++,
tab1,
"higher, where N is the bit length of the states. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"Efficient on CPUs of any bit width, particularly suited for non-cryptographic" );
mvwprintw( main_window,
yy++,
tab1,
"applications requiring long sequences with a good speed-randomness trade-off. " );
break;
}

/* switch */

/* Add a border. */
box( main_window, 0, 0 );
Expand Down Expand Up @@ -1794,6 +1845,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_isaac64;
}
if( focus == 3 )
{
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
}
return;

case KEY_BACKSPACE:
Expand Down
14 changes: 13 additions & 1 deletion src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ int nwipe_options_parse( int argc, char** argv )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;

/* The getopt() result holder. */
int nwipe_opt;
Expand Down Expand Up @@ -490,6 +491,11 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.prng = &nwipe_isaac64;
break;
}
if( strcmp( optarg, "add_lagg_fibonacci_prng" ) == 0 )
{
nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng;
break;
}

/* Else we do not know this PRNG. */
fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg );
Expand Down Expand Up @@ -539,6 +545,7 @@ void nwipe_options_log( void )
extern nwipe_prng_t nwipe_twister;
extern nwipe_prng_t nwipe_isaac;
extern nwipe_prng_t nwipe_isaac64;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;

/**
* Prints a manifest of options to the log.
Expand Down Expand Up @@ -590,6 +597,11 @@ void nwipe_options_log( void )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Mersenne Twister" );
}
if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator (EXPERIMENTAL!)" );
}

else
{
if( nwipe_options.prng == &nwipe_isaac )
Expand Down Expand Up @@ -681,7 +693,7 @@ void display_help()
puts( " -l, --logfile=FILE Filename to log to. Default is STDOUT\n" );
puts( " -P, --PDFreportpath=PATH Path to write PDF reports to. Default is \".\"" );
puts( " If set to \"noPDF\" no PDF reports are written.\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64)\n" );
puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng)\n" );
puts( " -q, --quiet Anonymize logs and the GUI by removing unique data, i.e." );
puts( " serial numbers, LU WWN Device ID, and SMBIOS/DMI data" );
puts( " XXXXXX = S/N exists, ????? = S/N not obtainable\n" );
Expand Down
48 changes: 48 additions & 0 deletions src/prng.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@
#include "mt19937ar-cok/mt19937ar-cok.h"
#include "isaac_rand/isaac_rand.h"
#include "isaac_rand/isaac64.h"
#include "alfg/add_lagg_fibonacci_prng.h" //Lagged Fibonacci generator prototype

nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read };

nwipe_prng_t nwipe_isaac = { "ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read };
nwipe_prng_t nwipe_isaac64 = { "ISAAC-64 (isaac64.c)", nwipe_isaac64_init, nwipe_isaac64_read };

/* ALFG PRNG Structure */
nwipe_prng_t nwipe_add_lagg_fibonacci_prng = { "Lagged Fibonacci generator",
nwipe_add_lagg_fibonacci_prng_init,
nwipe_add_lagg_fibonacci_prng_read };

/* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian. */
static inline void u32_to_buffer( u8* restrict buffer, u32 val, const int len )
{
Expand Down Expand Up @@ -250,3 +256,45 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )

return 0;
}

/* EXPERIMENTAL implementation of Lagged Fibonacci generator a lot of random numbers */

int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
nwipe_log( NWIPE_LOG_NOTICE, "Initialising Lagged Fibonacci generator PRNG" );

if( *state == NULL )
{
/* This is the first time that we have been called. */
*state = malloc( sizeof( add_lagg_fibonacci_state_t ) );
}
add_lagg_fibonacci_init(
(add_lagg_fibonacci_state_t*) *state, (unsigned long*) ( seed->s ), seed->length / sizeof( unsigned long ) );

return 0;
}

int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE )
{
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_ADD_LAGG_FIBONACCI_PRNG;

/* Loop to fill the buffer with blocks directly from the Fibonacci algorithm */
for( size_t ii = 0; ii < words; ++ii )
{
add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, bufpos );
bufpos += SIZE_OF_ADD_LAGG_FIBONACCI_PRNG; // Move to the next block
}

/* Handle remaining bytes if count is not a multiple of SIZE_OF_ADD_LAGG_FIBONACCI_PRNG */
const size_t remain = count % SIZE_OF_ADD_LAGG_FIBONACCI_PRNG;
if( remain > 0 )
{
unsigned char temp_output[16]; // Temporary buffer for the last block
add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, temp_output );
// Copy the remaining bytes
memcpy( bufpos, temp_output, remain );
}

return 0; // Success
}
7 changes: 7 additions & 0 deletions src/prng.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,18 @@ int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE );

/* ALFG prototypes. */
int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE );

/* Size of the twister is not derived from the architecture, but it is strictly 4 bytes */
#define SIZE_OF_TWISTER 4

/* Size of the isaac/isaac64 is not derived from the architecture, but it is strictly 4 or 8 bytes */
#define SIZE_OF_ISAAC 4
#define SIZE_OF_ISAAC64 8

/* Size of the Lagged Fibonacci generator is not derived from the architecture, but it is strictly 32 bytes */
#define SIZE_OF_ADD_LAGG_FIBONACCI_PRNG 32

#endif /* PRNG_H_ */
4 changes: 2 additions & 2 deletions src/temperature.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

//#define _LARGEFILE64_SOURCE
//#define _FILE_OFFSET_BITS 64
// #define _LARGEFILE64_SOURCE
// #define _FILE_OFFSET_BITS 64
#define _BSD_SOURCE

#include <stdio.h>
Expand Down
Loading