Merge branch 'master' into kernel-aes-ni

This commit is contained in:
PartialVolume
2025-11-26 21:14:23 +00:00
committed by GitHub
25 changed files with 875 additions and 327 deletions

View File

@@ -1,6 +1,11 @@
RELEASE NOTES
=============
v0.39
-----------------------
- Removed EXPERIMENTAL! comments for ALFG and Xoroshiro. [#652](https://github.com/martijnvanbrummelen/nwipe/pull/652) Thanks @Knogle
- Fix: some declaration changes to satisfy gcc 15. [#663]((https://github.com/martijnvanbrummelen/nwipe/pull/663) Thanks @Knogle
v0.38
-----------------------
includes the following changes:

View File

@@ -19,25 +19,26 @@ nwipe is a program that will securely erase the entire contents of disks. It can
## Erasure methods
The user can select from a variety of recognised secure erase methods which include:
* Fill With Zeros - Fills the device with zeros (0x00), one round only.
* Fill With Ones - Fills the device with ones (0xFF), one round only.
* RCMP TSSIT OPS-II - Royal Candian Mounted Police Technical Security Standard, OPS-II
* Fill With Zeros - Fills the device with zeros (0x00).
* Fill With Ones - Fills the device with ones (0xFF).
* RCMP TSSIT OPS-II - Royal Canadian Mounted Police Technical Security Standard, OPS-II.
* DoD Short - The American Department of Defense 5220.22-M short 3 pass wipe (passes 1, 2 & 7).
* DoD 5220.22M - The American Department of Defense 5220.22-M full 7 pass wipe.
* Gutmann Wipe - Peter Gutmann's method (Secure Deletion of Data from Magnetic and Solid-State Memory).
* PRNG Stream - Fills the device with a stream from the PRNG.
* Verify Zeros - This method only reads the device and checks that it is filled with zeros (0x00).
* Verify Ones - This method only reads the device and checks that it is filled with ones (0xFF).
* HMG IS5 enhanced - Secure Sanitisation of Protectively Marked Information or Sensitive Information
* HMG IS5 enhanced - Secure Sanitisation of Protectively Marked Information or Sensitive Information.
* Schneier Wipe - Bruce Schneier's method (7-pass mixed pattern).
nwipe also includes the following pseudo random number generators (prng):
nwipe also includes the following pseudo random number generators (PRNG):
* Mersenne Twister
* ISAAC
In addition to the above, the following prngs will be available in v0.37
* ISAAC-64
* Additive Lagged Fibonacci Generator
* XORoshiro-256
* Lagged Fibonacci
* AES-CTR (openssl)
In addition to the above, the following PRNG will be available in future versions:
* AES-256-CTR
These can be used to overwrite a drive with a stream of randomly generated characters.
@@ -46,13 +47,13 @@ nwipe can be found in many [Linux distro repositories](#which-linux-distro-uses-
nwipe is also included in [ShredOS](https://github.com/PartialVolume/shredos.x86_64) which was developed in particular to showcase nwipe as a fast-to-boot standalone method similar to DBAN. ShredOS always contains the latest nwipe version.
## Limitations regarding solid state drives
In the current form nwipe does not sanitize solid state drives (hereinafter referred to as SSDs)
of any form (SAS / Sata / NVME) and / or form factor (2.5" / 3.5" / PCI) fully due to their nature:
In the current form nwipe does not sanitize solid-state drives (hereinafter referred to as SSDs)
of any form (SAS / SATA / NVMe) and / or form factor (2.5" / 3.5" / PCI) fully due to their nature:
SSDs, as the transistors contained in the memory modules are subject to wear, contain in most cases
additional memory modules installed as failover for broken sectors outside
of the host accessible space (frequently referred to as "overprovisioning") and for garbage collection.
Some manufacturers reserve access to these areas only to disk's own controller and firmware.
It is therefor always advised to use nwipe / shredOS in conjunction with the manufacturer's or hardware vendor's own tools for sanitization to assure
It is therefor always advised to use nwipe / ShredOS in conjunction with the manufacturer's or hardware vendor's own tools for sanitization to assure
full destruction of the information contained on the disk.
Given that most vendors and manufacturers do not provide open source tools, it is advised to validate the outcome by comparing the data on the disk before and after sanitization.
A list of the most common tools and instructions for SSD wipes can be found in the [SSD Guide](ssd-guide.md).
@@ -114,7 +115,7 @@ yum install coreutils
yum install smartmontools
yum install hdparm
```
Note. The following programs are optionally installed although recommended. 1. dmidecode 2. readlink 3. smartmontools.
Note: The following programs are optionally installed although recommended. 1. dmidecode 2. readlink 3. smartmontools.
#### hdparm [REQUIRED]
hdparm provides some of the information regarding disk size in sectors as related to the host protected area (HPA) and device configuration overlay (DCO). We do however have our own function that directly access the DCO to obtain the 'real max sectors' so reliance on hdparm may be removed at a future date.
@@ -145,7 +146,7 @@ make
make install
```
Then run nwipe !
Then run nwipe!
```
cd src
sudo ./nwipe
@@ -184,9 +185,9 @@ Once done with your coding then the released/patch/fixed code can be compiled, w
## Automating the download and compilation process for Debian based distros.
Here's a script that will do just that! It will create a directory in your home folder called 'nwipe_master'. It installs all the libraries required to compile the software (build-essential) and all the libraries that nwipe requires (libparted etc). It downloads the latest master copy of nwipe from github. It then compiles the software and then runs the latest nwipe. It doesn't write over the version of nwipe that's installed in the repository (If you had nwipe already installed). To run the latest master version of nwipe manually you would run it like this `sudo ~/nwipe_master/nwipe/src/nwipe`
Here's a script that will do just that! It will create a directory in your home folder called 'nwipe_master'. It installs all the libraries required to compile the software (build-essential) and all the libraries that nwipe requires (libparted etc). It downloads the latest master copy of nwipe from GitHub. It then compiles the software and then runs the latest nwipe. It doesn't write over the version of nwipe that's installed in the repository (If you had nwipe already installed). To run the latest master version of nwipe manually you would run it like this `sudo ~/nwipe_master/nwipe/src/nwipe`
You can run the script multiple times; the first time it's run it will install all the libraries; subsequent times it will just say the libraries are up to date. As it always downloads a fresh copy of the nwipe master from Github, you can always stay up to date. Just run it to get the latest version of nwipe. It only takes 11 seconds to compile on my i7.
You can run the script multiple times; the first time it's run it will install all the libraries; subsequent times it will just say the libraries are up to date. As it always downloads a fresh copy of the nwipe master from GitHub, you can always stay up to date. Just run it to get the latest version of nwipe. It only takes 11 seconds to compile on my i7.
If you already have nwipe installed from the repository, you need to take care which version you are running. If you typed `nwipe` from any directory it will always run the original repository copy of nwipe. To run the latest nwipe you have to explicitly tell it where the new copy is, e.g in the directory `~/nwipe_master/nwipe/src`. That's why you would run it by typing `sudo ~/nwipe_master/nwipe/src/nwipe` alternatively you could cd to the directory and run it like this:

View File

@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
AC_INIT([nwipe],[0.38],[git@brumit.nl])
AC_INIT([nwipe],[0.39],[git@brumit.nl])
AM_INIT_AUTOMAKE(foreign subdir-objects)
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile])
AC_OUTPUT

View File

@@ -1,4 +1,4 @@
.TH NWIPE "8" "Jan 2025" "nwipe version 0.38" "User Commands"
.TH NWIPE "8" "Sep 2025" "nwipe version 0.39" "User Commands"
.SH NAME
nwipe \- securely erase disks
.SH SYNOPSIS
@@ -6,28 +6,30 @@ nwipe \- securely erase disks
[\fIoptions\fR] [\fIdevice1\fR] [\fIdevice2\fR] ...
.SH DESCRIPTION
nwipe is a command that will securely erase disks using a variety of
recognised methods. It is a fork of the dwipe command used by Darik's Boot
and Nuke (dban). nwipe is included with partedmagic if you want a quick and
recognized methods. It is a fork of the dwipe command used by Darik's Boot
and Nuke (DBAN). nwipe is included with partedmagic if you want a quick and
easy bootable CD version. nwipe was created out of a need to run the DBAN
dwipe command outside of DBAN, in order to allow its use with any host
distribution, thus giving better hardware support. It is essentially the
same as dwipe, with a few changes:
.TP
- pthreads is used instead of fork
- pthreads is used instead of fork.
.TP
- The parted library is used to detect drives
- The parted library is used to detect drives.
.TP
- The code is designed to be compiled with gcc
- The code is designed to be compiled with gcc.
.TP
- SIGUSR1 can be used to log the stats of the current wipe
- SIGUSR1 can be used to log the stats of the current wipe.
.TP
- Additional wiping methods and PRNGs.
.SH OPTIONS
.TP
\fB\-V\fR, \fB\-\-version\fR
Prints the version number
Prints the version number.
.TP
\fB\-h\fR, \fB\-\-help\fR
Prints a help summary
Prints a help summary.
.TP
\fB\-\-autonuke\fR
If no devices have been specified on the command line, starts wiping all
@@ -39,17 +41,17 @@ Power off system on completion of wipe delayed for one minute. During
this one minute delay you can abort the shutdown by typing sudo shutdown -c
.TP
\fB\-\-sync\fR=\fINUM\fR
Will perform a syn after NUM writes (default: 100000)
Will perform a syn after NUM writes (default: 100000).
.IP
0 \- fdatasync after the disk is completely written
fdatasync errors not detected until completion.
0 is not recommended as disk errors may cause nwipe
to appear to hang
to appear to hang.
.IP
1 \- fdatasync after every write
1 \- fdatasync after every write.
Warning: Lower values will reduce wipe speeds.
.IP
1000 \- fdatasync after 1000 writes
1000 \- fdatasync after 1000 writes.
.TP
\fB\-\-noblank\fR
Do not perform the final blanking pass after the wipe (default is to blank,
@@ -70,17 +72,20 @@ Do not show the GUI interface. Can only be used with the autonuke option.
Nowait option is automatically invoked with the nogui option.
SIGUSR1 can be used to retrieve the current wiping statistics.
.TP
\fB\-\-pdftag\fR
Enables a field on the PDF that holds a tag that identifies the host computer
.TP
\fB\-v\fR, \fB\-\-verbose\fR
Log more messages, useful for debugging.
.TP
\fB\-\-verify\fR=\fITYPE\fR
Whether to perform verification of erasure (default: last)
Whether to perform verification of erasure (default: last).
.IP
off \- Do not verify
off \- Do not verify.
.IP
last \- Verify after the last pass
last \- Verify after the last pass.
.IP
all \- Verify every pass
all \- Verify every pass.
.IP
Please mind that HMG IS5 enhanced always verifies the last (PRNG) pass
regardless of this option.
@@ -92,24 +97,26 @@ dod522022m / dod \- 7 pass DOD 5220.22\-M method
.IP
dodshort / dod3pass \- 3 pass DOD method
.IP
gutmann \- Peter Gutmann's Algorithm
gutmann \- Peter Gutmann's algorithm
.IP
ops2 \- RCMP TSSIT OPS\-II
.IP
random / prng / stream \- PRNG Stream
.IP
zero / quick \- Overwrite with zeros 0x00
zero / quick \- Overwrite with zeros (0x00)
.IP
one \- Overwrite with ones 0xFF
one \- Overwrite with ones (0xFF)
.IP
verify_zero \- Verifies disk is zero filled
verify_zero \- Verifies disk is zero (0x00) filled
.IP
verify_one \- Verifies disk is 0xFF filled
verify_one \- Verifies disk is one (0xFF) filled
.IP
is5enh \- HMG IS5 enhanced
.IP
bruce7 \- Schneier Bruce 7-pass mixed pattern
.TP
\fB\-l\fR, \fB\-\-logfile\fR=\fIFILE\fR
Filename to log to. Default is STDOUT
Filename to log to. Default is STDOUT.
.TP
\fB\-P\fR, \fB\-\-PDFreportpath\fR=\fIDIR\fR
Directory to write the PDF nwipe reports/certificates to.
@@ -117,15 +124,16 @@ Defaults to ".".
If \fIDIR\fR is set to \fInoPDF\fR no report PDF files are written.
.TP
\fB\-p\fR, \fB\-\-prng\fR=\fIMETHOD\fR
PRNG option (mersenne|twister|isaac|isaac64)
The PRNG option (default: xoroshiro256_prng).
(mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng|xoroshiro256_prng)
.TP
\fB\-q\fR, \fB\-\-quiet\fR
Anonymize serial numbers, Gui & logs display:
Anonymize serial numbers, GUI & logs display:
XXXXXXXX = S/N obtained & anonymized.
???????? = S/N not available.
.TP
\fB\-r\fR, \fB\-\-rounds\fR=\fINUM\fR
Number of times to wipe the device using the selected method (default: 1)
Number of times to wipe the device using the selected method (default: 1).
.TP
\fB\-e\fR, \fB\-\-exclude\fR=\fIDEVICES\fR
Up to ten comma separated devices to be excluded, examples:
@@ -133,10 +141,10 @@ Up to ten comma separated devices to be excluded, examples:
--exclude=/dev/sdc,/dev/sdd
--exclude=/dev/sdc,/dev/sdd,/dev/mapper/cryptswap1
.SH BUGS
Please see the GitHub site for the latest list
Please see the GitHub site for the latest list:
(https://github.com/martijnvanbrummelen/nwipe/issues)
.SH AUTHOR
Nwipe is developed by Martijn van Brummelen <github@brumit.nl>
nwipe is developed by Martijn van Brummelen <github@brumit.nl>.
.SH "SEE ALSO"
.BR shred (1),
.BR dwipe (1),

View File

@@ -20,6 +20,9 @@
* 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.
*
* Actually it uses subtraction as the core operation, making it conceptually closer to a
* "Subtractive Lagged Fibonacci Generator" (SLFG) variant, but well..
*
* Note: This implementation is designed for non-cryptographic applications and should not be
* used where cryptographic security is required.
*/

View File

@@ -122,6 +122,7 @@ int nwipe_conf_init()
*/
nwipe_conf_populate( "PDF_Certificate.PDF_Enable", "ENABLED" );
nwipe_conf_populate( "PDF_Certificate.PDF_Preview", "DISABLED" );
nwipe_conf_populate( "PDF_Certificate.PDF_tag", "DISABLED" );
/**
* The currently selected customer that will be printed on the report

View File

@@ -82,6 +82,12 @@ typedef struct nwipe_speedring_t_
// 20 chracters for serial number plus null Byte
#define NWIPE_SERIALNUMBER_LENGTH 20
// UUID size
#define UUID_SIZE 40
// Device name max size including /dev/ path
#define DEVICE_NAME_MAX_SIZE 100
typedef struct nwipe_context_t_
{
/*
@@ -99,8 +105,9 @@ typedef struct nwipe_context_t_
int device_minor; // The minor device number.
int device_part; // The device partition or slice number.
char* device_name; // The device file name.
char device_name_without_path[100];
char gui_device_name[100];
char device_name_without_path[DEVICE_NAME_MAX_SIZE];
char gui_device_name[DEVICE_NAME_MAX_SIZE];
char device_name_terse[DEVICE_NAME_MAX_SIZE];
unsigned long long device_size; // The device size in bytes.
u64 device_size_in_sectors; // The device size in number of logical sectors, this may be 512 or 4096 sectors
u64 device_size_in_512byte_sectors; // The device size in number of 512byte sectors, irrespective of logical sector
@@ -117,10 +124,10 @@ typedef struct nwipe_context_t_
int device_is_ssd; // 0 = no SSD, 1 = is a SSD
char device_serial_no[NWIPE_SERIALNUMBER_LENGTH
+ 1]; // Serial number(processed, 20 characters plus null termination) of the device.
char device_UUID[UUID_SIZE]; // Only populated with the UUID if device is a partition
int device_target; // The device target.
u64 eta; // The estimated number of seconds until method completion.
int entropy_fd; // The entropy source. Usually /dev/urandom.
int pass_count; // The number of passes performed by the working wipe method.
u64 pass_done; // The number of bytes that have already been i/o'd in this pass.
u64 pass_errors; // The number of errors across all passes.

View File

@@ -50,8 +50,9 @@
struct pdf_doc* pdf;
struct pdf_object* page;
char model_header[50] = ""; /* Model text in the header */
char serial_header[30] = ""; /* Serial number text in the header */
char model_header[55] = ""; /* Model text in the header */
char serial_header[35] = ""; /* Serial number text in the header */
char hostid_header[DMIDECODE_RESULT_LENGTH + 15] = ""; /* host identification, UUID, serial number, system tag */
char barcode[100] = ""; /* Contents of the barcode, i.e model:serial */
char pdf_footer[MAX_PDF_FOOTER_TEXT_LENGTH];
float height;
@@ -129,26 +130,20 @@ int create_pdf( nwipe_context_t* ptr )
/* Obtain page page_width */
page_width = pdf_page_width( page_1 );
/**********************************************
* Initialise serial no. to unknown if empty
*/
if( c->device_serial_no[0] == 0 )
{
snprintf( c->device_serial_no, sizeof( c->device_serial_no ), "Unknown" );
}
/*********************************************************************
* Create header and footer on page 1, with the exception of the green
* tick/red icon which is set from the 'status' section below
*/
pdf_add_text_wrap( pdf, NULL, pdf_footer, 12, 0, 30, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_line( pdf, NULL, 50, 50, 550, 50, 3, PDF_BLACK );
pdf_add_line( pdf, NULL, 50, 650, 550, 650, 3, PDF_BLACK );
pdf_add_image_data( pdf, NULL, 45, 665, 100, 100, bin2c_shred_db_jpg, 27063 );
pdf_set_font( pdf, "Helvetica-Bold" );
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Model", c->device_model );
pdf_add_text_wrap( pdf, NULL, model_header, 14, 0, 755, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "S/N", c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, serial_header, 14, 0, 735, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_set_font( pdf, "Helvetica" );
pdf_add_text_wrap( pdf, NULL, "Disk Erasure Report", 24, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( barcode, sizeof( barcode ), "%s:%s", c->device_model, c->device_serial_no );
pdf_add_text_wrap(
pdf, NULL, "Page 1 - Erasure Status", 14, 0, 670, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_barcode( pdf, NULL, PDF_BARCODE_128A, 100, 790, 400, 25, barcode, PDF_BLACK );
pdf_header_footer_text( c, "Page 1 - Erasure Status" );
/* ------------------------ */
/* Organisation Information */
@@ -243,10 +238,6 @@ int create_pdf( nwipe_context_t* ptr )
* Serial no.
*/
pdf_add_text( pdf, NULL, "Serial:", 12, 340, 410, PDF_GRAY );
if( c->device_serial_no[0] == 0 )
{
snprintf( c->device_serial_no, sizeof( c->device_serial_no ), "Unknown" );
}
pdf_set_font( pdf, "Helvetica-Bold" );
pdf_add_text( pdf, NULL, c->device_serial_no, text_size_data, 380, 410, PDF_BLACK );
pdf_set_font( pdf, "Helvetica" );
@@ -801,18 +792,19 @@ int create_pdf( nwipe_context_t* ptr )
* Create the reports filename
*
* Sanitize the strings that we are going to use to create the report filename
* by converting any non alphanumeric characters to an underscore or hyphon
* by converting any non alphanumeric characters to an underscore or hyphen
*/
replace_non_alphanumeric( end_time_text, '-' );
replace_non_alphanumeric( c->device_model, '_' );
replace_non_alphanumeric( c->device_serial_no, '_' );
snprintf( c->PDF_filename,
sizeof( c->PDF_filename ),
"%s/nwipe_report_%s_Model_%s_Serial_%s.pdf",
"%s/nwipe_report_%s_Model_%s_Serial_%s_device_%s.pdf",
nwipe_options.PDFreportpath,
end_time_text,
c->device_model,
c->device_serial_no );
c->device_serial_no,
c->device_name_terse );
pdf_save( pdf, c->PDF_filename );
pdf_destroy( pdf );
@@ -974,21 +966,7 @@ void create_header_and_footer( nwipe_context_t* c, char* page_title )
* Create header and footer on most recently added page, with the exception
* of the green tick/red icon which is set from the 'status' section below.
*/
pdf_add_text_wrap( pdf, NULL, pdf_footer, 12, 0, 30, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_line( pdf, NULL, 50, 50, 550, 50, 3, PDF_BLACK );
pdf_add_line( pdf, NULL, 50, 650, 550, 650, 3, PDF_BLACK );
pdf_add_image_data( pdf, NULL, 45, 665, 100, 100, bin2c_shred_db_jpg, 27063 );
pdf_set_font( pdf, "Helvetica-Bold" );
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Model", c->device_model );
pdf_add_text_wrap( pdf, NULL, model_header, 14, 0, 755, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "S/N", c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, serial_header, 14, 0, 735, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_set_font( pdf, "Helvetica" );
pdf_add_text_wrap( pdf, NULL, "Disk Erasure Report", 24, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( barcode, sizeof( barcode ), "%s:%s", c->device_model, c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, page_title, 14, 0, 670, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_barcode( pdf, NULL, PDF_BARCODE_128A, 100, 790, 400, 25, barcode, PDF_BLACK );
pdf_header_footer_text( c, page_title );
/**********************************************************
* Display the appropriate status icon, top right on page on
@@ -1019,3 +997,41 @@ void create_header_and_footer( nwipe_context_t* c, char* page_title )
break;
}
}
void pdf_header_footer_text( nwipe_context_t* c, char* page_title )
{
extern char dmidecode_system_serial_number[DMIDECODE_RESULT_LENGTH];
extern char dmidecode_system_uuid[DMIDECODE_RESULT_LENGTH];
pdf_add_text_wrap( pdf, NULL, pdf_footer, 12, 0, 30, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_line( pdf, NULL, 50, 50, 550, 50, 3, PDF_BLACK ); // Footer full width Line
pdf_add_line( pdf, NULL, 50, 650, 550, 650, 3, PDF_BLACK ); // Header full width Line
pdf_add_line( pdf, NULL, 175, 728, 425, 728, 3, PDF_BLACK ); // Header Page number, disk model divider line
pdf_add_image_data( pdf, NULL, 45, 665, 100, 100, bin2c_shred_db_jpg, 27063 );
pdf_set_font( pdf, "Helvetica-Bold" );
if( nwipe_options.PDFtag )
{
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Disk Model", c->device_model );
pdf_add_text_wrap( pdf, NULL, model_header, 11, 0, 710, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "Disk S/N", c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, serial_header, 11, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( hostid_header, sizeof( hostid_header ), " %s: %s ", "System S/N", dmidecode_system_serial_number );
pdf_add_text_wrap( pdf, NULL, hostid_header, 11, 0, 680, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( hostid_header, sizeof( hostid_header ), " %s: %s ", "System uuid", dmidecode_system_uuid );
pdf_add_text_wrap( pdf, NULL, hostid_header, 11, 0, 665, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
}
else
{
snprintf( model_header, sizeof( model_header ), " %s: %s ", "Disk Model", c->device_model );
pdf_add_text_wrap( pdf, NULL, model_header, 11, 0, 695, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( serial_header, sizeof( serial_header ), " %s: %s ", "Disk S/N", c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, serial_header, 11, 0, 680, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
}
pdf_set_font( pdf, "Helvetica" );
pdf_add_text_wrap( pdf, NULL, "Disk Erasure Report", 24, 0, 760, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
snprintf( barcode, sizeof( barcode ), "%s:%s", c->device_model, c->device_serial_no );
pdf_add_text_wrap( pdf, NULL, page_title, 14, 0, 740, PDF_BLACK, page_width, PDF_ALIGN_CENTER, &height );
pdf_add_barcode( pdf, NULL, PDF_BARCODE_128A, 100, 790, 400, 25, barcode, PDF_BLACK );
}

View File

@@ -49,4 +49,6 @@ int nwipe_get_smart_data( nwipe_context_t* );
void create_header_and_footer( nwipe_context_t*, char* );
void pdf_header_footer_text( nwipe_context_t*, char* );
#endif /* CREATE_PDF_H_ */

View File

@@ -26,7 +26,7 @@
void customer_processes( int );
void select_customers( int, char** );
void delete_customer();
void delete_customer( int, char** );
void add_customer();
void write_customer_csv_entry( char*, char*, char*, char* );
void delete_customer_csv_entry( int* );

View File

@@ -50,6 +50,119 @@
int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount );
char* trim( char* str );
/*
* Resolve a device path (including /dev/disk/by-* symlinks) to its
* underlying block device id (dev_t).
*
* Returns 0 on success and fills *out_rdev.
* Returns -1 on error or if the path is not a block device.
*/
static int nwipe_path_to_rdev( const char* path, dev_t* out_rdev )
{
struct stat st;
if( path == NULL || out_rdev == NULL )
{
errno = EINVAL;
return -1;
}
/*
* stat() follows symlinks by default, which is what we want for
* persistent names in /dev/disk/by-id, /dev/disk/by-path, etc.
*/
if( stat( path, &st ) != 0 )
{
return -1;
}
if( !S_ISBLK( st.st_mode ) )
{
/* Not a block device node. */
errno = ENOTBLK;
return -1;
}
*out_rdev = st.st_rdev;
return 0;
}
/*
* Check whether a candidate device node should be excluded based on the
* --exclude list. Matching is done primarily by device identity
* (major/minor via st_rdev), so persistent names like /dev/disk/by-id/*
* are safe. We keep legacy string-based matching as a fallback.
*
* Returns 1 if the candidate should be excluded, 0 otherwise.
*/
static int nwipe_is_excluded_device( const char* candidate_devnode )
{
dev_t cand_rdev;
int have_cand_rdev;
int i;
/* Try to resolve the candidate device to a dev_t. */
have_cand_rdev = ( nwipe_path_to_rdev( candidate_devnode, &cand_rdev ) == 0 );
for( i = 0; i < MAX_NUMBER_EXCLUDED_DRIVES; i++ )
{
const char* ex = nwipe_options.exclude[i];
dev_t ex_rdev;
int have_ex_rdev;
const char* base;
/* Empty slot in the exclude array. */
if( ex == NULL || ex[0] == 0 )
{
continue;
}
/*
* First try: both candidate and exclude entry resolve to block
* devices; compare device ids (major/minor).
*/
have_ex_rdev = ( nwipe_path_to_rdev( ex, &ex_rdev ) == 0 );
if( have_cand_rdev && have_ex_rdev && ex_rdev == cand_rdev )
{
nwipe_log( NWIPE_LOG_NOTICE, "Device %s excluded as per command line option -e", candidate_devnode );
return 1;
}
/*
* Fallback 1: exact string match. This keeps compatibility with
* older usage like --exclude=/dev/sda or --exclude=/dev/mapper/cryptswap1.
*/
if( strcmp( candidate_devnode, ex ) == 0 )
{
nwipe_log( NWIPE_LOG_NOTICE, "Device %s excluded as per command line option -e", candidate_devnode );
return 1;
}
/*
* Fallback 2: match against the basename only, so that an
* exclude entry like "sda" still works even if the full path is
* /dev/sda.
*/
base = strrchr( candidate_devnode, '/' );
if( base != NULL )
{
base++;
}
else
{
base = candidate_devnode;
}
if( strcmp( base, ex ) == 0 )
{
nwipe_log( NWIPE_LOG_NOTICE, "Device %s excluded as per command line option -e", candidate_devnode );
return 1;
}
}
return 0;
}
extern int terminate_signal;
int nwipe_device_scan( nwipe_context_t*** c )
@@ -138,15 +251,11 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
bus = 0;
/* Check whether this drive is on the excluded drive list ? */
idx = 0;
while( idx < MAX_NUMBER_EXCLUDED_DRIVES )
/* Check whether this drive is on the excluded drive list. */
if( nwipe_is_excluded_device( dev->path ) )
{
if( !strcmp( dev->path, nwipe_options.exclude[idx++] ) )
{
nwipe_log( NWIPE_LOG_NOTICE, "Device %s excluded as per command line option -e", dev->path );
return 0;
}
/* Already logged inside nwipe_is_excluded_device(). */
return 0;
}
/* Check whether the user has specified using the --nousb option
@@ -216,6 +325,19 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
/* remove /dev/ from device, right justify and prefix name so string length is eight characters */
nwipe_strip_path( next_device->device_name_without_path, next_device->device_name );
const char* device_name_terse;
device_name_terse = skip_whitespace( next_device->device_name_without_path );
if( device_name_terse != NULL )
{
/* remove the leading whitespace and save result, we use the device without path and no leading or trailing
* space in pdf file creation later */
strcpy( next_device->device_name_terse, device_name_terse );
}
else
{
strcpy( next_device->device_name_terse, "_" );
}
/* To maintain column alignment in the gui we have to remove /dev/ from device names that
* exceed eight characters including the /dev/ path.
*/
@@ -428,6 +550,20 @@ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount )
hpa_dco_status( next_device );
}
/*************************************
* Check whether the device has a UUID
*/
char uuid[UUID_SIZE] = "";
if( get_device_uuid( next_device->device_name, uuid ) == 0 )
{
strncpy( next_device->device_UUID, uuid, UUID_SIZE );
nwipe_log( NWIPE_LOG_INFO, "UUID for %s is: %s\n", next_device->device_name, next_device->device_UUID );
}
else
{
nwipe_log( NWIPE_LOG_INFO, "No UUID available for %s\n", next_device->device_name );
}
/* print an empty line to separate the drives in the log */
nwipe_log( NWIPE_LOG_INFO, " " );

342
src/gui.c
View File

@@ -1722,27 +1722,27 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"The Mersenne Twister, by Makoto Matsumoto and Takuji Nishimura, is a " );
"The Mersenne Twister, by Makoto Matsumoto and Takuji Nishimura, is a " );
mvwprintw( main_window,
yy++,
tab1,
"generalized feedback shift register PRNG that is uniform and " );
"generalized feedback shift register PRNG that is uniform and " );
mvwprintw( main_window,
yy++,
tab1,
"equidistributed in 623-dimensions with a proven period of 2^19937-1. " );
"equidistributed in 623-dimensions with a proven period of 2^19937-1. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
" " );
mvwprintw( main_window,
yy++,
tab1,
"This implementation passes the Marsaglia Diehard test suite. " );
"This implementation passes the Marsaglia Diehard test suite. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
" " );
break;
case 1:
@@ -1750,23 +1750,23 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"ISAAC, by Bob Jenkins, is a PRNG derived from RC4 with a minimum period of " );
"ISAAC, by Bob Jenkins, is a PRNG derived from RC4 with a minimum period of " );
mvwprintw( main_window,
yy++,
tab1,
"2^40 and an expected period of 2^8295. It is difficult to recover the " );
"2^40 and an expected period of 2^8295. It is difficult to recover the " );
mvwprintw( main_window,
yy++,
tab1,
"initial PRNG state by cryptanalysis of the ISAAC stream. " );
"initial PRNG state by cryptanalysis of the ISAAC stream. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
" " );
mvwprintw( main_window,
yy++,
tab1,
"Performs best on a 32-bit CPU. Use ISAAC-64 if this system has a 64-bit CPU." );
"Performs best on a 32-bit CPU. Use ISAAC-64 if this system has a 64-bit CPU. " );
break;
case 2:
@@ -1774,23 +1774,23 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"ISAAC-64, by Bob Jenkins, is like 32-bit ISAAC, but with a minimum period of" );
"ISAAC-64, by Bob Jenkins, is like 32-bit ISAAC, but with a minimum period of " );
mvwprintw( main_window,
yy++,
tab1,
"2^77 and an expected period of 2^16583. It is difficult to recover the " );
"2^77 and an expected period of 2^16583. It is difficult to recover the " );
mvwprintw( main_window,
yy++,
tab1,
"initial PRNG state by cryptanalysis of the ISAAC-64 stream. " );
"initial PRNG state by cryptanalysis of the ISAAC-64 stream. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
" " );
mvwprintw( main_window,
yy++,
tab1,
"Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " );
"Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " );
break;
case 3:
@@ -1798,11 +1798,11 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"ALFG (Additive Lagged Fibonacci Generator), is a class of PRNGs utilizing" );
"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" );
"the Fibonacci sequence with additive operations between lagged values. While " );
mvwprintw( main_window,
yy++,
tab1,
@@ -1810,31 +1810,31 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"that they provide lower levels of security, making them less suitable for" );
"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" );
"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" );
"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. " );
"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" );
"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. " );
"applications requiring long sequences with a good speed-randomness trade-off. " );
break;
case 4:
@@ -1842,47 +1842,47 @@ void nwipe_gui_prng( void )
mvwprintw( main_window,
yy++,
tab1,
"Xoroshiro256**, originally designed by David Blackman and Sebastiano Vigna" );
"XORoshiro256**, originally designed by David Blackman and Sebastiano Vigna " );
mvwprintw( main_window,
yy++,
tab1,
"for 128 bits, was adapted to 256 bits by Fabian Druschke. This adaptation " );
"for 128 bits, was adapted to 256 bits by Fabian Druschke. This adaptation " );
mvwprintw( main_window,
yy++,
tab1,
"enhances its capability for fast, high-quality generation of pseudo-random " );
"enhances its capability for fast, high-quality generation of pseudo-random " );
mvwprintw( main_window,
yy++,
tab1,
"numbers with a state size of 256 bits. It boasts an extremely long period " );
"numbers with a state size of 256 bits. It boasts an extremely long period " );
mvwprintw( main_window,
yy++,
tab1,
"of 2^256-1 without sacrificing performance, suitable for a wide range of " );
"of 2^256-1 without sacrificing performance, suitable for a wide range of " );
mvwprintw( main_window,
yy++,
tab1,
"applications. " );
"applications. " );
mvwprintw( main_window,
yy++,
tab1,
" " );
" " );
mvwprintw( main_window,
yy++,
tab1,
"The simple arithmetic operations (shifts, rotations, and XORs) of " );
"The simple arithmetic operations (shifts, rotations, and XORs) of " );
mvwprintw( main_window,
yy++,
tab1,
"Xoroshiro256** ensure low computational complexity. This, combined with " );
"XORoshiro256** ensure low computational complexity. This, combined with " );
mvwprintw( main_window,
yy++,
tab1,
"the adaptation for 256 bits by Fabian Druschke, allows efficient use " );
"the adaptation for 256 bits by Fabian Druschke, allows efficient use " );
mvwprintw( main_window,
yy++,
tab1,
"especially for legacy systems, due to its efficiency and minimal demands. " );
"especially for legacy systems, due to its efficiency and minimal demands. " );
break;
case 5:
mvwprintw(
@@ -2339,7 +2339,7 @@ void nwipe_gui_method( void )
extern int terminate_signal;
/* The number of implemented methods. */
const int count = 11;
const int count = 12;
/* The first tabstop. */
const int tab1 = 2;
@@ -2405,6 +2405,10 @@ void nwipe_gui_method( void )
{
focus = 10;
}
if( nwipe_options.method == &nwipe_bmb )
{
focus = 11;
}
do
{
@@ -2428,6 +2432,7 @@ void nwipe_gui_method( void )
mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_verify_one ) );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_is5enh ) );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_bruce7 ) );
mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_bmb ) );
mvwprintw( main_window, yy++, tab1, " " );
/* Print the cursor. */
@@ -2439,105 +2444,101 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 2, tab2, "Security Level: high (1 pass)" );
mvwprintw( main_window, 4, tab2, "This method fills the device with zeros. Note " );
mvwprintw( main_window, 5, tab2, "that the rounds option does not apply to this " );
mvwprintw( main_window, 6, tab2, "method. This method always runs one round. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "There is no publicly available evidence that " );
mvwprintw( main_window, 9, tab2, "data can be recovered from a modern traditional " );
mvwprintw( main_window, 10, tab2, "hard drive (HDD) that has been zero wiped, " );
mvwprintw( main_window, 11, tab2, "however a wipe that includes a prng may be " );
mvwprintw( main_window, 12, tab2, "preferable. " );
mvwprintw( main_window, 4, tab2, "This method fills the device with zeros. " );
mvwprintw( main_window, 5, tab2, " " );
mvwprintw( main_window, 6, tab2, "There is no publicly available evidence that " );
mvwprintw( main_window, 7, tab2, "data can be recovered from a modern traditional " );
mvwprintw( main_window, 8, tab2, "hard drive (HDD) that has been zero wiped, " );
mvwprintw( main_window, 9, tab2, "however a wipe that includes a PRNG may be " );
mvwprintw( main_window, 10, tab2, "preferable. " );
break;
case 1:
mvwprintw( main_window, 2, tab2, "Security Level: high (1 pass)" );
mvwprintw( main_window, 4, tab2, "This method fills the device with ones. Note that" );
mvwprintw( main_window, 5, tab2, "the rounds option does not apply to this method. " );
mvwprintw( main_window, 6, tab2, "This method always runs one round. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "This method might be used when wiping a solid " );
mvwprintw( main_window, 9, tab2, "state drive if an additional level of security is" );
mvwprintw( main_window, 10, tab2, "required beyond using the drives internal secure " );
mvwprintw( main_window, 11, tab2, "erase features. Alternatively PRNG may be " );
mvwprintw( main_window, 12, tab2, "preferable. " );
mvwprintw( main_window, 4, tab2, "This method fills the device with ones. " );
mvwprintw( main_window, 5, tab2, " " );
mvwprintw( main_window, 6, tab2, "This method might be used when wiping a solid " );
mvwprintw( main_window, 7, tab2, "state drive if an additional level of security is " );
mvwprintw( main_window, 8, tab2, "required beyond using the drives internal secure " );
mvwprintw( main_window, 9, tab2, "erase features. Alternatively PRNG may be " );
mvwprintw( main_window, 10, tab2, "preferable. " );
break;
case 2:
mvwprintw( main_window, 2, tab2, "Security Level: higher (8 passes)" );
mvwprintw( main_window, 4, tab2, "The Royal Canadian Mounted Police Technical " );
mvwprintw( main_window, 5, tab2, "Security Standard for Information Technology. " );
mvwprintw( main_window, 6, tab2, "Appendix OPS-II: Media Sanitization. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "This implementation, with regards to paragraph 2 " );
mvwprintw( main_window, 9, tab2, "section A of the standard, uses a pattern that is" );
mvwprintw( main_window, 10, tab2, "one random byte and that is changed each round. " );
mvwprintw( main_window, 4, tab2, "The Royal Canadian Mounted Police Technical " );
mvwprintw( main_window, 5, tab2, "Security Standard for Information Technology. " );
mvwprintw( main_window, 6, tab2, "Appendix OPS-II: Media Sanitization. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "This implementation, with regards to paragraph 2 " );
mvwprintw( main_window, 9, tab2, "section A of the standard, uses a pattern that is " );
mvwprintw( main_window, 10, tab2, "one random byte and that is changed each round. " );
break;
case 3:
mvwprintw( main_window, 2, tab2, "Security Level: higher (3 passes)" );
mvwprintw( main_window, 4, tab2, "The US Department of Defense 5220.22-M short wipe" );
mvwprintw( main_window, 5, tab2, "This method is composed of passes 1, 2 & 7 from " );
mvwprintw( main_window, 6, tab2, "the standard DoD 5220.22-M wipe. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "Pass 1: A random character " );
mvwprintw( main_window, 9, tab2, "Pass 2: The bitwise complement of pass 1. " );
mvwprintw( main_window, 10, tab2, "Pass 3: A random number generated data stream " );
mvwprintw( main_window, 4, tab2, "The US Department of Defense 5220.22-M short wipe." );
mvwprintw( main_window, 5, tab2, "This method is composed of passes 1, 2 & 7 from " );
mvwprintw( main_window, 6, tab2, "the standard DoD 5220.22-M wipe. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "Pass 1: A random character. " );
mvwprintw( main_window, 9, tab2, "Pass 2: The bitwise complement of pass 1. " );
mvwprintw( main_window, 10, tab2, "Pass 3: A random number generated data stream. " );
break;
case 4:
mvwprintw( main_window, 2, tab2, "Security Level: higher (7 passes)" );
mvwprintw( main_window, 3, tab2, "The American Department of Defense 5220.22-M " );
mvwprintw( main_window, 4, tab2, "standard wipe. " );
mvwprintw( main_window, 5, tab2, " " );
mvwprintw( main_window, 6, tab2, "Pass 1: A Random character " );
mvwprintw( main_window, 7, tab2, "Pass 2: The bitwise complement of pass 1 " );
mvwprintw( main_window, 8, tab2, "Pass 3: A random number generated data stream " );
mvwprintw( main_window, 9, tab2, "Pass 4: A Random character " );
mvwprintw( main_window, 10, tab2, "Pass 5: A Random character " );
mvwprintw( main_window, 11, tab2, "Pass 6: The bitwise complement of pass 5 " );
mvwprintw( main_window, 12, tab2, "Pass 7: A random number generated data stream " );
mvwprintw( main_window, 3, tab2, "The American Department of Defense 5220.22-M " );
mvwprintw( main_window, 4, tab2, "standard wipe. " );
mvwprintw( main_window, 5, tab2, " " );
mvwprintw( main_window, 6, tab2, "Pass 1: A random character. " );
mvwprintw( main_window, 7, tab2, "Pass 2: The bitwise complement of pass 1. " );
mvwprintw( main_window, 8, tab2, "Pass 3: A random number generated data stream. " );
mvwprintw( main_window, 9, tab2, "Pass 4: A random character. " );
mvwprintw( main_window, 10, tab2, "Pass 5: A random character. " );
mvwprintw( main_window, 11, tab2, "Pass 6: The bitwise complement of pass 5. " );
mvwprintw( main_window, 12, tab2, "Pass 7: A random number generated data stream. " );
break;
case 5:
mvwprintw( main_window, 2, tab2, "Security Level: Paranoid ! (35 passes) " );
mvwprintw( main_window, 3, tab2, "Don't waste your time with this on a modern drive" );
mvwprintw( main_window, 2, tab2, "Security Level: Paranoid ! (35 passes) " );
mvwprintw( main_window, 3, tab2, "Don't waste your time with this on a modern drive!" );
mvwprintw( main_window, 5, tab2, "This is the method described by Peter Gutmann in " );
mvwprintw( main_window, 6, tab2, "the paper entitled \"Secure Deletion of Data from" );
mvwprintw( main_window, 7, tab2, "Magnetic and Solid-State Memory\", however not " );
mvwprintw( main_window, 8, tab2, "relevant in regards to modern hard disk drives. " );
mvwprintw( main_window, 5, tab2, "This is the method described by Peter Gutmann in " );
mvwprintw( main_window, 6, tab2, "the paper entitled \"Secure Deletion of Data from " );
mvwprintw( main_window, 7, tab2, "Magnetic and Solid-State Memory\", however not " );
mvwprintw( main_window, 8, tab2, "relevant in regards to modern hard disk drives. " );
break;
case 6:
mvwprintw( main_window, 2, tab2, "Security Level: Depends on Rounds" );
mvwprintw( main_window, 4, tab2, "This method fills the device with a stream from " );
mvwprintw( main_window, 5, tab2, "the PRNG. It is probably the best method to use " );
mvwprintw( main_window, 6, tab2, "on modern hard disk drives due to variation in " );
mvwprintw( main_window, 7, tab2, "encoding methods. " );
mvwprintw( main_window, 8, tab2, " " );
mvwprintw( main_window, 9, tab2, "This method has a high security level with 1 " );
mvwprintw( main_window, 10, tab2, "round and an increasingly higher security level " );
mvwprintw( main_window, 11, tab2, "as rounds are increased." );
mvwprintw( main_window, 4, tab2, "This method fills the device with a stream from " );
mvwprintw( main_window, 5, tab2, "the PRNG. It is probably the best method to use " );
mvwprintw( main_window, 6, tab2, "on modern hard disk drives due to variation in " );
mvwprintw( main_window, 7, tab2, "encoding methods. " );
mvwprintw( main_window, 8, tab2, " " );
mvwprintw( main_window, 9, tab2, "This method has a high security level with 1 " );
mvwprintw( main_window, 10, tab2, "round and an increasingly higher security level " );
mvwprintw( main_window, 11, tab2, "as rounds are increased. " );
break;
case 7:
mvwprintw( main_window, 2, tab2, "Security Level: Not applicable" );
mvwprintw( main_window, 4, tab2, "This method only reads the device and checks " );
mvwprintw( main_window, 5, tab2, "that it is all zero. " );
mvwprintw( main_window, 4, tab2, "This method only reads the device and checks " );
mvwprintw( main_window, 5, tab2, "that it is all zeros (0x00). " );
break;
@@ -2545,8 +2546,8 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 2, tab2, "Security Level: Not applicable" );
mvwprintw( main_window, 4, tab2, "This method only reads the device and checks " );
mvwprintw( main_window, 5, tab2, "that it is all ones (0xFF)." );
mvwprintw( main_window, 4, tab2, "This method only reads the device and checks " );
mvwprintw( main_window, 5, tab2, "that it is all ones (0xFF). " );
break;
@@ -2554,14 +2555,14 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 2, tab2, "Security Level: higher (3 passes)" );
mvwprintw( main_window, 4, tab2, "HMG IA/IS 5 (Infosec Standard 5): Secure " );
mvwprintw( main_window, 5, tab2, "Sanitisation of Protectively Marked Information " );
mvwprintw( main_window, 6, tab2, "or Sensitive Information " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "This method fills the device with 0s, then with " );
mvwprintw( main_window, 9, tab2, "1s, then with a PRNG stream, then reads the " );
mvwprintw( main_window, 10, tab2, "device to verify the PRNG stream was " );
mvwprintw( main_window, 11, tab2, "successfully written. " );
mvwprintw( main_window, 4, tab2, "U.K. HMG IA/IS 5 (Infosec Standard 5): Secure " );
mvwprintw( main_window, 5, tab2, "Sanitisation of Protectively Marked Information " );
mvwprintw( main_window, 6, tab2, "or Sensitive Information. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "Pass 1 : Zeros (0x00). " );
mvwprintw( main_window, 9, tab2, "Pass 2 : Ones (0xFF). " );
mvwprintw( main_window, 10, tab2, "Pass 3 : A random number generated data stream. " );
mvwprintw( main_window, 11, tab2, "Pass 4 : Last Pass Verification of PRNG stream " );
break;
case 10:
@@ -2570,12 +2571,27 @@ void nwipe_gui_method( void )
mvwprintw( main_window, 4, tab2, "Bruce Schneier 7-Pass Wiping Method: " );
mvwprintw( main_window, 5, tab2, "A secure erasure technique developed by the " );
mvwprintw( main_window, 6, tab2, "renowned cryptographer Bruce Schneier. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "This method first overwrites the device with " );
mvwprintw( main_window, 9, tab2, "ones (0xFF), followed by zeroes (0x00). Then, " );
mvwprintw( main_window, 9, tab2, "ones (0xFF), followed by zeros (0x00). Then, " );
mvwprintw( main_window, 10, tab2, "it performs five additional passes of PRNG- " );
mvwprintw( main_window, 11, tab2, "generated random data to maximize security. " );
break;
case 11:
mvwprintw( main_window, 2, tab2, "Security Level: very high (6 passes)" );
mvwprintw( main_window, 4, tab2, "BMB21-2019 Chinese State Secrets Bureau standard " );
mvwprintw( main_window, 5, tab2, "Technical Requirement for Data Sanitization of " );
mvwprintw( main_window, 6, tab2, "Storage Media Involving State Secrets. " );
mvwprintw( main_window, 7, tab2, " " );
mvwprintw( main_window, 8, tab2, "Pass 1 : Ones (0xFF). " );
mvwprintw( main_window, 9, tab2, "Pass 2 : Zeros (0x00). " );
mvwprintw( main_window, 10, tab2, "Pass 3 : A random number generated data stream. " );
mvwprintw( main_window, 11, tab2, "Pass 4 : A random number generated data stream. " );
mvwprintw( main_window, 12, tab2, "Pass 5 : A random number generated data stream. " );
mvwprintw( main_window, 13, tab2, "Pass 6 : Ones (0xFF). " );
break;
} /* switch */
@@ -2675,6 +2691,10 @@ void nwipe_gui_method( void )
case 10:
nwipe_options.method = &nwipe_bruce7;
break;
case 11:
nwipe_options.method = &nwipe_bmb;
break;
}
} /* nwipe_gui_method */
@@ -2749,73 +2769,73 @@ void nwipe_gui_config( void )
mvwprintw( main_window, 2, tab2, "PDF Report = DISABLED" );
}
mvwprintw( main_window, 4, tab2, "Enable or Disable creation of the PDF " );
mvwprintw( main_window, 5, tab2, "report/certificate " );
mvwprintw( main_window, 4, tab2, "Enable or disable creation of the PDF " );
mvwprintw( main_window, 5, tab2, "report/certificate. " );
break;
case 1:
mvwprintw( main_window, 2, tab2, "PDF Report - Edit Organisation" );
mvwprintw( main_window, 2, tab2, "PDF Report - Edit Organisation " );
mvwprintw( main_window, 4, tab2, "This option allows you to edit details" );
mvwprintw( main_window, 5, tab2, "of the organisation that is performing" );
mvwprintw( main_window, 6, tab2, "the erasure. This includes: business " );
mvwprintw( main_window, 7, tab2, "name, business address, contact name " );
mvwprintw( main_window, 8, tab2, "and contact phone. " );
mvwprintw( main_window, 4, tab2, "This option allows you to edit details " );
mvwprintw( main_window, 5, tab2, "of the organisation that is performing " );
mvwprintw( main_window, 6, tab2, "the erasure. This includes: business " );
mvwprintw( main_window, 7, tab2, "name, business address, contact name " );
mvwprintw( main_window, 8, tab2, "and contact phone. " );
break;
case 2:
mvwprintw( main_window, 2, tab2, "PDF Report - Select Customer" );
mvwprintw( main_window, 2, tab2, "PDF Report - Select Customer " );
mvwprintw( main_window, 4, tab2, "Allows selection of a customer as " );
mvwprintw( main_window, 5, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 6, tab2, "information includes Name (This can be" );
mvwprintw( main_window, 7, tab2, "a personal or business name), address " );
mvwprintw( main_window, 8, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 9, tab2, " " );
mvwprintw( main_window, 10, tab2, "Customer data is located in: " );
mvwprintw( main_window, 11, tab2, "/etc/nwipe/nwipe_customers.csv " );
mvwprintw( main_window, 4, tab2, "Allows selection of a customer as " );
mvwprintw( main_window, 5, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 6, tab2, "information includes Name (This can be " );
mvwprintw( main_window, 7, tab2, "a personal or business name), address " );
mvwprintw( main_window, 8, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 9, tab2, " " );
mvwprintw( main_window, 10, tab2, "Customer data is located in: " );
mvwprintw( main_window, 11, tab2, "/etc/nwipe/nwipe_customers.csv " );
break;
case 3:
mvwprintw( main_window, 2, tab2, "PDF Report - Add Customer " );
mvwprintw( main_window, 2, tab2, "PDF Report - Add Customer " );
mvwprintw( main_window, 4, tab2, "This option allows you to add a new " );
mvwprintw( main_window, 5, tab2, "customer. A customer can be optionally" );
mvwprintw( main_window, 6, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 7, tab2, "information includes Name (This can be" );
mvwprintw( main_window, 8, tab2, "a personal or business name), address " );
mvwprintw( main_window, 9, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 10, tab2, " " );
mvwprintw( main_window, 11, tab2, "Customer data is saved in: " );
mvwprintw( main_window, 12, tab2, "/etc/nwipe/nwipe_customers.csv " );
mvwprintw( main_window, 4, tab2, "This option allows you to add a new " );
mvwprintw( main_window, 5, tab2, "customer. A customer can be optionally " );
mvwprintw( main_window, 6, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 7, tab2, "information includes Name (This can be " );
mvwprintw( main_window, 8, tab2, "a personal or business name), address " );
mvwprintw( main_window, 9, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 10, tab2, " " );
mvwprintw( main_window, 11, tab2, "Customer data is saved in: " );
mvwprintw( main_window, 12, tab2, "/etc/nwipe/nwipe_customers.csv " );
break;
case 4:
mvwprintw( main_window, 2, tab2, "PDF Report - Delete Customer " );
mvwprintw( main_window, 2, tab2, "PDF Report - Delete Customer " );
mvwprintw( main_window, 4, tab2, "This option allows you to delete a " );
mvwprintw( main_window, 5, tab2, "customer. A customer can be optionally" );
mvwprintw( main_window, 6, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 7, tab2, "information includes Name (This can be" );
mvwprintw( main_window, 8, tab2, "a personal or business name), address " );
mvwprintw( main_window, 9, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 10, tab2, " " );
mvwprintw( main_window, 11, tab2, "Customer data is saved in: " );
mvwprintw( main_window, 12, tab2, "/etc/nwipe/nwipe_customers.csv " );
mvwprintw( main_window, 4, tab2, "This option allows you to delete a " );
mvwprintw( main_window, 5, tab2, "customer. A customer can be optionally " );
mvwprintw( main_window, 6, tab2, "displayed on the PDF report. Customer " );
mvwprintw( main_window, 7, tab2, "information includes Name (This can be " );
mvwprintw( main_window, 8, tab2, "a personal or business name), address " );
mvwprintw( main_window, 9, tab2, "contact name and contact phone. " );
mvwprintw( main_window, 10, tab2, " " );
mvwprintw( main_window, 11, tab2, "Customer data is saved in: " );
mvwprintw( main_window, 12, tab2, "/etc/nwipe/nwipe_customers.csv " );
break;
case 5:
mvwprintw( main_window, 2, tab2, "PDF Report - Preview Organisation, " );
mvwprintw( main_window, 3, tab2, "Customer and Date/Time details " );
mvwprintw( main_window, 2, tab2, "PDF Report - Preview Organisation, " );
mvwprintw( main_window, 3, tab2, "Customer and Date/Time details " );
mvwprintw( main_window, 5, tab2, "This allows the above information to " );
mvwprintw( main_window, 6, tab2, "be checked prior to starting the wipe " );
mvwprintw( main_window, 7, tab2, "so that the information is correct on " );
mvwprintw( main_window, 8, tab2, "the pdf report. " );
mvwprintw( main_window, 5, tab2, "This allows the above information to " );
mvwprintw( main_window, 6, tab2, "be checked prior to starting the wipe " );
mvwprintw( main_window, 7, tab2, "so that the information is correct on " );
mvwprintw( main_window, 8, tab2, "the PDF report. " );
break;
case 6:
@@ -2828,22 +2848,22 @@ void nwipe_gui_config( void )
{
mvwprintw( main_window, 2, tab2, "Preview Org. & Customer at start = DISABLED" );
}
mvwprintw( main_window, 4, tab2, "A preview prior to the drive selection" );
mvwprintw( main_window, 5, tab2, "of the organisation that is performing" );
mvwprintw( main_window, 6, tab2, "the wipe, the customer details and the" );
mvwprintw( main_window, 7, tab2, "current date and time in order to " );
mvwprintw( main_window, 8, tab2, "confirm that the information is " );
mvwprintw( main_window, 9, tab2, "correct on the pdf report prior to " );
mvwprintw( main_window, 10, tab2, "drive selection and starting the erase" );
mvwprintw( main_window, 4, tab2, "A preview prior to the drive selection " );
mvwprintw( main_window, 5, tab2, "of the organisation that is performing " );
mvwprintw( main_window, 6, tab2, "the wipe, the customer details and the " );
mvwprintw( main_window, 7, tab2, "current date and time in order to " );
mvwprintw( main_window, 8, tab2, "confirm that the information is " );
mvwprintw( main_window, 9, tab2, "correct on the PDF report prior to " );
mvwprintw( main_window, 10, tab2, "drive selection and starting the erase." );
break;
case 8:
mvwprintw( main_window, 2, tab2, "Set System Date & Time " );
mvwprintw( main_window, 2, tab2, "Set System Date & Time " );
mvwprintw( main_window, 4, tab2, "Useful when host is not connected to " );
mvwprintw( main_window, 5, tab2, "the internet and not running the 'ntp'" );
mvwprintw( main_window, 6, tab2, "(network time protocol). " );
mvwprintw( main_window, 4, tab2, "Useful when host is not connected to " );
mvwprintw( main_window, 5, tab2, "the internet and not running the 'NTP' " );
mvwprintw( main_window, 6, tab2, "(Network Time Protocol). " );
break;
} /* switch */

View File

@@ -25,8 +25,7 @@ MODIFIED:
*(r++) = b = ind(mm,y>>RANDSIZL) + x; \
}
void isaac(ctx)
randctx *ctx;
void isaac(randctx *ctx)
{
register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
mm=ctx->randmem;
@@ -64,9 +63,7 @@ randctx *ctx;
}
/* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
void randinit(ctx, flag)
randctx *ctx;
word flag;
void randinit(randctx *ctx, word flag)
{
word i;
ub4 a,b,c,d,e,f,g,h;

View File

@@ -32,10 +32,9 @@ typedef struct randctx randctx;
If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ-1] as the seed.
------------------------------------------------------------------------------
*/
void randinit(/*_ randctx *r, word flag _*/);
void isaac(/*_ randctx *r _*/);
void randinit(randctx *r, word flag);
void isaac(randctx *r);
/*
------------------------------------------------------------------------------

View File

@@ -507,6 +507,11 @@ void nwipe_log_OSinfo()
return;
}
/* Globally accessable dmidecode host identifiable data. */
char dmidecode_system_serial_number[DMIDECODE_RESULT_LENGTH];
char dmidecode_system_uuid[DMIDECODE_RESULT_LENGTH];
char dmidecode_baseboard_serial_number[DMIDECODE_RESULT_LENGTH];
int nwipe_log_sysinfo()
{
FILE* fp;
@@ -559,9 +564,16 @@ int nwipe_log_sysinfo()
char cmd[sizeof( dmidecode_keywords ) + sizeof( dmidecode_command2 )];
unsigned int keywords_idx;
unsigned int i;
keywords_idx = 0;
/* Initialise every character in the string with zero */
for( i = 0; i < DMIDECODE_RESULT_LENGTH; i++ )
{
dmidecode_system_serial_number[i] = 0;
}
p_dmidecode_command = 0;
if( system( "which dmidecode > /dev/null 2>&1" ) )
@@ -619,11 +631,35 @@ int nwipe_log_sysinfo()
else
{
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
/* if system-serial-number copy result to extern string */
if( keywords_idx == 5 )
{
strncpy( dmidecode_system_serial_number, path, DMIDECODE_RESULT_LENGTH );
dmidecode_system_serial_number[DMIDECODE_RESULT_LENGTH - 1] = 0;
}
if( keywords_idx == 6 )
{
strncpy( dmidecode_system_uuid, path, DMIDECODE_RESULT_LENGTH );
dmidecode_system_uuid[DMIDECODE_RESULT_LENGTH - 1] = 0;
}
}
}
else
{
nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0][0], path );
/* if system-serial-number copy result to extern string */
if( keywords_idx == 5 )
{
strncpy( dmidecode_system_serial_number, path, DMIDECODE_RESULT_LENGTH );
dmidecode_system_serial_number[DMIDECODE_RESULT_LENGTH - 1] = 0;
}
if( keywords_idx == 6 )
{
strncpy( dmidecode_system_uuid, path, DMIDECODE_RESULT_LENGTH );
dmidecode_system_uuid[DMIDECODE_RESULT_LENGTH - 1] = 0;
}
}
}
/* close */

View File

@@ -29,6 +29,8 @@
#define OS_info_Line_offset 31 /* OS_info line offset in log */
#define OS_info_Line_Length 48 /* OS_info line length */
#define DMIDECODE_RESULT_LENGTH 64
typedef enum nwipe_log_t_ {
NWIPE_LOG_NONE = 0,
NWIPE_LOG_DEBUG, // Output only when --verbose option used on cmd line.

View File

@@ -47,6 +47,52 @@
#include "options.h"
#include "pass.h"
#include "logging.h"
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h> /* SYS_getrandom */
#if defined( __linux__ )
/* On glibc/musl with <sys/random.h> available, it's fine (optional). */
/* #include <sys/random.h> */
#endif
/**
* @brief Fill a buffer with cryptographically secure random bytes using getrandom(2).
*
* This wrapper blocks until the kernel CRNG is initialized, then loops until
* @p len bytes are written (handling short reads and EINTR/EAGAIN).
*
* @param[out] buf Destination buffer.
* @param[in] len Number of bytes to generate.
* @return On success, returns (ssize_t)len.
* On error, returns -errno and leaves errno set.
*/
static ssize_t nwipe_read_entropy( void* buf, size_t len )
{
unsigned char* p = (unsigned char*) buf;
size_t n = len;
while( n > 0 )
{
/* Prefer the raw syscall to avoid libc version pitfalls. */
ssize_t r = syscall( SYS_getrandom, p, n, 0 /* blocking */ );
if( r < 0 )
{
if( errno == EINTR || errno == EAGAIN )
{
continue; /* retry */
}
return -errno;
}
if( r == 0 )
{
/* Extremely unlikely: treat as transient and retry. */
continue;
}
p += r;
n -= (size_t) r;
}
return (ssize_t) len;
}
/*
* Comment Legend
@@ -69,6 +115,7 @@ const char* nwipe_verify_zero_label = "Verify Zeros (0x00)";
const char* nwipe_verify_one_label = "Verify Ones (0xFF)";
const char* nwipe_is5enh_label = "HMG IS5 Enhanced";
const char* nwipe_bruce7_label = "Bruce Schneier 7-Pass";
const char* nwipe_bmb_label = "BMB21-2019";
const char* nwipe_unknown_label = "Unknown Method (FIXME)";
@@ -123,6 +170,10 @@ const char* nwipe_method_label( void* method )
{
return nwipe_bruce7_label;
}
if( method == &nwipe_bmb )
{
return nwipe_bmb_label;
}
/* else */
return nwipe_unknown_label;
@@ -287,7 +338,7 @@ void* nwipe_dod522022m( void* ptr )
{ 0, NULL } };
/* Load the array with random characters. */
r = read( c->entropy_fd, &dod, sizeof( dod ) );
r = nwipe_read_entropy( &dod, sizeof( dod ) );
/* NOTE: Only the random data in dod[0], dod[3], and dod[4] is actually used. */
@@ -358,7 +409,7 @@ void* nwipe_dodshort( void* ptr )
{ 0, NULL } };
/* Load the array with random characters. */
r = read( c->entropy_fd, &dod, sizeof( dod ) );
r = nwipe_read_entropy( &dod, sizeof( dod ) );
/* NOTE: Only the random data in dod[0] is actually used. */
@@ -458,7 +509,7 @@ void* nwipe_gutmann( void* ptr )
u16 s[27];
/* Load the array with random characters. */
ssize_t r = read( c->entropy_fd, &s, sizeof( s ) );
ssize_t r = nwipe_read_entropy( &s, sizeof( s ) );
if( r != sizeof( s ) )
{
r = errno;
@@ -616,7 +667,7 @@ void* nwipe_ops2( void* ptr )
}
/* Load the array of random characters. */
r = read( c->entropy_fd, s, u );
r = nwipe_read_entropy( s, u );
if( r != u )
{
@@ -799,6 +850,42 @@ void* nwipe_bruce7( void* ptr )
return NULL;
}
void* nwipe_bmb( void* ptr )
{
/**
* BMB Secure Wipe Method:
* Pass 1: 0xFF
* Pass 2: 0x00
* Pass 3-5: 3× Random
* Pass 6: 0xFF
*/
nwipe_context_t* c = (nwipe_context_t*) ptr;
time( &c->start_time );
c->wipe_status = 1;
char onefill[1] = { '\xFF' };
char zerofill[1] = { '\x00' };
nwipe_pattern_t patterns[] = {
{ 1, &onefill[0] }, // 0xFF
{ 1, &zerofill[0] }, // 0x00
{ -1, "" }, // RANDOM
{ -1, "" }, // RANDOM
{ -1, "" }, // RANDOM
{ 1, &onefill[0] }, // 0xFF
{ 0, NULL } // 0X00
};
c->result = nwipe_runmethod( c, patterns );
c->wipe_status = 0;
time( &c->end_time );
return NULL;
}
int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
{
/**
@@ -960,13 +1047,13 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
c->pass_type = NWIPE_PASS_WRITE;
/* Seed the PRNG. */
r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length );
r = nwipe_read_entropy( c->prng_seed.s, c->prng_seed.length );
/* Check the result. */
if( r < 0 )
{
c->pass_type = NWIPE_PASS_NONE;
nwipe_perror( errno, __FUNCTION__, "read" );
nwipe_perror( errno, __FUNCTION__, "getrandom" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." );
return -1;
}
@@ -1063,12 +1150,12 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns )
c->pass_type = NWIPE_PASS_FINAL_OPS2;
/* Seed the PRNG. */
r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length );
r = nwipe_read_entropy( c->prng_seed.s, c->prng_seed.length );
/* Check the result. */
if( r < 0 )
{
nwipe_perror( errno, __FUNCTION__, "read" );
nwipe_perror( errno, __FUNCTION__, "getrandom" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." );
return -1;
}

View File

@@ -55,6 +55,7 @@ void* nwipe_one( void* ptr );
void* nwipe_verify_zero( void* ptr );
void* nwipe_verify_one( void* ptr );
void* nwipe_bruce7( void* ptr );
void* nwipe_bmb( void* ptr );
void calculate_round_size( nwipe_context_t* );

View File

@@ -32,6 +32,14 @@
#include "context.h"
#include "logging.h"
#include "miscellaneous.h"
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h> // for isspace()
#include <stddef.h> // for NULL
/* Convert string to upper case
*/
@@ -739,3 +747,150 @@ void fix_endian_model_names( char* model )
free( tmp_string );
free( model_lower_case );
}
/*
* get_device_uuid - Find the UUID corresponding to a given block device
* @device_path: e.g., "/dev/sda1"
* @uuid_buf: pointer to a 40-byte buffer where the UUID string will be stored
*
* Returns 0 on success, -1 on failure.
*/
int get_device_uuid( const char* device_path, char* uuid_buf )
{
const char* uuid_dir = "/dev/disk/by-uuid";
struct dirent* entry;
DIR* dir;
char link_path[PATH_MAX];
char resolved_path[PATH_MAX];
ssize_t len;
if( !device_path || !uuid_buf )
{
errno = EINVAL;
return -1;
}
dir = opendir( uuid_dir );
if( !dir )
{
perror( "opendir" );
return -1;
}
while( ( entry = readdir( dir ) ) != NULL )
{
// Skip "." and ".."
if( strcmp( entry->d_name, "." ) == 0 || strcmp( entry->d_name, ".." ) == 0 )
continue;
snprintf( link_path, sizeof( link_path ), "%s/%s", uuid_dir, entry->d_name );
// readlink() doesn't null-terminate, so we must handle that
len = readlink( link_path, resolved_path, sizeof( resolved_path ) - 1 );
if( len == -1 )
continue; // skip unreadable links
resolved_path[len] = '\0';
// Construct full path (readlink gives a relative path, usually "../../sda1")
char full_path[PATH_MAX + strlen( uuid_dir ) + 1];
if( resolved_path[0] != '/' )
{
// Resolve relative symlink path
snprintf( full_path, sizeof( full_path ), "%s/%s", uuid_dir, resolved_path );
if( realpath( full_path, full_path ) == NULL )
{
closedir( dir );
return -1;
}
}
else
{
strncpy( full_path, resolved_path, sizeof( full_path ) );
full_path[sizeof( full_path ) - 1] = '\0';
}
// Compare with the given device path
if( strcmp( full_path, device_path ) == 0 )
{
strncpy( uuid_buf, entry->d_name, 40 );
uuid_buf[39] = '\0';
closedir( dir );
return 0;
}
}
closedir( dir );
errno = ENOENT;
return -1; // not found
}
/**
* find_base_device - searches /sys/block for a device that matches
* the prefix of the provided name.
*
* @devname: the input device name (e.g. "sda1", "sdb2")
* @result: buffer to store the matched base device name
* @size: size of the result buffer
*
* Returns: 0 on success (match found), -1 on failure (no match or error)
*/
int find_base_device( const char* devname, char* result, size_t size )
{
if( !devname || !result || size == 0 )
{
fprintf( stderr, "Invalid argument(s)\n" );
return -1;
}
DIR* dir = opendir( "/sys/block" );
if( !dir )
{
perror( "opendir" );
return -1;
}
struct dirent* entry;
int found = -1;
while( ( entry = readdir( dir ) ) != NULL )
{
// Skip "." and ".."
if( entry->d_name[0] == '.' )
continue;
// Check if the given devname starts with the block device name
size_t len = strlen( entry->d_name );
if( strncmp( devname, entry->d_name, len ) == 0 )
{
// Match found
strncpy( result, entry->d_name, size - 1 );
result[size - 1] = '\0';
found = 0;
break;
}
}
closedir( dir );
return found;
}
/**
* skip_whitespace - Returns a pointer to the first non-whitespace character
* in a given string.
*
* @str: input string
*
* Returns: pointer to the first non-whitespace character,
* or NULL if str is NULL or the string contains only whitespace.
*/
const char* skip_whitespace( const char* str )
{
if( !str )
return NULL;
while( *str && isspace( (unsigned char) *str ) )
str++;
return *str ? str : NULL;
}

View File

@@ -129,4 +129,36 @@ int write_system_datetime( char*, char*, char*, char*, char*, char* );
*/
void fix_endian_model_names( char* model );
/**
* Obtains the UUID of the drive partition
*
* @param constchar* device path, example /dev/sda1
* @param char* pointer to UUID string UUID_SIZE long
* @return 0 = success, -1 = failure.
*/
int get_device_uuid( const char*, char* );
/**
* find_base_device - searches /sys/block for a device that matches
* the prefix of the provided name.
*
* @devname: the input device name (e.g. "sda1", "sdb2")
* @result: buffer to store the matched base device name
* @size: size of the result buffer
*
* Returns: 0 on success (match found), -1 on failure (no match or error)
*/
int find_base_device( const char*, char*, size_t );
/**
* skip_whitespace - Returns a pointer to the first non-whitespace character
* in a given string.
*
* @str: input string
*
* Returns: pointer to the first non-whitespace character,
* or NULL if str is NULL or the string contains only whitespace.
*/
const char* skip_whitespace( const char* );
#endif /* HPA_DCO_H_ */

View File

@@ -97,9 +97,6 @@ int main( int argc, char** argv )
char module_shortform[50];
char final_cmd_modprobe[sizeof( modprobe_command ) + sizeof( module_shortform )];
/* The entropy source file handle. */
int nwipe_entropy;
/* The generic index variables. */
int i;
int j;
@@ -256,21 +253,6 @@ int main( int argc, char** argv )
exit( 1 );
}
/* Open the entropy source. */
nwipe_entropy = open( NWIPE_KNOB_ENTROPY, O_RDONLY );
/* Check the result. */
if( nwipe_entropy < 0 )
{
nwipe_perror( errno, __FUNCTION__, "open" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to open entropy source %s.", NWIPE_KNOB_ENTROPY );
cleanup();
free( c2 );
return errno;
}
nwipe_log( NWIPE_LOG_NOTICE, "Opened entropy source '%s'.", NWIPE_KNOB_ENTROPY );
/* Block relevant signals in main thread. Any other threads that are */
/* created after this will also block those signals. */
sigset_t sigset;
@@ -359,9 +341,6 @@ int main( int argc, char** argv )
for( i = 0; i < nwipe_enumerated; i++ )
{
/* Set the entropy source. */
c1[i]->entropy_fd = nwipe_entropy;
if( nwipe_options.autonuke )
{
/* When the autonuke option is set, select all disks. */

View File

@@ -161,6 +161,9 @@ int nwipe_options_parse( int argc, char** argv )
/* Verify that wipe patterns are being written to the device. */
{ "verify", required_argument, 0, 0 },
/* Enables a field on the PDF that holds a tag that identifies the host computer */
{ "pdftag", no_argument, 0, 0 },
/* Display program version. */
{ "verbose", no_argument, 0, 'v' },
@@ -204,11 +207,12 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.sync = DEFAULT_SYNC_RATE;
nwipe_options.verbose = 0;
nwipe_options.verify = NWIPE_VERIFY_LAST;
nwipe_options.PDFtag = 0;
memset( nwipe_options.logfile, '\0', sizeof( nwipe_options.logfile ) );
memset( nwipe_options.PDFreportpath, '\0', sizeof( nwipe_options.PDFreportpath ) );
strncpy( nwipe_options.PDFreportpath, ".", 2 );
/* Read PDF settings from nwipe.conf if available */
/* Read PDF Enable/Disable settings from nwipe.conf if available */
if( ( ret = nwipe_conf_read_setting( "PDF_Certificate.PDF_Enable", &read_value ) ) )
{
/* error occurred */
@@ -242,6 +246,40 @@ int nwipe_options_parse( int argc, char** argv )
}
}
/* Read PDF tag Enable/Disable settings from nwipe.conf if available */
if( ( ret = nwipe_conf_read_setting( "PDF_Certificate.PDF_tag", &read_value ) ) )
{
/* error occurred */
nwipe_log( NWIPE_LOG_ERROR,
"nwipe_conf_read_setting():Error reading PDF_Certificate.PDF_tag from nwipe.conf, ret code %i",
ret );
/* Use default values */
nwipe_options.PDFtag = 1;
}
else
{
if( !strcmp( read_value, "ENABLED" ) )
{
nwipe_options.PDFtag = 1;
}
else
{
if( !strcmp( read_value, "DISABLED" ) )
{
nwipe_options.PDFtag = 0;
}
else
{
// error occurred
nwipe_log(
NWIPE_LOG_ERROR,
"PDF_Certificate.PDF_tag in nwipe.conf returned a value that was neither ENABLED or DISABLED" );
nwipe_options.PDFtag = 0; // Default to Enabled
}
}
}
/* PDF Preview enable/disable */
if( ( ret = nwipe_conf_read_setting( "PDF_Certificate.PDF_Preview", &read_value ) ) )
{
@@ -383,6 +421,12 @@ int nwipe_options_parse( int argc, char** argv )
exit( EINVAL );
}
if( strcmp( nwipe_options_long[i].name, "pdftag" ) == 0 )
{
nwipe_options.PDFtag = 1;
break;
}
/* getopt_long should raise on invalid option, so we should never get here. */
exit( EINVAL );
@@ -453,6 +497,11 @@ int nwipe_options_parse( int argc, char** argv )
nwipe_options.method = &nwipe_bruce7;
break;
}
if( strcmp( optarg, "bmb" ) == 0 )
{
nwipe_options.method = &nwipe_bmb;
break;
}
/* Else we do not know this wipe method. */
fprintf( stderr, "Error: Unknown wipe method '%s'.\n", optarg );
@@ -615,6 +664,13 @@ int nwipe_options_parse( int argc, char** argv )
} /* command line options */
/* Disable blanking for ops2 and verify methods */
if( nwipe_options.method == &nwipe_ops2 || nwipe_options.method == &nwipe_verify_zero
|| nwipe_options.method == &nwipe_verify_one )
{
nwipe_options.noblank = 1;
}
/* Return the number of options that were processed. */
return optind;
}
@@ -680,11 +736,11 @@ void nwipe_options_log( void )
}
else if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator (EXPERIMENTAL!)" );
nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator" );
}
else if( nwipe_options.prng == &nwipe_xoroshiro256_prng )
{
nwipe_log( NWIPE_LOG_NOTICE, " prng = XORoshiro-256 (EXPERIMENTAL!)" );
nwipe_log( NWIPE_LOG_NOTICE, " prng = XORoshiro-256" );
}
else if( nwipe_options.prng == &nwipe_aes_ctr_prng )
{
@@ -775,33 +831,38 @@ void display_help()
puts( " one - Overwrite with ones (0xFF)" );
puts( " verify_zero - Verifies disk is zero filled" );
puts( " verify_one - Verifies disk is 0xFF filled" );
puts( " is5enh - HMG IS5 enhanced\n" );
puts( " bruce7 - Schneier Bruce 7-pass mixed pattern\n" );
puts( " is5enh - HMG IS5 enhanced\n" );
puts( " bruce7 - Schneier Bruce 7-pass mixed pattern\n" );
puts( " bmb - BMB21-2019 mixed pattern\n" );
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 "
puts( " -p, --prng=METHOD PRNG option "
"(mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng|xoroshiro256_prng|aes_ctr_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" );
puts( " -r, --rounds=NUM Number of times to wipe the device using the selected" );
puts( " method (default: 1)\n" );
puts( " --noblank Do NOT blank disk after wipe" );
puts( " (default is to complete a final blank pass)\n" );
puts( " --nowait Do NOT wait for a key before exiting" );
puts( " (default is to wait)\n" );
puts( " --nosignals Do NOT allow signals to interrupt a wipe" );
puts( " (default is to allow)\n" );
puts( " --nogui Do NOT show the GUI interface. Automatically invokes" );
puts( " the nowait option. Must be used with the --autonuke" );
puts( " option. Send SIGUSR1 to log current stats\n" );
puts( " --nousb Do NOT show or wipe any USB devices whether in GUI" );
puts( " mode, --nogui or --autonuke modes.\n" );
puts( " -e, --exclude=DEVICES Up to ten comma separated devices to be excluded" );
puts( " --exclude=/dev/sdc" );
puts( " --exclude=/dev/sdc,/dev/sdd" );
puts( " --exclude=/dev/sdc,/dev/sdd,/dev/mapper/cryptswap1\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" );
puts( " -r, --rounds=NUM Number of times to wipe the device using the selected" );
puts( " method. (default: 1)\n" );
puts( " --noblank Do NOT blank disk after wipe." );
puts( " (default is to complete a final blank pass)\n" );
puts( " --nowait Do NOT wait for a key before exiting." );
puts( " (default is to wait)\n" );
puts( " --nosignals Do NOT allow signals to interrupt a wipe." );
puts( " (default is to allow)\n" );
puts( " --nogui Do NOT show the GUI interface. Automatically invokes" );
puts( " the nowait option. Must be used with the --autonuke" );
puts( " option. Send SIGUSR1 to log current stats.\n" );
puts( " --nousb Do NOT show or wipe any USB devices whether in GUI" );
puts( " mode, --nogui or --autonuke modes.\n" );
puts( " --pdftag Enables a field on the PDF that holds a tag that\n" );
puts( " identifies the host computer\n" );
puts( " -e, --exclude=DEVICES Up to ten comma separated devices to be excluded." );
puts( " --exclude=/dev/sdc" );
puts( " --exclude=/dev/sdc,/dev/sdd" );
puts( " --exclude=/dev/sdc,/dev/sdd,/dev/mapper/cryptswap1\n" );
puts( " --exclude=/dev/disk/by-id/ata-XXXXXXXX" );
puts( " --exclude=/dev/disk/by-path/pci-0000:00:17.0-ata-1\n" );
puts( "" );
exit( EXIT_SUCCESS );
}

View File

@@ -24,7 +24,6 @@
#define OPTIONS_H_
/* Program knobs. */
#define NWIPE_KNOB_ENTROPY "/dev/urandom"
#define NWIPE_KNOB_IDENTITY_SIZE 512
#define NWIPE_KNOB_LABEL_SIZE 128
#define NWIPE_KNOB_LOADAVG "/proc/loadavg"
@@ -68,6 +67,7 @@ typedef struct
int verbose; // Make log more verbose
int PDF_enable; // 0=PDF creation disabled, 1=PDF creation enabled
int PDF_preview_details; // 0=Disable preview Org/Cust/date/time before drive selection, 1=Enable Preview
int PDFtag; // Enable display of hostID, such as UUID or serial no. on PDF report.
nwipe_verify_t verify; // A flag to indicate whether writes should be verified.
} nwipe_options_t;

View File

@@ -264,7 +264,7 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE )
return 0;
}
/* EXPERIMENTAL implementation of Lagged Fibonacci generator a lot of random numbers */
/* Implementation of Lagged Fibonacci generator a lot of random numbers */
int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
if( *state == NULL )
@@ -278,7 +278,7 @@ int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
return 0;
}
/* EXPERIMENTAL implementation of XORoroshiro256 algorithm to provide high-quality, but a lot of random numbers */
/* Implementation of XORoroshiro256 algorithm to provide high-quality, but a lot of random numbers */
int nwipe_xoroshiro256_prng_init( NWIPE_PRNG_INIT_SIGNATURE )
{
nwipe_log( NWIPE_LOG_NOTICE, "Initialising XORoroshiro-256 PRNG" );
@@ -324,7 +324,7 @@ int nwipe_xoroshiro256_prng_read( NWIPE_PRNG_READ_SIGNATURE )
u8* restrict bufpos = buffer;
size_t words = count / SIZE_OF_XOROSHIRO256_PRNG;
/* Loop to fill the buffer with blocks directly from the XORoroshiro256 algorithm */
/* Loop to fill the buffer with blocks directly from the XORoshiro256 algorithm */
for( size_t ii = 0; ii < words; ++ii )
{
xoroshiro256_genrand_uint256_to_buf( (xoroshiro256_state_t*) *state, bufpos );

View File

@@ -4,15 +4,15 @@
* used by configure to dynamically assign those values
* to documentation files.
*/
const char* version_string = "0.38.1";
const char* version_string = "0.39.1";
const char* program_name = "nwipe";
const char* author_name = "Martijn van Brummelen";
const char* email_address = "git@brumit.nl";
const char* years = "2024";
const char* years = "2025";
const char* copyright = "Copyright Darik Horn <dajhorn-dban@vanadac.com>\n\
Andy Beverley <andy@andybev.com> Martijn van Brummelen <martijn@brumit.nl>\n\
Nick Law <shredos.eraser@gmail.com> (@PartialVolume) and others\n\
This is free software; see the source for copying conditions.\n\
There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\
FOR A PARTICULAR PURPOSE.\n";
const char* banner = "nwipe 0.38.1";
const char* banner = "nwipe 0.39.1";