Skip to content

Commit

Permalink
Several changes, adding AES-128 using libssl in CTR mode as new PRNG,…
Browse files Browse the repository at this point in the history
… in experimental state. Fixed formatting, fixed AES PRNG header.
  • Loading branch information
Fabian Druschke committed Mar 10, 2024
1 parent cb595e1 commit e9b126d
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 37 deletions.
6 changes: 3 additions & 3 deletions src/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# what flags you want to pass to the C compiler & linker
#CFLAGS = -lncurses -lparted
AM_CFLAGS =
AM_LDFLAGS =
AM_CFLAGS =
AM_LDFLAGS = -lcrypto

# 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 aes/aes_ctr_prng.h aes/aes_ctr_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)
52 changes: 52 additions & 0 deletions src/aes/aes_ctr_prng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "aes_ctr_prng.h"
#include <openssl/rand.h>
#include <string.h>
// #include <stdio.h> // Necessary for printf
#include <openssl/aes.h>
#include <openssl/modes.h>

void aes_ctr_prng_init( aes_ctr_state_t* state, unsigned long init_key[], unsigned long key_length )
{
unsigned char key[16]; // Expanded to 128 Bit
memset( key, 0, 16 );

// printf("Original key length (in unsigned long units): %lu\n", key_length);
// printf("Original key (64 Bit): %016lx\n", init_key[0]);

// Repeat the 64-bit key to create a 128-bit key.
for( size_t i = 0; i < 16; i++ )
{
key[i] = ( (unsigned char*) init_key )[i % 8];
}

AES_set_encrypt_key( key, 128, &state->aes_key ); // 128 Bit key
memset( state->ivec, 0, AES_BLOCK_SIZE );
state->num = 0;
memset( state->ecount, 0, AES_BLOCK_SIZE );
}

static void next_state( aes_ctr_state_t* state )
{
for( int i = 0; i < AES_BLOCK_SIZE; ++i )
{
if( ++state->ivec[i] )
break;
}
}

unsigned long aes_ctr_prng_genrand_uint32( aes_ctr_state_t* state )
{
unsigned long result = 0;

CRYPTO_ctr128_encrypt( (unsigned char*) &result,
(unsigned char*) &result,
sizeof( result ),
&state->aes_key,
state->ivec,
state->ecount,
&state->num,
(block128_f) AES_encrypt );
next_state( state ); // Ensure this function does not cause errors

return result & 0xFFFFFFFF;
}
22 changes: 22 additions & 0 deletions src/aes/aes_ctr_prng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef AES_CTR_RNG_H
#define AES_CTR_RNG_H

#include <stdint.h>
#include <openssl/aes.h>

// Structure to store the state of the AES-CTR random number generator
typedef struct
{
AES_KEY aes_key;
unsigned char ivec[AES_BLOCK_SIZE];
unsigned int num;
unsigned char ecount[AES_BLOCK_SIZE];
} aes_ctr_state_t;

// Initializes the AES-CTR random number generator
void init_aes_ctr( aes_ctr_state_t* state, const unsigned char* key );

// Generates a 32-bit integer using AES-CTR
unsigned int aes_ctr_generate_uint32( aes_ctr_state_t* state );

#endif // AES_CTR_RNG_H
24 changes: 22 additions & 2 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,10 +1599,11 @@ 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 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,6 +1637,10 @@ void nwipe_gui_prng( void )
{
focus = 2;
}
if( nwipe_options.prng == &nwipe_aes_ctr_prng )
{
focus = 3;
}

do
{
Expand All @@ -1651,6 +1656,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_aes_ctr_prng.label );
yy++;

/* Print the cursor. */
Expand Down Expand Up @@ -1733,8 +1739,18 @@ 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,
"AES-CTR Ni Prototype " );
break;

}


/* switch */

/* Add a border. */
box( main_window, 0, 0 );
Expand Down Expand Up @@ -1794,6 +1810,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_isaac64;
}
if( focus == 3 )
{
nwipe_options.prng = &nwipe_aes_ctr_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_aes_ctr_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, "aes_ctr_prng" ) == 0 )
{
nwipe_options.prng = &nwipe_aes_ctr_prng;
break;
}

/* Else we do not know this PRNG. */
fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg );
Expand Down Expand Up @@ -539,6 +545,8 @@ 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_aes_ctr_prng;


