Skip to content

Commit

Permalink
Added AES-256-XTS XEX-based Tweaked CodeBook mode with ciphertext Ste…
Browse files Browse the repository at this point in the history
…aling, increasing speed by writing 2x256b at once, and increasing security
  • Loading branch information
Knogle committed Aug 23, 2024
1 parent e56a47c commit 11afdc3
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 4 deletions.
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 alfg/add_lagg_fibonacci_prng.h alfg/add_lagg_fibonacci_prng.c xor/xoroshiro256_prng.h xor/xoroshiro256_prng.c 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_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 xor/xoroshiro256_prng.h xor/xoroshiro256_prng.c aes/aes_xts_prng.h aes/aes_xts_prng.c 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)
159 changes: 159 additions & 0 deletions src/aes/aes_xts_prng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* AES XTS PRNG Implementation with EVP_MD_BLAKE2 for Key Derivation
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This header file contains definitions for the AES (Advanced Encryption Standard)
* implementation in XTS (XEX-based tweaked-codebook mode with ciphertext stealing) mode
* for pseudorandom number generation, utilizing OpenSSL for cryptographic functions and BLAKE2
* for generating a 512-bit seed.
*
* As the author of this work, 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.
*
* USAGE OF OPENSSL IN THIS SOFTWARE:
* This software uses OpenSSL for cryptographic operations. Users are responsible for
* ensuring compliance with OpenSSL's licensing terms.
*/

#include "aes_xts_prng.h"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

typedef enum {
NWIPE_LOG_NONE = 0,
NWIPE_LOG_DEBUG, // Debugging messages, detailed for troubleshooting
NWIPE_LOG_INFO, // Informative logs, for regular operation insights
NWIPE_LOG_NOTICE, // Notices for significant but non-critical events
NWIPE_LOG_WARNING, // Warnings about potential errors
NWIPE_LOG_ERROR, // Error messages, significant issues that affect operation
NWIPE_LOG_FATAL, // Fatal errors, require immediate termination of the program
NWIPE_LOG_SANITY, // Sanity checks, used primarily in debugging phases
NWIPE_LOG_NOTIMESTAMP // Log entries without timestamp information
} nwipe_log_t;

extern void nwipe_log(nwipe_log_t level, const char* format, ...);

/* Initializes the AES XTS pseudorandom number generator state using BLAKE2b for key derivation.
This function sets up the cryptographic context necessary for generating
pseudorandom numbers using AES in XTS mode. It utilizes BLAKE2b to derive
a 512-bit key from the provided seed, ensuring that the PRNG output is unpredictable
and secure, provided the seed is kept secret and is sufficiently random.
- state: Pointer to the AES XTS PRNG state structure.
- init_key: Array containing the seed for key generation.
- key_length: Length of the seed array. */
int aes_xts_prng_init(aes_xts_state_t* state, unsigned long init_key[], unsigned long key_length)
{
assert(state != NULL && init_key != NULL && key_length > 0); // Validate inputs

unsigned char key[64]; // Storage for the 512-bit key (2 x 256-bit)
memset(state->ivec, 0, AES_BLOCK_SIZE); // Clear IV buffer
state->num = 0; // Reset the block counter
memset(state->ecount, 0, AES_BLOCK_SIZE); // Clear encryption count buffer

nwipe_log(NWIPE_LOG_DEBUG, "Initializing AES XTS PRNG with provided seed using BLAKE2b via EVP_MD."); // Log initialization

// Use EVP_MD for BLAKE2b hash computation
EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); // Create new EVP_MD context for BLAKE2b
if (!mdctx)
{
nwipe_log(NWIPE_LOG_FATAL, "Failed to allocate EVP_MD_CTX for BLAKE2b, return code: %d.", ERR_get_error()); // Log context allocation failure
return -1; // Handle error
}

if (EVP_DigestInit_ex(mdctx, EVP_blake2b512(), NULL) != 1)
{
nwipe_log(NWIPE_LOG_FATAL, "BLAKE2b context initialization failed, return code: %d.", ERR_get_error()); // Log init failure
EVP_MD_CTX_free(mdctx); // Clean up context
return -1; // Handle error
}

if (EVP_DigestUpdate(mdctx, (const unsigned char*)init_key, key_length * sizeof(unsigned long)) != 1)
{
nwipe_log(NWIPE_LOG_FATAL, "BLAKE2b hash update failed, return code: %d.", ERR_get_error()); // Log update failure
EVP_MD_CTX_free(mdctx); // Clean up context
return -1; // Handle error
}

if (EVP_DigestFinal_ex(mdctx, key, NULL) != 1)
{
nwipe_log(NWIPE_LOG_FATAL, "BLAKE2b hash finalization failed, return code: %d.", ERR_get_error()); // Log finalization failure
EVP_MD_CTX_free(mdctx); // Clean up context
return -1; // Handle error
}

