From 11afdc30f9692d902112f32046e3e756faee30d8 Mon Sep 17 00:00:00 2001 From: Fabian Druschke Date: Fri, 23 Aug 2024 20:59:13 +0200 Subject: [PATCH] Added AES-256-XTS XEX-based Tweaked CodeBook mode with ciphertext Stealing, increasing speed by writing 2x256b at once, and increasing security --- src/Makefile.am | 2 +- src/aes/aes_xts_prng.c | 159 +++++++++++++++++++++++++++++++++++++++++ src/aes/aes_xts_prng.h | 52 ++++++++++++++ src/gui.c | 85 +++++++++++++++++++++- src/options.c | 13 +++- src/prng.c | 101 ++++++++++++++++++++++++++ src/prng.h | 7 ++ 7 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 src/aes/aes_xts_prng.c create mode 100644 src/aes/aes_xts_prng.h diff --git a/src/Makefile.am b/src/Makefile.am index 07494fdb..c05ee20f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/aes/aes_xts_prng.c b/src/aes/aes_xts_prng.c new file mode 100644 index 00000000..62316529 --- /dev/null +++ b/src/aes/aes_xts_prng.c @@ -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 +#include +#include +#include +#include + +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; +} + diff --git a/src/aes/aes_xts_prng.h b/src/aes/aes_xts_prng.h new file mode 100644 index 00000000..2237228a --- /dev/null +++ b/src/aes/aes_xts_prng.h @@ -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 +#include +#include + +// 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 + diff --git a/src/gui.c b/src/gui.c index fd0d589c..6a1f3535 100644 --- a/src/gui.c +++ b/src/gui.c @@ -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; @@ -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. */ @@ -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. */ @@ -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. */ @@ -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: diff --git a/src/options.c b/src/options.c index 98e316ae..e9d933e0 100644 --- a/src/options.c +++ b/src/options.c @@ -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; @@ -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 ); @@ -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. @@ -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" ); @@ -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" ); diff --git a/src/prng.c b/src/prng.c index acc6cf7f..3fd3fec2 100644 --- a/src/prng.c +++ b/src/prng.c @@ -28,6 +28,7 @@ #include "alfg/add_lagg_fibonacci_prng.h" //Lagged Fibonacci generator prototype #include "xor/xoroshiro256_prng.h" //XORoshiro-256 prototype #include "aes/aes_ctr_prng.h" // AES-NI prototype +#include "aes/aes_xts_prng.h" // AES-XTS prototype nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read }; @@ -44,6 +45,9 @@ nwipe_prng_t nwipe_xoroshiro256_prng = { "XORoshiro-256", nwipe_xoroshiro256_prn /* AES-CTR-NI PRNG Structure */ nwipe_prng_t nwipe_aes_ctr_prng = { "AES-256-CTR (OpenSSL)", nwipe_aes_ctr_prng_init, nwipe_aes_ctr_prng_read }; +/* AES-XTS PRNG Structure */ +nwipe_prng_t nwipe_aes_xts_prng = { "AES-256-XTS (OpenSSL)", nwipe_aes_xts_prng_init, nwipe_aes_xts_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 ) { @@ -436,3 +440,100 @@ int nwipe_aes_ctr_prng_read( NWIPE_PRNG_READ_SIGNATURE ) return 0; // Indicate success. } +/** + * EXPERIMENTAL implementation of AES-256 in XTS mode to provide high-quality random numbers. + * Initializes the AES XTS PRNG state. + * + * This function sets up the cryptographic context necessary for generating pseudorandom numbers + * using AES-256 in XTS mode. It utilizes SHA-512 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 sufficiently random. + * + * @param state A pointer to the PRNG state structure. If the pointed state is NULL, + * memory will be allocated and initialized for it. + * @param init_key An array containing the seed for key generation. + * @param key_length The length of the seed array. + * @return int Returns 0 on success, -1 on failure (e.g., memory allocation failure or initialization error). + */ + +int nwipe_aes_xts_prng_init( NWIPE_PRNG_INIT_SIGNATURE ) +{ + // Log the start of the PRNG initialization process. + nwipe_log( NWIPE_LOG_DEBUG, "Initialising AES XTS PRNG" ); + + // Check if the state pointer is NULL, indicating that it hasn't been allocated yet. + if( *state == NULL ) + { + // Allocate memory for the PRNG state and initialize it to zeros. + *state = calloc( 1, sizeof( aes_xts_state_t ) ); + + // Check if memory allocation failed. + if( *state == NULL ) + { + // Log the memory allocation failure. + nwipe_log( NWIPE_LOG_FATAL, "Failed to allocate memory for AES XTS PRNG state." ); + return -1; // Return an error code indicating failure. + } + } + + // Initialize the PRNG state with the provided seed. + if( aes_xts_prng_init( + (aes_xts_state_t*) *state, (unsigned long*) ( seed->s ), seed->length / sizeof( unsigned long ) ) + != 0 ) + { + nwipe_log( NWIPE_LOG_SANITY, "Fatal error occured during PRNG init in OpenSSL." ); + return -1; + } + + return 0; // Indicate success. +} + +/** + * Generates random data using the AES XTS PRNG. + * + * @param state A double pointer to the PRNG state structure. + * @param buffer A pointer to the buffer where the generated random data will be stored. + * @param count The number of bytes of random data to generate. + * @return int Returns 0 on success. + */ +int nwipe_aes_xts_prng_read( NWIPE_PRNG_READ_SIGNATURE ) +{ + // Pointer to track the current position in the output buffer. + u8* restrict bufpos = buffer; + + // Calculate the number of complete 512-bit blocks to generate. + size_t words = count / SIZE_OF_AES_XTS_PRNG; + + // Loop to fill the buffer with 512-bit blocks of random data. + for( size_t ii = 0; ii < words; ++ii ) + { + // Generate a 512-bit block and write it directly to the buffer. + if( aes_xts_prng_genrand_uint512_to_buf( (aes_xts_state_t*) *state, bufpos ) != 0 ) + { + nwipe_log( NWIPE_LOG_SANITY, "Fatal error occured during RNG generation in OpenSSL." ); + return -1; + } + + // Move the buffer position to the start of the next block. + bufpos += SIZE_OF_AES_XTS_PRNG; + } + + // Calculate the number of remaining bytes to generate, if any. + const size_t remain = count % SIZE_OF_AES_XTS_PRNG; + + // Check if there are remaining bytes to generate. + if( remain > 0 ) + { + // Temporary buffer for the last block of random data. + unsigned char temp_output[32]; + memset( temp_output, 0, sizeof( temp_output ) ); + + // Generate one more block of random data. + aes_xts_prng_genrand_uint512_to_buf( (aes_xts_state_t*) *state, temp_output ); + + // Copy only the necessary remaining bytes to the output buffer. + memcpy( bufpos, temp_output, remain ); + } + + return 0; // Indicate success. +} diff --git a/src/prng.h b/src/prng.h index 3e9a7177..f597360c 100644 --- a/src/prng.h +++ b/src/prng.h @@ -67,6 +67,10 @@ int nwipe_xoroshiro256_prng_read( NWIPE_PRNG_READ_SIGNATURE ); int nwipe_aes_ctr_prng_init( NWIPE_PRNG_INIT_SIGNATURE ); int nwipe_aes_ctr_prng_read( NWIPE_PRNG_READ_SIGNATURE ); +/* AES-XTR-256 (512-bit) prototype. */ +int nwipe_aes_xts_prng_init( NWIPE_PRNG_INIT_SIGNATURE ); +int nwipe_aes_xts_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 @@ -83,4 +87,7 @@ int nwipe_aes_ctr_prng_read( NWIPE_PRNG_READ_SIGNATURE ); /* Size of the AES-CTR is not derived from the architecture, but it is strictly 32 bytes */ #define SIZE_OF_AES_CTR_PRNG 32 +/* Size of the AES-XTS is not derived from the architecture, but it is strictly 64 bytes */ +#define SIZE_OF_AES_XTS_PRNG 64 + #endif /* PRNG_H_ */