/**
* Prints a manifest of options to the log.
Expand Down Expand Up @@ -590,6 +598,10 @@ void nwipe_options_log( void )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Mersenne Twister" );
}
if( nwipe_options.prng == &nwipe_aes_ctr_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = AES-CTR New Instructions (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|aes-ctr)\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
46 changes: 46 additions & 0 deletions src/prng.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@
#include "mt19937ar-cok/mt19937ar-cok.h"
#include "isaac_rand/isaac_rand.h"
#include "isaac_rand/isaac64.h"
#include "aes/aes_ctr_prng.h" // AES-NI 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 };

/* AES-CTR-NI PRNG Structure */
nwipe_prng_t nwipe_aes_ctr_prng = { "AES-CTR-PRNG", nwipe_aes_ctr_prng_init, nwipe_aes_ctr_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 +255,44 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )

return 0;
}


/* EXPERIMENTAL implementation of AES-128 in counter mode to provide high-quality random numbers */

int nwipe_aes_ctr_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
nwipe_log( NWIPE_LOG_NOTICE, "Initialising AES CTR PRNG" );

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

return 0;
}

int nwipe_aes_ctr_prng_read( NWIPE_PRNG_READ_SIGNATURE )
{
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_AES_CTR_PRNG; // the values of aes_ctr_prng_genrand_uint32 is strictly 4 bytes

/* AES CTR PRNG returns 4-bytes per call, so progress by 4 bytes. */
for( size_t ii = 0; ii < words; ++ii )
{
u32_to_buffer( bufpos, aes_ctr_prng_genrand_uint32( (aes_ctr_state_t*) *state ), SIZE_OF_AES_CTR_PRNG );
bufpos += SIZE_OF_AES_CTR_PRNG;
}

/* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */
const size_t remain = count % SIZE_OF_AES_CTR_PRNG; // SIZE_OF_AES_CTR_PRNG is strictly 4 bytes
if( remain > 0 )
{
u32_to_buffer( bufpos, aes_ctr_prng_genrand_uint32( (aes_ctr_state_t*) *state ), remain );
}

return 0;
}


49 changes: 18 additions & 31 deletions src/prng.h
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
/*
* prng.h: Pseudo Random Number Generator abstractions for nwipe.
*
* Copyright Darik Horn <[email protected]>.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/

#ifndef PRNG_H_
#define PRNG_H_

Expand All @@ -34,26 +14,30 @@ typedef struct
#define NWIPE_PRNG_READ_SIGNATURE void **state, void *buffer, size_t count

/* Function pointers for PRNG actions. */
typedef int ( *nwipe_prng_init_t )( NWIPE_PRNG_INIT_SIGNATURE );
typedef int ( *nwipe_prng_read_t )( NWIPE_PRNG_READ_SIGNATURE );
typedef int (*nwipe_prng_init_t)(NWIPE_PRNG_INIT_SIGNATURE);
typedef int (*nwipe_prng_read_t)(NWIPE_PRNG_READ_SIGNATURE);

/* The generic PRNG definition. */
typedef struct
{
const char* label; // The name of the pseudo random number generator.
nwipe_prng_init_t init; // Inialize the prng state with the seed.
nwipe_prng_read_t read; // Read data from the prng.
const char* label; // The name of the pseudo random number generator.
nwipe_prng_init_t init; // Initialize the prng state with the seed.
nwipe_prng_read_t read; // Read data from the prng.
} nwipe_prng_t;

/* Mersenne Twister prototypes. */
int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_twister_init(NWIPE_PRNG_INIT_SIGNATURE);
int nwipe_twister_read(NWIPE_PRNG_READ_SIGNATURE);

/* ISAAC prototypes. */
int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE );
int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE );
int nwipe_isaac_init(NWIPE_PRNG_INIT_SIGNATURE);
int nwipe_isaac_read(NWIPE_PRNG_READ_SIGNATURE);
int nwipe_isaac64_init(NWIPE_PRNG_INIT_SIGNATURE);
int nwipe_isaac64_read(NWIPE_PRNG_READ_SIGNATURE);

/* AES-CTR-NI prototypes. */
int nwipe_aes_ctr_prng_init(NWIPE_PRNG_INIT_SIGNATURE);
int nwipe_aes_ctr_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
Expand All @@ -62,4 +46,7 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE );
#define SIZE_OF_ISAAC 4
#define SIZE_OF_ISAAC64 8

/* Size of the AES-CTR is not derived from the architecture, but it is strictly 4 or 8 bytes */
#define SIZE_OF_AES_CTR_PRNG 4

#endif /* PRNG_H_ */

0 comments on commit e9b126d

Please sign in to comment.