EVP_MD_CTX_free(mdctx); // Clean up context after successful hashing

state->ctx = EVP_CIPHER_CTX_new(); // Create new AES-XTS-256 context
if (!state->ctx)
{
nwipe_log(NWIPE_LOG_FATAL, "Failed to allocate EVP_CIPHER_CTX, return code: %d.", ERR_get_error()); // Log cipher context failure
return -1; // Handle error
}

if (EVP_EncryptInit_ex(state->ctx, EVP_aes_256_xts(), NULL, key, state->ivec) != 1)
{
nwipe_log(NWIPE_LOG_FATAL, "AES-XTS-256 encryption context initialization failed, return code: %d.", ERR_get_error()); // Log encryption init failure
EVP_CIPHER_CTX_free(state->ctx); // Clean up context on failure
return -1; // Handle error
}

nwipe_log(NWIPE_LOG_DEBUG, "AES XTS PRNG successfully initialized using BLAKE2."); // Log successful initialization
return 0; // Exit successfully
}

/* Generates pseudorandom numbers and writes them to a buffer.
This function performs the core operation of producing pseudorandom data.
It directly updates the buffer provided, filling it with pseudorandom bytes
generated using the AES-XTS-256 mode of operation.
- state: Pointer to the initialized AES XTS PRNG state.
- bufpos: Target buffer where the pseudorandom numbers will be written. */
int aes_xts_prng_genrand_uint512_to_buf(aes_xts_state_t* state, unsigned char* bufpos)
{
assert(state != NULL && bufpos != NULL); // Validate inputs

unsigned char temp_buffer[64]; // Temporary storage for pseudorandom bytes (512-bit)
memset(temp_buffer, 0, sizeof(temp_buffer)); // Zero out temporary buffer
int outlen; // Length of data produced by encryption

if (EVP_EncryptUpdate(state->ctx, temp_buffer, &outlen, temp_buffer, sizeof(temp_buffer)) != 1)
{
nwipe_log(NWIPE_LOG_ERROR, "Failed to generate pseudorandom numbers, return code: %d.", ERR_get_error()); // Log generation failure
return -1; // Handle error
}

memcpy(bufpos, temp_buffer, sizeof(temp_buffer)); // Copy pseudorandom bytes to buffer
return 0; // Exit successfully
}

// General cleanup function for AES XTS PRNG
int aes_xts_prng_general_cleanup(aes_xts_state_t* state)
{
if (state != NULL)
{
// Free the EVP_CIPHER_CTX if it has been allocated
if (state->ctx)
{
EVP_CIPHER_CTX_free(state->ctx);
state->ctx = NULL; // Nullify the pointer after free
}

// Clear sensitive information from the state
memset(state->ivec, 0, AES_BLOCK_SIZE);
memset(state->ecount, 0, AES_BLOCK_SIZE);
state->num = 0;
}
return 0;
}

52 changes: 52 additions & 0 deletions src/aes/aes_xts_prng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* AES XTS PRNG Definitions
* Author: Fabian Druschke
* Date: 2024-03-13
*
* This header file contains definitions for the AES (Advanced Encryption Standard)
* implementation in XTS (XEX-based Tweaked-codebook mode with ciphertext Stealing) mode
* for pseudorandom number generation, utilizing OpenSSL for cryptographic functions.
*
* As the author of this work, 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.
*
* USAGE OF OPENSSL IN THIS SOFTWARE:
* This software uses OpenSSL for cryptographic operations. Users are responsible for
* ensuring compliance with OpenSSL's licensing terms.
*/

#ifndef AES_XTS_RNG_H
#define AES_XTS_RNG_H

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

// Structure to store the state of the AES-XTS random number generator
typedef struct
{
EVP_CIPHER_CTX* ctx; // Encryption context for AES-XTS
unsigned char ivec[AES_BLOCK_SIZE]; // Initialization vector
unsigned int num; // Counter for the number of blocks processed
unsigned char ecount[AES_BLOCK_SIZE]; // Encryption count buffer for feedback
} aes_xts_state_t;

// Initializes the AES-XTS random number generator
int aes_xts_prng_init(aes_xts_state_t* state, unsigned long init_key[], unsigned long key_length);

// Generates a 512-bit random number using AES-XTS and stores it directly in the output buffer
int aes_xts_prng_genrand_uint512_to_buf(aes_xts_state_t* state, unsigned char* bufpos);

// General cleanup function for AES XTS PRNG
int aes_xts_prng_general_cleanup(aes_xts_state_t* state);

#endif // AES_XTS_RNG_H

85 changes: 83 additions & 2 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -1603,11 +1603,12 @@ void nwipe_gui_prng( void )
extern nwipe_prng_t nwipe_xoroshiro256_prng;
extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng;
extern nwipe_prng_t nwipe_aes_ctr_prng;
extern nwipe_prng_t nwipe_aes_xts_prng;

extern int terminate_signal;

/* The number of implemented PRNGs. */
const int count = 6;
const int count = 7;

/* The first tabstop. */
const int tab1 = 2;
Expand Down Expand Up @@ -1653,6 +1654,10 @@ void nwipe_gui_prng( void )
{
focus = 5;
}
if( nwipe_options.prng == &nwipe_aes_xts_prng )
{
focus = 6;
}
do
{
/* Clear the main window. */
Expand All @@ -1670,6 +1675,7 @@ void nwipe_gui_prng( void )
mvwprintw( main_window, yy++, tab1, " %s", nwipe_add_lagg_fibonacci_prng.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_xoroshiro256_prng.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_aes_ctr_prng.label );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_aes_xts_prng.label );
yy++;

/* Print the cursor. */
Expand Down Expand Up @@ -1887,8 +1893,79 @@ void nwipe_gui_prng( void )
main_window, yy++, tab1, "stands as the world gold standard for data encryption techniques." );
mvwprintw( main_window, yy++, tab1, "Intended to be used only with 64-Bit CPUs, supporting AES-Ni." );
break;
case 6:
mvwprintw( main_window,
yy++,
tab1,
"AES-256 in ultra-secure XTS Mode (XEX-based), expertly implemented by Fabian Druschke" );
mvwprintw(
main_window, yy++, tab1, "within nwipe using OpenSSL, leveraging the cryptographic strength and " );
mvwprintw( main_window,
yy++,
tab1,
"efficiency of AES to generate high-quality pseudo-random numbers. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"Designed specifically for the truly paranoid (just kidding!): If AES-256-CTR" );
mvwprintw( main_window,
yy++,
tab1,
"isn't enough for you, this XTS mode with XEX-based tweaked-codebook steps" );
mvwprintw( main_window,
yy++,
tab1,
"up the security game. Perfectly optimized for encrypting block devices," );
mvwprintw( main_window,
yy++,
tab1,
"ensuring maximum data protection. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"This implementation emphasizes the use of AES New Instructions (AES-NI)," );
mvwprintw( main_window,
yy++,
tab1,
"starting from the Westmere-EP architecture, which significantly boosts " );
mvwprintw( main_window,
yy++,
tab1,
"performance and security for data wiping tasks. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
mvwprintw( main_window,
yy++,
tab1,
"The integration of AES-NI accelerates cryptographic operations, making " );
mvwprintw( main_window,
yy++,
tab1,
"AES-256 in XTS mode an ideal choice for efficient and secure data erasure " );
mvwprintw( main_window,
yy++,
tab1,
"in nwipe. Compliant with NIST SP 800-38E, AES-256 XTS (XEX-based) stands as" );
mvwprintw( main_window,
yy++,
tab1,
"the gold standard for data encryption and protection. Intended for use only" );
mvwprintw( main_window,
yy++,
tab1,
"with 64-bit CPUs that support AES-NI by generating 2x256-bit keys at once." );
break;
}

/* switch */

/* Add a border. */
Expand Down Expand Up @@ -1961,6 +2038,10 @@ void nwipe_gui_prng( void )
{
nwipe_options.prng = &nwipe_aes_ctr_prng;
}
if( focus == 6 )
{
nwipe_options.prng = &nwipe_aes_xts_prng;
}
return;

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

/* The getopt() result holder. */
int nwipe_opt;
Expand Down Expand Up @@ -561,6 +562,11 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.prng = &nwipe_aes_ctr_prng;
break;
}
if( strcmp( optarg, "aes_xtr_prng" ) == 0 )
{
nwipe_options.prng = &nwipe_aes_xts_prng;
break;
}

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

/**
* Prints a manifest of options to the log.
Expand Down Expand Up @@ -676,6 +683,10 @@ void nwipe_options_log( void )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = AES-CTR New Instructions (EXPERIMENTAL!)" );
}
else if( nwipe_options.prng == &nwipe_aes_xts_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = AES-XTR Block Cipher (EXPERIMENTAL!)" );
}
else if( nwipe_options.prng == &nwipe_isaac )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" );
Expand Down Expand Up @@ -766,7 +777,7 @@ void display_help()
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|add_lagg_fibonacci_prng|xoroshiro256_prng|aes_ctr_prng)\n" );
"(mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng|xoroshiro256_prng|aes_ctr_prng|aes_xtr_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
Loading

0 comments on commit 11afdc3

Please sign in to comment.