pax_global_header00006660000000000000000000000064132120442140014503gustar00rootroot0000000000000052 comment=533fa56de870c2b703ea903efae61162d4012406 nwipe-0.24/000077500000000000000000000000001321204421400125525ustar00rootroot00000000000000nwipe-0.24/.gitignore000066400000000000000000000006721321204421400145470ustar00rootroot00000000000000Makefile Makefile.in aclocal.m4 autom4te.cache/ compile config.h config.h.in config.log config.status configure depcomp install-sh man/Makefile man/Makefile.in missing src/.deps/ src/Makefile src/Makefile.in src/nwipe src/nwipe-device.o src/nwipe-gui.o src/nwipe-isaac_rand.o src/nwipe-logging.o src/nwipe-method.o src/nwipe-mt19937ar-cok.o src/nwipe-nwipe.o src/nwipe-options.o src/nwipe-pass.o src/nwipe-prng.o src/nwipe-version.o stamp-h1 nwipe-0.24/COPYING000066400000000000000000000432541321204421400136150ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. nwipe-0.24/Makefile.am000066400000000000000000000000551321204421400146060ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign SUBDIRS = src man nwipe-0.24/README000066400000000000000000000074371321204421400134450ustar00rootroot00000000000000Installation ============ First bootstrap the source tree: ./init.sh The install using the standard: ./configure make make install The ncurses, pthreads and parted libraries are required for compiling. For any problems, please use the Github page: https://github.com/martijnvanbrummelen/nwipe Martijn van Brummelen RELEASE NOTES ============= v0.24 - use include values for version 0.17 - display throughput value more friendly(Thanks Kelderek) v0.23 - make serial visible again on 32Bit machines v0.22 - Update manpage - use long long for device size - Use ped_unit_format_byte function to display(friendly) size of device v0.21 - Fix ETA not updating properly and bad total throughput display. Thanks (Niels Bassler). v0.20 - Fix build when panel header is not in /usr/include (Thanks Vincent Untz). v0.19 - Fix building on Fedora(Unknown off64_t) bug #19. - Use PRNG instead of zero's bug #7. Thanks xambroz. v0.18 ===== - Fixed grammar. - Move from loff_t to off64_t for musl libc support. - Add "--nosignals" option. - Automake needs the dist_ prefix to include man pages in 'make dist'. - Remove more compiler warnings. - Add libintl, libuuid dependencies to allow parted static link v0.17 ===== - Remove control reaches end of non-void function" warnings(Thanks Vincent Untz). - Remove unused variables (thanks Vincent Untz). - Change start key to 'S' instead of F10 (closes debian bug #755474). - Fix problem with unusable device (Closes debian bug #755473). v0.16 ===== - Fix problems building with clang compiler (thanks Martijn van Brummelen) v0.15 ===== - Add more detailed information to status page when wiping - Add ability to send SIGUSR1 to print wiping current status to log - Fixed problem with status bar disappearing on narrow windows (Github issue #1) v0.14 ===== - Added explicit check for ncurses (required for Fedora). See bug 3604008. v0.13 ===== - Added nowait option (patch 3601259 - thanks David Shaw). - Added nogui option. - Updated man page and help command for above options and autonuke. - Added pkg-config check for ncurses (patch 3603140 - thanks Alon Bar-Lev). v0.12 ===== - Added ability to specify device on command line (patch 3587144). - Fixed segfault for -p option (patch 3587132). v0.11 ===== - Fixed bug 3568750. Not closing devices after initial scan. v0.10 ===== - Fixed bug 3553851. Not exiting on terminal kill. Fixed for all areas of program including wiping. v0.09 ===== - Added feature #3545971. Display device name. - Added feature #3496858. Option to not perform a final blanking pass. v0.08 ===== - Fixed bug #3501746 whereby "wipe finished" was displayed too early v0.07 ===== - Added threading synchronisation for logging - Fixed bug #3486927 (incorrect Sourceforge URL) v0.06 ===== - Added man page (thanks Michal Ambroz ) - Updated GPL licence and FSF address (thanks Michal Ambroz ) v0.05 ===== - Added sequence number to disk selection - Added check for ncurses header files in subdir - Fixed screen corruption bug introduced in 0.04 - Fixed occasional seg fault on start - Introduced dynamic array allocation for devices, with no hard limit - Minor updates to configure.ac v0.04 ===== - Removed references to DBAN in options.c - Added log file name option (-l|--logfile) - If no log file specified all messages go to STDOUT - Incorrect success message after an interruption fixed - Improved labelling of disks with no partition table - Added help command - Added version command - Added command 'b' to blank screen during wipe - Compilation needs to include panel library KNOWN BUG - display sometimes becomes corrupted after starting wipe v0.03 ===== - Added quit option label (ctrl-c) - Removed further references to DWIPE - Added GPL V2 licence file (COPYING) v0.02 ===== - Fixed segfault that happened during multiple disk wipes nwipe-0.24/README.md000066400000000000000000000011701321204421400140300ustar00rootroot00000000000000nwipe 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 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. To use from the git repository, first create all the autoconf files with ./init.sh Then do the standard ./configure --prefix=/usr && make && make install For release notes please see the [README file](README) nwipe-0.24/configure.ac000066400000000000000000000040441321204421400150420ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.64]) AC_INIT(nwipe, 0.24, git@brumit.nl) AM_INIT_AUTOMAKE(nwipe, 0.24) AC_OUTPUT(Makefile src/Makefile man/Makefile) AC_CONFIG_SRCDIR([src/nwipe.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC PKG_PROG_PKG_CONFIG # Checks for libraries. PKG_CHECK_MODULES( [PANEL], [panel], [ CFLAGS="${CFLAGS} ${PANEL_CFLAGS}" LIBS="${LIBS} ${PANEL_LIBS}" ], [AC_CHECK_LIB([panel], [main], [ LIBS="-lpanel $LIBS" AC_CHECK_HEADERS(panel.h,, [ AC_CHECK_HEADERS(ncurses/panel.h, [ AC_DEFINE([PANEL_IN_SUBDIR], [ncurses/], [Look for ncurses headers in subdir]) ], [AC_MSG_ERROR([ncurses panel headers not found])]) ]) ], [AC_MSG_ERROR([ncurses panel library not found])])] ) PKG_CHECK_MODULES( [NCURSES], [ncurses], [ CFLAGS="${CFLAGS} ${NCURSES_CFLAGS}" LIBS="${LIBS} ${NCURSES_LIBS}" ], [AC_CHECK_LIB([ncurses], [delscreen], [ LIBS="-lncurses $LIBS" AC_CHECK_HEADERS(ncurses.h,, [ AC_CHECK_HEADERS(ncurses/ncurses.h, [ AC_DEFINE([NCURSES_IN_SUBDIR], [ncurses/], [Look for ncurses headers in subdir]) ], [AC_MSG_ERROR([ncurses headers not found])]) ]) ], [AC_MSG_ERROR([ncurses development library not found])] )] ) AC_CHECK_LIB([intl], [libintl_dgettext]) # needed to statically link libparted, but not given in its pkgconfig file AC_CHECK_LIB([uuid], [uuid_generate]) # needed to statically link libparted, but not given in its pkgconfig file PKG_CHECK_MODULES([PARTED], [libparted]) AC_CHECK_LIB([pthread], [main], ,[AC_MSG_ERROR([pthread development library not found])]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h inttypes.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/file.h sys/ioctl.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T AC_CHECK_MEMBERS([struct stat.st_blksize]) # Checks for library functions. AC_FUNC_MALLOC AC_CHECK_FUNCS([fdatasync memset regcomp strdup strerror]) AC_OUTPUT nwipe-0.24/init.sh000077500000000000000000000001641321204421400140550ustar00rootroot00000000000000#!/bin/bash # Script to create all the required autoconf files aclocal autoheader automake --add-missing autoconf nwipe-0.24/man/000077500000000000000000000000001321204421400133255ustar00rootroot00000000000000nwipe-0.24/man/Makefile.am000066400000000000000000000000301321204421400153520ustar00rootroot00000000000000dist_man_MANS = nwipe.1 nwipe-0.24/man/nwipe.1000066400000000000000000000052751321204421400145420ustar00rootroot00000000000000.TH NWIPE "1" "December 2017" "nwipe version 0.24" "User Commands" .SH NAME nwipe \- securely erase disks .SH SYNOPSIS .B nwipe [\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 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 .TP - The parted library is used to detect drives .TP - The code is designed to be compiled with gcc .TP - SIGUSR1 can be used to log the stats of the current wipe .SH OPTIONS .TP \fB\-V\fR, \fB\-\-version\fR Prints the version number .TP \fB\-h\fR, \fB\-\-help\fR Prints a help summary .TP \fB\-\-autonuke\fR If no devices have been specified on the command line, starts wiping all devices immediately. If devices have been specified, starts wiping only those specified devices immediately. .TP \fB\-\-sync\fR Open devices in sync mode .TP \fB\-\-nowait\fR Do not wait for a key before exiting (default is to wait). .TP \fB\-\-nosignals\fR Do not allow signals to interrupt a wipe (default is to allow). .TP \fB\-\-nogui\fR 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\-\-verify\fR=\fITYPE\fR Whether to perform verification of erasure (default: last) off \- Do not verify last \- Verify after the last pass all \- Verify every pass .TP \fB\-m\fR, \fB\-\-method\fR=\fIMETHOD\fR The wiping method (default: dodshort). .IP dod522022m / dod \- 7 pass DOD 5220.22\-M method .IP dodshort / dod3pass \- 3 pass DOD method .IP gutmann \- Peter Gutmann's Algorithm .IP ops2 \- RCMP TSSIT OPS\-II .IP random / prng / stream \- PRNG Stream .IP zero / quick \- Overwrite with zeros .TP \fB\-l\fR, \fB\-\-logfile\fR=\fIFILE\fR Filename to log to. Default is STDOUT .TP \fB\-p\fR, \fB\-\-prng\fR=\fIMETHOD\fR PRNG option (mersenne|twister|isaac) .TP \fB\-r\fR, \fB\-\-rounds\fR=\fINUM\fR Number of times to wipe the device using the selected method (default: 1) .SH BUGS Please see the github site for the latest list (https://github.com/martijnvanbrummelen/nwipe/issues) .SH AUTHOR Nwipe is developed by Martijn van Brummelen .SH "SEE ALSO" .BR shred (1), .BR dwipe (1), .BR dd (1), .BR dcfldd (1), .BR dc3dd (1) nwipe-0.24/src/000077500000000000000000000000001321204421400133415ustar00rootroot00000000000000nwipe-0.24/src/Makefile.am000066400000000000000000000010471321204421400153770ustar00rootroot00000000000000# what flags you want to pass to the C compiler & linker #CFLAGS = -lncurses -lparted AM_CFLAGS = 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 isaac_rand.c logging.h options.h prng.h nwipe.c gui.c isaac_rand.h method.h pass.c device.c gui.h isaac_standard.h mt19937ar-cok.c nwipe.h mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c version.h nwipe_CFLAGS = $(PARTED_CFLAGS) nwipe_LDADD = $(PARTED_LIBS) nwipe-0.24/src/context.h000066400000000000000000000204131321204421400151760ustar00rootroot00000000000000/* * context.h: The internal state representation of nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef CONTEXT_H_ #define CONTEXT_H_ #include "prng.h" typedef enum nwipe_device_t_ { NWIPE_DEVICE_UNKNOWN = 0, /* Unknown device. */ NWIPE_DEVICE_IDE, NWIPE_DEVICE_SCSI, NWIPE_DEVICE_COMPAQ, /* Unimplemented. */ NWIPE_DEVICE_USB, /* Unimplemented. */ NWIPE_DEVICE_IEEE1394 /* Unimplemented. */ } nwipe_device_t; typedef enum nwipe_pass_t_ { NWIPE_PASS_NONE = 0, /* Not running. */ NWIPE_PASS_WRITE, /* Writing patterns to the device. */ NWIPE_PASS_VERIFY, /* Verifying a pass. */ NWIPE_PASS_FINAL_BLANK, /* Filling the device with zeros. */ NWIPE_PASS_FINAL_OPS2 /* Special case for nwipe_ops2. */ } nwipe_pass_t; typedef enum nwipe_select_t_ { NWIPE_SELECT_NONE = 0, /* Unused. */ NWIPE_SELECT_TRUE, /* Wipe this device. */ NWIPE_SELECT_TRUE_PARENT, /* A parent of this device has been selected, so the wipe is implied. */ NWIPE_SELECT_FALSE, /* Do not wipe this device. */ NWIPE_SELECT_FALSE_CHILD, /* A child of this device has been selected, so we can't wipe this device. */ NWIPE_SELECT_DISABLED /* Do not wipe this device and do not allow it to be selected. */ } nwipe_select_t; #define NWIPE_KNOB_SPEEDRING_SIZE 30 #define NWIPE_KNOB_SPEEDRING_GRANULARITY 10 typedef struct nwipe_speedring_t_ { u64 bytes[NWIPE_KNOB_SPEEDRING_SIZE]; u64 bytestotal; u64 byteslast; time_t times[NWIPE_KNOB_SPEEDRING_SIZE]; time_t timestotal; time_t timeslast; u32 position; } nwipe_speedring_t; typedef struct nwipe_context_t_ { int block_size; /* The soft block size reported the device. */ int device_bus; /* The device bus number. */ int device_fd; /* The file descriptor of the device file being wiped. */ int device_host; /* The host number. */ struct hd_driveid device_id; /* The WIN_IDENTIFY data for IDE drives. */ int device_lun; /* The device logical unit number. */ int device_major; /* The major device number. */ int device_minor; /* The minor device number. */ int device_part; /* The device partition or slice number. */ char* device_name; /* The device file name. */ long long device_size; /* The device size in bytes. */ char* device_size_text; /* The device size in a more (human)readable format. */ struct stat device_stat; /* The device file state from fstat(). */ nwipe_device_t device_type; /* Indicates an IDE, SCSI, or Compaq SMART device. */ 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. */ char* label; /* The string that we will show the user. */ 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. */ u64 pass_size; /* The total number of i/o bytes across all passes. */ nwipe_pass_t pass_type; /* The type of the current working pass. */ int pass_working; /* The current working pass. */ nwipe_prng_t* prng; /* The PRNG implementation. */ nwipe_entropy_t prng_seed; /* The random data that is used to seed the PRNG. */ void* prng_state; /* The private internal state of the PRNG. */ int result; /* The process return value. */ int round_count; /* The number of rounds performed by the working wipe method. */ u64 round_done; /* The number of bytes that have already been i/o'd. */ u64 round_errors; /* The number of errors across all rounds. */ u64 round_size; /* The total number of i/o bytes across all rounds. */ double round_percent; /* The percentage complete across all rounds. */ int round_working; /* The current working round. */ int sector_size; /* The hard sector size reported by the device. */ nwipe_select_t select; /* Indicates whether this device should be wiped. */ int signal; /* Set when the child is killed by a signal. */ nwipe_speedring_t speedring; /* Ring buffer for computing the rolling throughput average. */ short sync_status; /* A flag to indicate when the method is syncing. */ pthread_t thread; /* The ID of the thread. */ u64 throughput; /* Average throughput in bytes per second. */ u64 verify_errors; /* The number of verification errors across all passes. */ struct hd_driveid identity; /* The serial number of the drive (where applicable) */ } nwipe_context_t; /* We use 2 data structs to pass data between threads. */ /* The first contains any required values: */ /* Values cannot form part of the second array below, hence the need for this. */ typedef struct { int nwipe_enumerated; /* The number of devices available. */ int nwipe_selected; /* The number of devices being wiped. */ time_t maxeta; /* The estimated runtime of the slowest device. */ u64 throughput; /* Total throughput */ u64 errors; /* The combined number of errors of all processes. */ pthread_t *gui_thread; /* The ID of GUI thread. */ } nwipe_misc_thread_data_t; /* The second points to the first structure, as well as the structure of all the devices */ typedef struct { nwipe_context_t **c; /* Pointer to the nwipe context structure. */ nwipe_misc_thread_data_t *nwipe_misc_thread_data; /* Pointer to the misc structure above. */ } nwipe_thread_data_ptr_t; #endif /* CONTEXT_H_ */ /* eof */ nwipe-0.24/src/device.c000066400000000000000000000100221321204421400147370ustar00rootroot00000000000000/* * device.c: Device routines for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ /* Why is this needed? Segfaults without it */ #include #include "nwipe.h" #include "context.h" #include "method.h" #include "options.h" #include "logging.h" #include #include int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ); int nwipe_device_scan( nwipe_context_t*** c ) { /** * Scans the the filesystem for storage device names. * * @parameter device_names A reference to a null array pointer. * @modifies device_names Populates device_names with an array of nwipe_contect_t * @returns The number of strings in the device_names array. * */ PedDevice* dev = NULL; ped_device_probe_all(); int dcount = 0; while ((dev = ped_device_get_next (dev))) { if (check_device(c, dev, dcount)) dcount++; } /* Return the number of devices that were found. */ return dcount; } /* nwipe_device_scan */ int nwipe_device_get( nwipe_context_t*** c, char **devnamelist, int ndevnames ) { /** * Gets information about devices * * @parameter device_names A reference to a null array pointer. * @parameter devnamelist An array of string pointers to the device names * @parameter ndevnames Number of elements in devnamelist * @modifies device_names Populates device_names with an array of nwipe_contect_t * @returns The number of strings in the device_names array. * */ PedDevice* dev = NULL; int i; int dcount = 0; for(i = 0; i < ndevnames; i++) { dev = ped_device_get(devnamelist[i]); if (!dev) break; if (check_device(c, dev, dcount)) dcount++; } /* Return the number of devices that were found. */ return dcount; } /* nwipe_device_get */ int check_device( nwipe_context_t*** c, PedDevice* dev, int dcount ) { /* Populate this struct, then assign it to overall array of structs. */ nwipe_context_t* next_device; /* Try opening the device to see if it's valid. Close on completion. */ if (!ped_device_open(dev)) return 0; ped_device_close(dev); /* New device, reallocate memory for additional struct pointer */ *c = realloc (*c, (dcount+1) * sizeof(nwipe_context_t *)); next_device = malloc (sizeof(nwipe_context_t)); /* Check the allocation. */ if( ! next_device ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to create the array of enumeration contexts." ); return 0; } /* Zero the allocation. */ memset( next_device , 0, sizeof( nwipe_context_t ) ); /* Get device information */ next_device->label = dev->model; next_device->device_name = dev->path; next_device->device_size = dev->length * dev->sector_size; next_device->device_size_text = ped_unit_format_byte(dev, dev->length * dev->sector_size); /* Attempt to get serial number of device. */ ioctl(next_device->device_fd, HDIO_GET_IDENTITY, &next_device->identity); (*c)[dcount] = next_device; return 1; } /* eof */ nwipe-0.24/src/device.h000066400000000000000000000023451321204421400147550ustar00rootroot00000000000000/* * device.h: Device routines for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef DEVICE_H_ #define DEVICE_H_ void nwipe_device_identify( nwipe_context_t* c ); /* Get hardware information about the device. */ int nwipe_device_scan( nwipe_context_t*** c ); /* Find devices that we can wipe. */ int nwipe_device_get( nwipe_context_t*** c, char **devnamelist, int ndevnames ); /* Get info about devices to wipe */ #endif /* DEVICE_H_ */ /* eof */ nwipe-0.24/src/gui.c000066400000000000000000001574611321204421400143070ustar00rootroot00000000000000/* * gui.c: An ncurses GUI for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ /* RATIONALE: * * This entire GUI is a non-portable task-specific thunk. * * The alternatives are, however, no better. The CDK is large and clumsy, * and things like ncurses libmenu are not worth the storage overhead. * */ /* Why is this needed? Segfaults without it */ #include #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "gui.h" #include "pass.h" #include "logging.h" #include "version.h" #define NWIPE_GUI_PANE 8 /* Header window: width, height, x coordinate, y coordinate. */ #define NWIPE_GUI_HEADER_W COLS #define NWIPE_GUI_HEADER_H 1 #define NWIPE_GUI_HEADER_X 0 #define NWIPE_GUI_HEADER_Y 0 /* Footer window: width, height, x coordinate, y coordinate. */ #define NWIPE_GUI_FOOTER_W COLS #define NWIPE_GUI_FOOTER_H 1 #define NWIPE_GUI_FOOTER_X 0 #define NWIPE_GUI_FOOTER_Y (LINES -1) /* Options window: width, height, x coorindate, y coordinate. */ #define NWIPE_GUI_OPTIONS_W 44 #define NWIPE_GUI_OPTIONS_H 7 #define NWIPE_GUI_OPTIONS_Y 1 #define NWIPE_GUI_OPTIONS_X 0 /* Options fields, relative to their window. */ #define NWIPE_GUI_OPTIONS_TAB 10 #define NWIPE_GUI_OPTIONS_ENTROPY_Y 1 #define NWIPE_GUI_OPTIONS_ENTROPY_X 1 #define NWIPE_GUI_OPTIONS_PRNG_Y 2 #define NWIPE_GUI_OPTIONS_PRNG_X 1 #define NWIPE_GUI_OPTIONS_METHOD_Y 3 #define NWIPE_GUI_OPTIONS_METHOD_X 1 #define NWIPE_GUI_OPTIONS_VERIFY_Y 4 #define NWIPE_GUI_OPTIONS_VERIFY_X 1 #define NWIPE_GUI_OPTIONS_ROUNDS_Y 5 #define NWIPE_GUI_OPTIONS_ROUNDS_X 1 /* Stats window: width, height, x coordinate, y coordinate. */ #define NWIPE_GUI_STATS_W 36 #define NWIPE_GUI_STATS_H 7 #define NWIPE_GUI_STATS_Y 1 #define NWIPE_GUI_STATS_X 44 /* Stats fields, relative to their window. */ #define NWIPE_GUI_STATS_RUNTIME_Y 1 #define NWIPE_GUI_STATS_RUNTIME_X 1 #define NWIPE_GUI_STATS_ETA_Y 2 #define NWIPE_GUI_STATS_ETA_X 1 #define NWIPE_GUI_STATS_LOAD_Y 3 #define NWIPE_GUI_STATS_LOAD_X 1 #define NWIPE_GUI_STATS_THROUGHPUT_Y 4 #define NWIPE_GUI_STATS_THROUGHPUT_X 1 #define NWIPE_GUI_STATS_ERRORS_Y 5 #define NWIPE_GUI_STATS_ERRORS_X 1 #define NWIPE_GUI_STATS_TAB 16 /* Select window: width, height, x coordinate, y coordinate. */ #define NWIPE_GUI_MAIN_W COLS #define NWIPE_GUI_MAIN_H ( LINES - NWIPE_GUI_MAIN_Y -1 ) #define NWIPE_GUI_MAIN_Y 8 #define NWIPE_GUI_MAIN_X 0 /* Window pointers. */ WINDOW* footer_window; WINDOW* header_window; WINDOW* main_window; WINDOW* options_window; WINDOW* stats_window; PANEL* footer_panel; PANEL* header_panel; PANEL* main_panel; PANEL* options_panel; PANEL* stats_panel; /* Options window title. */ const char* options_title = " Options "; /* Statistics window title. */ const char* stats_title = " Statistics "; /* Footer labels. */ const char* nwipe_buttons1 = "Ctrl-C=Quit S=Start M=Method P=PRNG V=Verify R=Rounds B=Blanking-pass Space=Select"; const char* nwipe_buttons2 = " J=Up K=Down Space=Select"; const char* nwipe_buttons3 = " B=Blank screen, ctrl-c=Quit"; void nwipe_gui_title( WINDOW* w, const char* s ) { /** * Prints the string 's' centered on the first line of the window 'w'. * */ /* The number of lines in the window. (Not used.) */ int wy; /* The number of columns in the window. */ int wx; /* Get the window dimensions. */ getmaxyx( w, wy, wx ); /*Calculate available total margin */ int margin = (wx - strlen( s )); if (margin < 0) margin = 0; /* Print the title. */ mvwprintw( w, 0, margin / 2, "%s", s ); } /* nwipe_gui_title */ void nwipe_gui_init( void ) { /** * Initializes the ncurses gui. * */ /* Initialize the screen. */ initscr(); /* Disable TTY line buffering. */ cbreak(); /* Disable TTY echo. */ noecho(); /* Enable most special keys. */ keypad( stdscr, TRUE ); if( has_colors() ) { /* Initialize color capabilities. */ start_color(); if( can_change_color() ) { /* Redefine cyan to gray. */ init_color( COLOR_CYAN, 128, 128, 128 ); } /* Set white on blue as the emphasis color. */ init_pair( 1, COLOR_WHITE, COLOR_BLUE ); /* Set gray (or cyan) on blue as the normal color. */ init_pair( 2, COLOR_CYAN, COLOR_BLUE ); /* Set red on blue as the hilite color. */ init_pair( 3, COLOR_RED, COLOR_BLUE ); /* Set blue on white as the color for the header and footer windows. */ init_pair( 4, COLOR_BLUE, COLOR_WHITE ); /* Set white on green for success messages. */ init_pair( 5, COLOR_WHITE, COLOR_GREEN ); /* Set white on green for failure messages. */ init_pair( 6, COLOR_WHITE, COLOR_RED ); /* Set black on black for when hiding the display. */ init_pair( 7, COLOR_BLACK, COLOR_BLACK ); /* Set the background style. */ wbkgdset( stdscr, COLOR_PAIR(1) | ' ' ); } /* Clear the screen. */ wclear( stdscr ); /* Create the header window. */ header_window = newwin( NWIPE_GUI_HEADER_H, NWIPE_GUI_HEADER_W, NWIPE_GUI_HEADER_Y, NWIPE_GUI_HEADER_X ); header_panel = new_panel( header_window ); if( has_colors() ) { /* Set the background style of the header window. */ wbkgdset( header_window, COLOR_PAIR(4) | ' ' ); } /* Clear the header window. */ wclear( header_window ); /* Print the product banner. */ nwipe_gui_title( header_window, banner ); /* Create the footer window. */ footer_window = newwin( NWIPE_GUI_FOOTER_H, NWIPE_GUI_FOOTER_W, NWIPE_GUI_FOOTER_Y, NWIPE_GUI_FOOTER_X ); footer_panel = new_panel( footer_window ); if( has_colors() ) { /* Set the background style of the footer window. */ wbkgdset( footer_window, COLOR_PAIR(4) | ' ' ); } /* Clear the footer window. */ wclear( footer_window ); /* Create the options window. */ options_window = newwin( NWIPE_GUI_OPTIONS_H, NWIPE_GUI_OPTIONS_W, NWIPE_GUI_OPTIONS_Y, NWIPE_GUI_OPTIONS_X ); options_panel = new_panel( options_window ); if( has_colors() ) { /* Set the background style of the options window. */ wbkgdset( options_window, COLOR_PAIR(1) | ' ' ); /* Apply the color change to the options window. */ wattron( options_window, COLOR_PAIR(1) ); } /* Clear the options window. */ wclear( options_window ); /* Add a border. */ box( options_window, 0, 0 ); /* Create the stats window. */ stats_window = newwin( NWIPE_GUI_STATS_H, NWIPE_GUI_STATS_W, NWIPE_GUI_STATS_Y, NWIPE_GUI_STATS_X ); stats_panel = new_panel( stats_window ); if( has_colors() ) { /* Set the background style of the stats window. */ wbkgdset( stats_window, COLOR_PAIR(1) | ' ' ); /* Apply the color change to the stats window. */ wattron( stats_window, COLOR_PAIR(1) ); } /* Clear the new window. */ wclear( stats_window ); /* Add a border. */ box( stats_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( stats_window, stats_title ); /* Print field labels. */ mvwprintw( stats_window, NWIPE_GUI_STATS_RUNTIME_Y, NWIPE_GUI_STATS_RUNTIME_X, "Runtime: " ); mvwprintw( stats_window, NWIPE_GUI_STATS_ETA_Y, NWIPE_GUI_STATS_ETA_X, "Remaining: " ); mvwprintw( stats_window, NWIPE_GUI_STATS_LOAD_Y, NWIPE_GUI_STATS_LOAD_X, "Load Averages: " ); mvwprintw( stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_THROUGHPUT_X, "Throughput: " ); mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_ERRORS_X, "Errors: " ); /* Create the main window. */ main_window = newwin( NWIPE_GUI_MAIN_H, NWIPE_GUI_MAIN_W, NWIPE_GUI_MAIN_Y, NWIPE_GUI_MAIN_X ); main_panel = new_panel( main_window ); if( has_colors() ) { /* Set the background style. */ wbkgdset( main_window, COLOR_PAIR(1) | ' ' ); /* Apply the color change. */ wattron( main_window, COLOR_PAIR(1) ); } /* Clear the main window. */ werase( main_window ); /* Add a border. */ box( main_window, 0, 0 ); /* Refresh the screen. */ wrefresh( stdscr ); wrefresh( header_window ); wrefresh( footer_window ); wrefresh( options_window ); wrefresh( stats_window ); wrefresh( main_window ); update_panels(); doupdate(); /* Hide the cursor. */ curs_set( 0 ); } /* nwipe_gui_init */ void nwipe_gui_free( void ) { /** * Releases the ncurses gui. * */ /* Free ncurses resources. */ del_panel( footer_panel ); del_panel( header_panel ); del_panel( main_panel ); del_panel( options_panel ); del_panel( stats_panel ); delwin( footer_window ); delwin( header_window ); delwin( main_window ); delwin( options_window ); delwin( stats_window ); endwin(); } /* nwipe_gui_free */ void nwipe_gui_select( int count, nwipe_context_t** c ) { /** * The primary user interface. Allows the user to * change options and specify the devices to be wiped. * * @parameter count The number of contexts in the array. * @parameter c An array of device contexts. * * @modifies c[].select Sets the select flag according to user input. * @modifies options Sets program options according to to user input. * */ /* Widget labels. */ const char* select_title = " Disks and Partitions "; /* The number of lines available in the window. */ int wlines; /* The number of columns available in the window. */ int wcols; /* The number of selection elements that we can show in the window. */ int slots; /* The index of the element that is visible in the first slot. */ int offset = 0; /* The selection focus. */ int focus = 0; /* A generic loop variable. */ int i; /* User input buffer. */ int keystroke; /* The current working line. */ int yy; /* There is one slot per line. */ getmaxyx( main_window, wlines, wcols ); /* Less two lines for the box and two lines for padding. */ slots = wlines - 4; do { /* Clear the main window. */ werase( main_window ); /* Update the footer window. */ werase( footer_window ); nwipe_gui_title( footer_window, nwipe_buttons1 ); wrefresh( footer_window ); /* Update the options window. */ nwipe_gui_options(); /* Initialize the line offset. */ yy = 2; for( i = 0; i < slots && i < count ; i++ ) { /* Move to the next line. */ mvwprintw( main_window, yy++, 1, " " ); if( i + offset == focus ) { if( c[focus]->select == NWIPE_SELECT_TRUE || c[focus]->select == NWIPE_SELECT_FALSE ) { /* Print the 'enabled' cursor. */ waddch( main_window, ACS_RARROW ); } else { /* Print the 'disabled' cursor. */ waddch( main_window, ACS_DIAMOND ); } } else { /* Print whitespace. */ waddch( main_window, ' ' ); } switch( c[i+offset]->select ) { case NWIPE_SELECT_TRUE: wprintw( main_window, " [wipe] %i. %s - %s %s (%s)", (i + offset + 1), c[i+offset]->device_name, c[i+offset]->label, c[i+offset]->identity.serial_no, c[i+offset]->device_size_text ); break; case NWIPE_SELECT_FALSE: /* Print an element that is not selected. */ wprintw( main_window, " [ ] %i. %s - %s %s (%s)", (i + offset +1), c[i+offset]->device_name, c[i+offset]->label, c[i+offset]->identity.serial_no, c[i+offset]->device_size_text ); break; case NWIPE_SELECT_TRUE_PARENT: /* This element will be wiped when its parent is wiped. */ wprintw( main_window, " [****] %i. %s - %s %s (%s)", (i + offset +1), c[i+offset]->device_name, c[i+offset]->label, c[i+offset]->identity.serial_no, c[i+offset]->device_size_text ); break; case NWIPE_SELECT_FALSE_CHILD: /* We can't wipe this element because it has a child that is being wiped. */ wprintw( main_window, " [----] %i. %s - %s %s (%s)", (i + offset +1), c[i+offset]->device_name, c[i+offset]->label, c[i+offset]->identity.serial_no, c[i+offset]->device_size_text ); break; case NWIPE_SELECT_DISABLED: /* We don't know how to wipe this device. (Iomega Zip drives.) */ wprintw( main_window, " [????] %s", "Unrecognized Device" ); break; default: /* TODO: Handle the sanity error. */ break; } /* switch select */ } /* for */ if( offset > 0 ) { mvwprintw( main_window, 1, wcols -8, " More " ); waddch( main_window, ACS_UARROW ); } if( count - offset > slots ) { mvwprintw( main_window, wlines -2, wcols -8, " More " ); waddch( main_window, ACS_DARROW ); } /* Draw a border around the menu window. */ box( main_window, 0, 0 ); /* Print a title. */ nwipe_gui_title( main_window, select_title ); /* Refresh the window. */ wrefresh( main_window ); /* Get user input. */ keystroke = getch(); switch( keystroke ) { case KEY_DOWN: case 'j': case 'J': /* Increment the focus. */ focus += 1; if( focus >= count ) { /* The focus is already at the last element. */ focus = count -1; break; } if( focus - offset >= slots ) { /* The next element is offscreen. Scroll down. */ offset += 1; break; } break; case KEY_UP: case 'k': case 'K': /* Decrement the focus. */ focus -= 1; if( focus < 0 ) { /* The focus is already at the last element. */ focus = 0; break; } if( focus < offset ) { /* The next element is offscreen. Scroll up. */ offset -= 1; break; } break; case KEY_ENTER: case 10: case ' ': /* TODO: This block should be made into a function. */ if( c[focus]->select == NWIPE_SELECT_TRUE ) { /* Reverse the selection of this element. */ c[focus]->select = NWIPE_SELECT_FALSE; if( c[focus]->device_part == 0 ) { /* Sub-deselect all partitions and slices within this disk. */ for( i = 0 ; i < count ; i++ ) { if ( c[i]->device_type == c[focus]->device_type && c[i]->device_host == c[focus]->device_host && c[i]->device_bus == c[focus]->device_bus && c[i]->device_target == c[focus]->device_target && c[i]->device_lun == c[focus]->device_lun && c[i]->device_part > 0 ) { c[i]->select = NWIPE_SELECT_FALSE; } } /* for all contexts */ } /* if sub-deselect */ else { /* The number of selected partitions or slices within this disk. */ int j = 0; for( i = 0 ; i < count ; i++ ) { if ( c[i]->device_type == c[focus]->device_type && c[i]->device_host == c[focus]->device_host && c[i]->device_bus == c[focus]->device_bus && c[i]->device_target == c[focus]->device_target && c[i]->device_lun == c[focus]->device_lun && c[i]->device_part > 0 && c[i]->select == NWIPE_SELECT_TRUE ) { /* Increment the counter. */ j += 1; } } /* for all contexts */ if( j == 0 ) { /* Find the parent disk of this partition or slice. */ for( i = 0 ; i < count ; i++ ) { if ( c[i]->device_type == c[focus]->device_type && c[i]->device_host == c[focus]->device_host && c[i]->device_bus == c[focus]->device_bus && c[i]->device_target == c[focus]->device_target && c[i]->device_lun == c[focus]->device_lun && c[i]->device_part == 0 ) { /* Enable the disk element. */ c[i]->select = NWIPE_SELECT_FALSE; } } /* for all contexts */ } /* if */ } /* else super-enable */ break; } /* if NWIPE_SELECT_TRUE */ if( c[focus]->select == NWIPE_SELECT_FALSE ) { /* Reverse the selection. */ c[focus]->select = NWIPE_SELECT_TRUE; if( c[focus]->device_part == 0 ) { /* Sub-select all partitions and slices within this disk. */ for( i = 0 ; i < count ; i++ ) { if ( c[i]->device_type == c[focus]->device_type && c[i]->device_host == c[focus]->device_host && c[i]->device_bus == c[focus]->device_bus && c[i]->device_target == c[focus]->device_target && c[i]->device_lun == c[focus]->device_lun && c[i]->device_part > 0 ) { c[i]->select = NWIPE_SELECT_TRUE_PARENT; } } /* for */ } /* if sub-select */ else { /* ASSERT: ( c[focus]->device_part > 0 ) */ /* Super-deselect the disk that contains this device. */ for( i = 0 ; i < count ; i++ ) { if ( c[i]->device_type == c[focus]->device_type && c[i]->device_host == c[focus]->device_host && c[i]->device_bus == c[focus]->device_bus && c[i]->device_target == c[focus]->device_target && c[i]->device_lun == c[focus]->device_lun && c[i]->device_part == 0 ) { c[i]->select = NWIPE_SELECT_FALSE_CHILD; } } } /* else super-deselect */ break; } /* if NWIPE_SELECT_FALSE */ /* TODO: Explain to the user why they can't change this. */ break; case 'm': case 'M': /* Run the method dialog. */ nwipe_gui_method(); break; case 'p': case 'P': /* Run the PRNG dialog. */ nwipe_gui_prng(); break; case 'r': case 'R': /* Run the rounds dialog. */ nwipe_gui_rounds(); break; case 'v': case 'V': /* Run the option dialog. */ nwipe_gui_verify(); break; case 'b': case 'B': /* Run the noblank dialog. */ nwipe_gui_noblank(); break; } /* keystroke switch */ } while( keystroke != 'S' && keystroke != ERR ); /* Clear the main window. */ werase( main_window ); /* Refresh the main window. */ wrefresh( main_window ); /* Clear the footer. */ werase( footer_window ); /* Refresh the footer window. */ wrefresh( footer_window ); } /* nwipe_gui_select */ void nwipe_gui_options( void ) { /** * Updates the options window. * * @modifies options_window * */ /* Erase the window. */ werase( options_window ); mvwprintw( options_window, NWIPE_GUI_OPTIONS_ENTROPY_Y, NWIPE_GUI_OPTIONS_ENTROPY_X, \ "Entropy: Linux Kernel (urandom)" ); mvwprintw( options_window, NWIPE_GUI_OPTIONS_PRNG_Y, NWIPE_GUI_OPTIONS_PRNG_X, \ "PRNG: %s", nwipe_options.prng->label ); mvwprintw( options_window, NWIPE_GUI_OPTIONS_METHOD_Y, NWIPE_GUI_OPTIONS_METHOD_X, \ "Method: %s", nwipe_method_label( nwipe_options.method) ); mvwprintw( options_window, NWIPE_GUI_OPTIONS_VERIFY_Y, NWIPE_GUI_OPTIONS_VERIFY_X, "Verify: " ); switch( nwipe_options.verify ) { case NWIPE_VERIFY_NONE: wprintw( options_window, "Off" ); break; case NWIPE_VERIFY_LAST: wprintw( options_window, "Last Pass" ); break; case NWIPE_VERIFY_ALL: wprintw( options_window, "All Passes" ); break; default: wprintw( options_window, "Unknown %i", nwipe_options.verify ); } /* switch verify */ mvwprintw( options_window, NWIPE_GUI_OPTIONS_ROUNDS_Y, NWIPE_GUI_OPTIONS_ROUNDS_X, "Rounds: " ); if ( nwipe_options.noblank ) { wprintw( options_window, "%i (no final blanking pass)", nwipe_options.rounds); } else { wprintw( options_window, "%i (plus blanking pass)", nwipe_options.rounds); } /* Add a border. */ box( options_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( options_window, options_title ); /* Refresh the window. */ wrefresh( options_window ); } /* nwipe_gui_options */ void nwipe_gui_rounds( void ) { /** * Allows the user to change the rounds option. * * @modifies nwipe_options.rounds * @modifies main_window * */ /* Set the initial focus. */ int focus = nwipe_options.rounds; /* The first tabstop. */ const int tab1 = 2; /* The current working row. */ int yy; /* Input buffer. */ int keystroke; /* Erase the footer window. */ werase( footer_window ); wrefresh( footer_window ); do { /* Erase the main window. */ werase( main_window ); /* Add a border. */ box( main_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( main_window, " Rounds " ); /* Initialize the working row. */ yy = 4; /* 0 1 2 3 4 5 6 7 */ mvwprintw( main_window, yy++, tab1, "This is the number of times to run the wipe method on each device." ); mvwprintw( main_window, yy++, tab1, "" ); if( focus > 0 ) { /* Print the syslinux configuration hint. */ mvwprintw( main_window, yy++, tab1, "syslinux.cfg: nuke=\"nwipe --rounds %i\"", focus ); /* Print this line last so that the cursor is in the right place. */ mvwprintw( main_window, 2, tab1, "> %i", focus ); } else { mvwprintw( main_window, yy++, tab1, "The number of rounds must be a non-negative integer." ); /* Print this line last so that the cursor is in the right place. */ mvwprintw( main_window, 2, tab1, "> " ); } /* Reveal the cursor. */ curs_set( 1 ); /* Refresh the window. */ wrefresh( main_window ); /* Get a keystroke. */ keystroke = getch(); switch( keystroke ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if( focus < 100000000 ) { /* Left shift, base ten. */ focus *= 10; /* This assumes ASCII input, where the zero character is 0x30. */ focus += keystroke - 48; } break; case KEY_BACKSPACE: case KEY_LEFT: case 127: /* Right shift, base ten. */ focus /= 10; break; } /* switch keystroke */ /* Hide the cursor. */ curs_set( 0 ); } while( keystroke != 10 && keystroke != ERR ); if( focus > 0 ) { /* Set the number of rounds. */ nwipe_options.rounds = focus; } } /* nwipe_guid_rounds */ void nwipe_gui_prng( void ) { /** * Allows the user to change the PRNG. * * @modifies nwipe_options.prng * @modifies main_window * */ extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; /* The number of implemented PRNGs. */ const int count = 2; /* The first tabstop. */ const int tab1 = 2; /* The second tabstop. */ const int tab2 = 30; /* Set the initial focus. */ int focus = 0; /* The current working row. */ int yy; /* Input buffer. */ int keystroke; /* Update the footer window. */ werase( footer_window ); nwipe_gui_title( footer_window, nwipe_buttons2 ); wrefresh( footer_window ); if( nwipe_options.prng == &nwipe_twister ) { focus = 0; } if( nwipe_options.prng == &nwipe_isaac ) { focus = 1; } while( keystroke != ERR ) { /* Clear the main window. */ werase( main_window ); /* Initialize the working row. */ yy = 2; /* Print the options. */ mvwprintw( main_window, yy++, tab1, "" ); mvwprintw( main_window, yy++, tab1, "" ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_twister.label ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac.label ); mvwprintw( main_window, yy++, tab1, "" ); /* Print the cursor. */ mvwaddch( main_window, 4 + focus, tab1, ACS_RARROW ); switch( focus ) { case 0: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --prng twister\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "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 " ); mvwprintw( main_window, yy++, tab1, "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. " ); mvwprintw( main_window, yy++, tab1, " " ); break; case 1: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --prng isaac\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "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 " ); mvwprintw( main_window, yy++, tab1, "initial PRNG state by cryptanalysis of the ISAAC stream. " ); mvwprintw( main_window, yy++, tab1, " " ); break; } /* switch */ /* Add a border. */ box( main_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( main_window, " Pseudo Random Number Generator " ); /* Refresh the window. */ wrefresh( main_window ); /* Get a keystroke. */ keystroke = getch(); switch( keystroke ) { case KEY_DOWN: case 'j': case 'J': if( focus < count -1 ) { focus += 1; } break; case KEY_UP: case 'k': case 'K': if( focus > 0 ) { focus -= 1; } break; case KEY_ENTER: case ' ': case 10: if( focus == 0 ) { nwipe_options.prng = &nwipe_twister; } if( focus == 1 ) { nwipe_options.prng = &nwipe_isaac; } return; case KEY_BACKSPACE: case KEY_BREAK: return; } /* switch */ } /* while */ } /* nwipe_gui_prng */ void nwipe_gui_verify( void ) { /** * Allows the user to change the verification option. * * @modifies nwipe_options.verify * @modifies main_window * */ /* The number of definitions in the nwipe_verify_t enumeration. */ const int count = 3; /* The first tabstop. */ const int tab1 = 2; /* The second tabstop. */ const int tab2 = 30; /* Set the initial focus. */ int focus = nwipe_options.verify; /* The current working row. */ int yy; /* Input buffer. */ int keystroke; /* Update the footer window. */ werase( footer_window ); nwipe_gui_title( footer_window, nwipe_buttons2 ); wrefresh( footer_window ); while( keystroke != ERR ) { /* Clear the main window. */ werase( main_window ); /* Initialize the working row. */ yy = 2; /* Print the options. */ mvwprintw( main_window, yy++, tab1, " Verification Off " ); mvwprintw( main_window, yy++, tab1, " Verify Last Pass " ); mvwprintw( main_window, yy++, tab1, " Verify All Passes " ); mvwprintw( main_window, yy++, tab1, " " ); /* Print the cursor. */ mvwaddch( main_window, 2 + focus, tab1, ACS_RARROW ); switch( focus ) { case 0: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --verify off\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "Do not verify passes. The wipe will be a write-only operation. " ); mvwprintw( main_window, yy++, tab1, " " ); break; case 1: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --verify last\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "Check whether the device is actually empty after the last pass fills the " ); mvwprintw( main_window, yy++, tab1, "device with zeros. " ); break; case 2: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --verify all\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "After every pass, read back the pattern and check whether it is correct. " ); mvwprintw( main_window, yy++, tab1, " " ); mvwprintw( main_window, yy++, tab1, "This program writes the entire length of the device before it reads back " ); mvwprintw( main_window, yy++, tab1, "for verification, even for random pattern passes, to better ensure that " ); mvwprintw( main_window, yy++, tab1, "hardware caches are actually flushed. " ); break; } /* switch */ /* Add a border. */ box( main_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( main_window, " Verification Mode " ); /* Refresh the window. */ wrefresh( main_window ); /* Get a keystroke. */ keystroke = getch(); switch( keystroke ) { case KEY_DOWN: case 'j': case 'J': if( focus < count -1 ) { focus += 1; } break; case KEY_UP: case 'k': case 'K': if( focus > 0 ) { focus -= 1; } break; case KEY_ENTER: case ' ': case 10: if( focus >= 0 && focus < count ) { nwipe_options.verify = focus; } if( nwipe_options.verify != NWIPE_VERIFY_NONE ) { nwipe_options.noblank = 0; } return; case KEY_BACKSPACE: case KEY_BREAK: return; } /* switch */ } /* while */ } /* nwipe_gui_verify */ void nwipe_gui_noblank( void ) { /** * Allows the user to change the verification option. * * @modifies nwipe_options.noblank * @modifies main_window * */ /* The number of options available. */ const int count = 2; /* The first tabstop. */ const int tab1 = 2; /* The second tabstop. */ const int tab2 = 40; /* Set the initial focus. */ int focus = nwipe_options.noblank; /* The current working row. */ int yy; /* Input buffer. */ int keystroke; /* Update the footer window. */ werase( footer_window ); nwipe_gui_title( footer_window, nwipe_buttons2 ); wrefresh( footer_window ); while( keystroke != ERR ) { /* Clear the main window. */ werase( main_window ); /* Initialize the working row. */ yy = 2; /* Print the options. */ mvwprintw( main_window, yy++, tab1, " Perform a final blanking pass " ); mvwprintw( main_window, yy++, tab1, " Do not perform final blanking pass " ); mvwprintw( main_window, yy++, tab1, " " ); /* Print the cursor. */ mvwaddch( main_window, 2 + focus, tab1, ACS_RARROW ); switch( focus ) { case 0: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "Perform a final blanking pass after the wipe, leaving disk with only zeros. " ); mvwprintw( main_window, yy++, tab1, " " ); break; case 1: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe -b\"" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "Do not perform a final blanking pass. Leave data as per final wiping pass. " ); mvwprintw( main_window, yy++, tab1, "Any verification options will be ignored. Not compatible with Quick Erase. " ); break; } /* switch */ /* Add a border. */ box( main_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( main_window, " Final Blanking Pass " ); /* Refresh the window. */ wrefresh( main_window ); /* Get a keystroke. */ keystroke = getch(); switch( keystroke ) { case KEY_DOWN: case 'j': case 'J': if( focus < count -1 ) { focus += 1; } break; case KEY_UP: case 'k': case 'K': if( focus > 0 ) { focus -= 1; } break; case KEY_ENTER: case ' ': case 10: if( focus >= 0 && focus < count ){ nwipe_options.noblank = focus; } if ( nwipe_options.noblank ) { nwipe_options.verify = NWIPE_VERIFY_NONE; } return; case KEY_BACKSPACE: case KEY_BREAK: return; } /* switch */ } /* while */ } /* nwipe_gui_noblank */ void nwipe_gui_method( void ) { /** * Allows the user to change the wipe method. * * @modifies nwipe_options.method * @modifies main_window * */ /* The number of implemented methods. */ const int count = 6; /* The first tabstop. */ const int tab1 = 2; /* The second tabstop. */ const int tab2 = 30; /* The currently selected method. */ int focus = 0; /* The current working row. */ int yy; /* Input buffer. */ int keystroke; /* Update the footer window. */ werase( footer_window ); nwipe_gui_title( footer_window, nwipe_buttons2 ); wrefresh( footer_window ); if( nwipe_options.method == &nwipe_zero ) { focus = 0; } if( nwipe_options.method == &nwipe_ops2 ) { focus = 1; } if( nwipe_options.method == &nwipe_dodshort ) { focus = 2; } if( nwipe_options.method == &nwipe_dod522022m ) { focus = 3; } if( nwipe_options.method == &nwipe_gutmann ) { focus = 4; } if( nwipe_options.method == &nwipe_random ) { focus = 5; } do { /* Clear the main window. */ werase( main_window ); /* Initialize the working row. */ yy = 2; /* Print the options. */ mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_zero ) ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_ops2 ) ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_dodshort ) ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_dod522022m ) ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_gutmann ) ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_method_label( &nwipe_random ) ); mvwprintw( main_window, yy++, tab1, " " ); /* Print the cursor. */ mvwaddch( main_window, 2 + focus, tab1, ACS_RARROW ); switch( focus ) { case 0: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method zero\"" ); mvwprintw( main_window, 3, tab2, "Security Level: Low (1 pass)" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "This method fills the device with zeros. Note that the rounds option does " ); mvwprintw( main_window, yy++, tab1, "not apply to this method. This method always runs one round. " ); mvwprintw( main_window, yy++, tab1, " " ); mvwprintw( main_window, yy++, tab1, "Use this method to blank disks before internal redeployment, or before " ); mvwprintw( main_window, yy++, tab1, "reinstalling Microsoft Windows to remove the data areas that the format " ); mvwprintw( main_window, yy++, tab1, "utility preserves. " ); break; case 1: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method ops2\"" ); mvwprintw( main_window, 3, tab2, "Security Level: Medium (8 passes)" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "The Royal Canadian Mounted Police Technical Security Standard for " ); mvwprintw( main_window, yy++, tab1, "Information Technology, Appendix OPS-II: Media Sanitization. " ); mvwprintw( main_window, yy++, tab1, " " ); mvwprintw( main_window, yy++, tab1, "This implementation, with regards to paragraph 2 section A of the standard, " ); mvwprintw( main_window, yy++, tab1, "uses a pattern that is one random byte and that is changed each round. " ); break; case 2: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method dodshort\"" ); mvwprintw( main_window, 3, tab2, "Security Level: Medium (3 passes)" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "The American Department of Defense 5220.22-M short wipe. " ); mvwprintw( main_window, yy++, tab1, "This method is composed of passes 1,2,7 from the standard wipe. " ); break; case 3: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method dod522022m\"" ); mvwprintw( main_window, 3, tab2, "Security Level: Medium (7 passes)" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "The American Department of Defense 5220.22-M standard wipe. " ); mvwprintw( main_window, yy++, tab1, "This implementation uses the same algorithm as the Heidi Eraser product. " ); break; case 4: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method gutmann\"" ); mvwprintw( main_window, 3, tab2, "Security Level: High (35 passes)" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "This is the method described by Peter Gutmann in the paper entitled " ); mvwprintw( main_window, yy++, tab1, "\"Secure Deletion of Data from Magnetic and Solid-State Memory\". " ); break; case 5: mvwprintw( main_window, 2, tab2, "syslinux.cfg: nuke=\"nwipe --method random\"" ); mvwprintw( main_window, 3, tab2, "Security Level: Depends on Rounds" ); /* 0 1 2 3 4 5 6 7 8 */ mvwprintw( main_window, yy++, tab1, "This method fills the device with a stream from the PRNG. It is probably the " ); mvwprintw( main_window, yy++, tab1, "best method to use on modern hard disk drives because encoding schemes vary. " ); mvwprintw( main_window, yy++, tab1, " " ); mvwprintw( main_window, yy++, tab1, "This method has a medium security level with 4 rounds, and a high security " ); mvwprintw( main_window, yy++, tab1, "level with 8 rounds. " ); break; } /* switch */ /* Add a border. */ box( main_window, 0, 0 ); /* Add a title. */ nwipe_gui_title( main_window, " Wipe Method " ); /* Refresh the window. */ wrefresh( main_window ); /* Get a keystroke. */ keystroke = getch(); switch( keystroke ) { case KEY_DOWN: case 'j': case 'J': if( focus < count -1 ) { focus += 1; } break; case KEY_UP: case 'k': case 'K': if( focus > 0 ) { focus -= 1; } break; case KEY_BACKSPACE: case KEY_BREAK: return; } /* switch */ } while( keystroke != KEY_ENTER && keystroke != ' ' && keystroke != 10 && keystroke != ERR ); switch( focus ) { case 0: nwipe_options.method = &nwipe_zero; break; case 1: nwipe_options.method = &nwipe_ops2; break; case 2: nwipe_options.method = &nwipe_dodshort; break; case 3: nwipe_options.method = &nwipe_dod522022m; break; case 4: nwipe_options.method = &nwipe_gutmann; break; case 5: nwipe_options.method = &nwipe_random; break; } } /* nwipe_gui_method */ void nwipe_gui_load( void ) { /** * Prints the system load average to the statistics window. * * @modifies stat_window Prints the system load average to the statistics window. * */ /* A file handle for the stat file. */ FILE* nwipe_fp; /* The one, five, and fifteen minute load averages. */ float load_01; float load_05; float load_15; /* Open the loadavg file. */ nwipe_fp = fopen( NWIPE_KNOB_LOADAVG, "r" ); /* Print the label. */ mvwprintw( stats_window, NWIPE_GUI_STATS_LOAD_Y, NWIPE_GUI_STATS_LOAD_X, "Load Averages:" ); if( nwipe_fp ) { /* The load averages are the first three numbers in the file. */ if( 3 == fscanf( nwipe_fp, "%f %f %f", &load_01, &load_05, &load_15 ) ) { /* Print the load average. */ mvwprintw( stats_window, NWIPE_GUI_STATS_LOAD_Y, NWIPE_GUI_STATS_TAB, "%04.2f %04.2f %04.2f", load_01, load_05, load_15 ); } else { /* Print an error. */ mvwprintw( stats_window, NWIPE_GUI_STATS_LOAD_Y, NWIPE_GUI_STATS_TAB, "(fscanf error %i)", errno ); } /* Close the loadavg file. */ fclose( nwipe_fp ); } else { mvwprintw( stats_window, NWIPE_GUI_STATS_LOAD_Y, NWIPE_GUI_STATS_TAB, "(fopen error %i)", errno ); } } /* nwipe_gui_load */ void *nwipe_gui_status( void *ptr ) { /** * Shows runtime statistics and overall progress. * * @parameter count The number of contexts in the array. * @parameter c An array of device contexts. * * @modifies main_window Prints information into the main window. * @modifies c[].throughput Updates the i/o throughput value. * */ nwipe_thread_data_ptr_t *nwipe_thread_data_ptr; nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t *) ptr; nwipe_context_t **c; nwipe_misc_thread_data_t *nwipe_misc_thread_data; int count; c = nwipe_thread_data_ptr->c; nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data; count = nwipe_misc_thread_data->nwipe_selected; /* Throughput print formats. */ char* nwipe_tera = "%llu TB/s"; char* nwipe_giga = "%llu GB/s"; char* nwipe_mega = "%llu MB/s"; char* nwipe_kilo = "%llu KB/s"; char* nwipe_unit = "%llu B/s"; /* The throughput format pointer. */ char* nwipe_format; /* We count time from when this function is first called. */ static time_t nwipe_time_start = 0; /* Whether the screen has been blanked by the user. */ static int nwipe_gui_blank = 0; /* The current time. */ time_t nwipe_time_now; /* The index of the element that is visible in the first slot. */ static int offset; /* The number of elements that we can show in the window. */ int slots; /* Window dimensions. */ int wlines; int wcols; /* Generic loop variable. */ int i; /* The current working line in the main window. */ int yy; /* User input buffer. */ int keystroke; /* The combined througput of all processes. */ nwipe_misc_thread_data->throughput = 0; /* The estimated runtime of the slowest device. */ nwipe_misc_thread_data->maxeta = 0; /* The combined number of errors of all processes. */ nwipe_misc_thread_data->errors = 0; /* Time values. */ int nwipe_hh; int nwipe_mm; int nwipe_ss; /* The number of active wipe processes. */ /* Set to 1 initially to start loop. */ int nwipe_active = 1; if( nwipe_time_start == 0 ) { /* This is the first time that we have been called. */ nwipe_time_start = time( NULL ) -1; } /* Get the window dimensions. */ getmaxyx( main_window, wlines, wcols ); /* Less four lines for the box and padding. */ slots = wlines - 4; /* Each element prints three lines. */ slots /= 3; /* Add text to footer window */ nwipe_gui_title( footer_window, nwipe_buttons3 ); wrefresh( footer_window ); while ( nwipe_active ) { /* Get the current time. */ nwipe_time_now = time( NULL ); /* Erase the main window. */ werase( main_window ); /* Erase the stats window. */ werase( stats_window ); /* Initialize our working offset to the third line. */ yy = 2; /* Try to get a keystroke. */ keystroke = getch(); if ( keystroke > 0 && nwipe_gui_blank == 1 ) { /* Show screen */ nwipe_gui_blank = 0; /* Set background */ wbkgdset( stdscr, COLOR_PAIR(1) ); wclear( stdscr ); /* Unhide panels */ show_panel(header_panel); show_panel(footer_panel); show_panel(stats_panel); show_panel(options_panel); show_panel(main_panel); /* Update panels */ update_panels(); doupdate(); } else if ( keystroke > 0 ) { switch( keystroke ) { case 'b': case 'B': /* Blank screen. */ nwipe_gui_blank = 1; hide_panel(header_panel); hide_panel(footer_panel); hide_panel(stats_panel); hide_panel(options_panel); hide_panel(main_panel); /* Set the background style. */ wbkgdset( stdscr, COLOR_PAIR(7) ); wclear( stdscr ); break; case KEY_DOWN: case 'j': case 'J': /* Scroll down. */ offset += 1; if( count < slots ) { offset = 0; } else if( offset + slots > count ) { offset = count - slots; } break; case KEY_UP: case 'k': case 'K': /* Scroll up. */ offset -= 1; if( offset < 0 ) { offset = 0; } break; default: /* Do nothing. */ break; } } /* keystroke */ /* Update screen if not blanked. */ if ( nwipe_gui_blank == 0 ) { nwipe_active = compute_stats(ptr); // Returns number of active wipe threads /* Print information for the user. */ for( i = offset ; i < offset + slots && i < count ; i++ ) { /* Print the context label. */ if ( strlen(c[i]->identity.serial_no) ) { mvwprintw( main_window, yy++, 2, "%s - %s (%s)", c[i]->device_name, c[i]->label, c[i]->identity.serial_no); } else { mvwprintw( main_window, yy++, 2, "%s - %s", c[i]->device_name, c[i]->label ); } /* Check whether the child process is still running the wipe. */ if( c[i]->thread > 0 ) { /* Print percentage and pass information. */ mvwprintw( main_window, yy++, 4, "[%05.2f%%, round %i of %i, pass %i of %i] ", \ c[i]->round_percent, c[i]->round_working, c[i]->round_count, c[i]->pass_working, c[i]->pass_count ); } /* child running */ else { if( c[i]->result == 0 ) { mvwprintw( main_window, yy++, 4, "(success) " ); } else if( c[i]->signal ) { mvwprintw( main_window, yy++, 4, "(failure, signal %i) ", c[i]->signal ); } else { mvwprintw( main_window, yy++, 4, "(failure, code %i) ", c[i]->result ); } } /* child returned */ if( c[i]->verify_errors ) { wprintw( main_window, "[verify errors: %llu] ", c[i]->verify_errors ); } if( c[i]->pass_errors ) { wprintw( main_window, "[pass errors: %llu] ", c[i]->pass_errors ); } switch( c[i]->pass_type ) { case NWIPE_PASS_FINAL_BLANK: wprintw( main_window, "[blanking] " ); break; case NWIPE_PASS_FINAL_OPS2: wprintw( main_window, "[OPS-II final] " ); break; case NWIPE_PASS_WRITE: wprintw( main_window, "[writing] " ); break; case NWIPE_PASS_VERIFY: wprintw( main_window, "[verifying] " ); break; case NWIPE_PASS_NONE: break; } if( c[i]->sync_status ) { wprintw( main_window, "[syncing] " ); } if( c[i]->throughput >= INT64_C( 1000000000000 ) ) { wprintw( main_window, "[%llu TB/s] ", c[i]->throughput / INT64_C( 1000000000000 ) ); } else if( c[i]->throughput >= INT64_C( 1000000000 ) ) { wprintw( main_window, "[%llu GB/s] ", c[i]->throughput / INT64_C( 1000000000 ) ); } else if( c[i]->throughput >= INT64_C( 1000000 ) ) { wprintw( main_window, "[%llu MB/s] ", c[i]->throughput / INT64_C( 1000000 ) ); } else if( c[i]->throughput >= INT64_C( 1000 ) ) { wprintw( main_window, "[%llu KB/s] ", c[i]->throughput / INT64_C( 1000 ) ); } else { wprintw( main_window, "[%llu B/s] ", c[i]->throughput / INT64_C( 1 ) ); } /* Insert whitespace. */ yy += 1; } /* for */ if( offset > 0 ) { mvwprintw( main_window, 1, wcols -8, " More " ); waddch( main_window, ACS_UARROW ); } if( count - offset > slots ) { mvwprintw( main_window, wlines -2, wcols -8, " More " ); waddch( main_window, ACS_DARROW ); } /* Box the main window. */ box( main_window, 0, 0 ); /* Refresh the main window. */ wrefresh( main_window ); /* Update the load average field. */ nwipe_gui_load(); u64 nwipe_throughput = nwipe_misc_thread_data->throughput; if( nwipe_throughput >= INT64_C( 1000000000000 ) ) { nwipe_throughput /= INT64_C( 1000000000000 ); nwipe_format = nwipe_tera; } else if( nwipe_throughput >= INT64_C( 1000000000 ) ) { nwipe_throughput /= INT64_C( 1000000000 ); nwipe_format = nwipe_giga; } else if( nwipe_throughput >= INT64_C( 1000000 ) ) { nwipe_throughput /= INT64_C( 1000000 ); nwipe_format = nwipe_mega; } else if( nwipe_throughput >= INT64_C( 1000 ) ) { nwipe_throughput /= INT64_C( 1000 ); nwipe_format = nwipe_kilo; } else { nwipe_throughput /= INT64_C( 1 ); nwipe_format = nwipe_unit; } /* Print the combined throughput. */ mvwprintw( stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_THROUGHPUT_X, "Throughput:" ); if( nwipe_throughput > 0 ) { mvwprintw( stats_window, NWIPE_GUI_STATS_THROUGHPUT_Y, NWIPE_GUI_STATS_TAB, nwipe_format, nwipe_throughput ); } /* Change the current time into a delta. */ nwipe_time_now -= nwipe_time_start; /* Put the delta into HH:mm:ss form. */ nwipe_hh = nwipe_time_now / 3600; nwipe_time_now %= 3600; nwipe_mm = nwipe_time_now / 60; nwipe_time_now %= 60; nwipe_ss = nwipe_time_now; /* Print the runtime. */ mvwprintw( stats_window, NWIPE_GUI_STATS_RUNTIME_Y, 1, "Runtime:" ); mvwprintw( stats_window, NWIPE_GUI_STATS_RUNTIME_Y, NWIPE_GUI_STATS_TAB, "%02i:%02i:%02i", nwipe_hh, nwipe_mm, nwipe_ss ); mvwprintw( stats_window, NWIPE_GUI_STATS_ETA_Y, 1, "Remaining:" ); time_t nwipe_maxeta = nwipe_misc_thread_data->maxeta; if( nwipe_maxeta > 0 ) { /* Do it again for the estimated runtime remaining. */ nwipe_hh = nwipe_maxeta / 3600; nwipe_maxeta %= 3600; nwipe_mm = nwipe_maxeta / 60; nwipe_maxeta %= 60; nwipe_ss = nwipe_maxeta; /* Print the estimated runtime remaining. */ mvwprintw( stats_window, NWIPE_GUI_STATS_ETA_Y, NWIPE_GUI_STATS_TAB, "%02i:%02i:%02i", nwipe_hh, nwipe_mm, nwipe_ss ); } /* Print the error count. */ mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_ERRORS_X, "Errors:" ); mvwprintw( stats_window, NWIPE_GUI_STATS_ERRORS_Y, NWIPE_GUI_STATS_TAB, "%llu", nwipe_misc_thread_data->errors ); /* Add a border. */ box( stats_window, 0, 0 ); /* Add a title. */ mvwprintw( stats_window, 0, ( NWIPE_GUI_STATS_W - strlen( stats_title ) ) /2, "%s", stats_title ); /* Refresh the stats window. */ wrefresh( stats_window ); } // end blank screen if if (nwipe_options.logfile[0] == '\0') { // Logging to STDOUT. Flush log. def_prog_mode(); /* Save the tty modes */ endwin(); /* End curses mode temporarily */ /* Flush stdout and disable buffering, otherwise output missed new lines. */ fflush(stdout); setbuf(stdout, NULL); pthread_mutex_lock( &mutex1 ); for (i=0; i < log_current_element; i++) { printf("%s\n", log_lines[i]); } log_current_element = 0; pthread_mutex_unlock( &mutex1 ); reset_prog_mode(); /* Return to the previous tty mode*/ /* stored by def_prog_mode() */ refresh(); /* Do refresh() to restore the */ /* Screen contents */ } /* Test for a thread cancellation request */ pthread_testcancel(); } // while if (nwipe_options.logfile[0] == '\0') { nwipe_gui_title( footer_window, "Wipe finished - press enter to exit. Logged to STDOUT" ); } else { char finish_message[NWIPE_GUI_FOOTER_W]; snprintf(finish_message, sizeof(finish_message), "Wipe finished - press enter to exit. Logged to %s", nwipe_options.logfile); nwipe_gui_title( footer_window, finish_message ); } wrefresh( footer_window ); nwipe_misc_thread_data->gui_thread = 0; return NULL; } /* nwipe_gui_status */ int compute_stats(void *ptr) { nwipe_thread_data_ptr_t *nwipe_thread_data_ptr; nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t *) ptr; nwipe_context_t **c; nwipe_misc_thread_data_t *nwipe_misc_thread_data; c = nwipe_thread_data_ptr->c; nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data; int count = nwipe_misc_thread_data->nwipe_selected; int nwipe_active = 0; int i; time_t nwipe_time_now = time( NULL ); nwipe_misc_thread_data->throughput = 0; nwipe_misc_thread_data->maxeta = 0; /* Enumerate all contexts to compute statistics. */ for( i = 0 ; i < count ; i++ ) { /* Check whether the child process is still running the wipe. */ if( c[i]->thread > 0 ) { /* Increment the child counter. */ nwipe_active += 1; /* Maintain a rolling average of throughput. */ nwipe_update_speedring( &c[i]->speedring, c[i]->round_done, nwipe_time_now ); if( c[i]->speedring.timestotal > 0 ) { /* Update the current average throughput in bytes-per-second. */ c[i]->throughput = c[i]->speedring.bytestotal / c[i]->speedring.timestotal; /* Update the estimated remaining runtime. */ /* Check that throughput is not zero (sometimes caused during a sync) */ if (c[i]->throughput == 0) { c[i]->throughput = 1; } c[i]->eta = ( c[i]->round_size - c[i]->round_done ) / c[i]->throughput; if( c[i]->eta > nwipe_misc_thread_data->maxeta ) { nwipe_misc_thread_data->maxeta = c[i]->eta; } } /* Update the percentage value. */ c[i]->round_percent = (double) c[i]->round_done / (double) c[i]->round_size * 100; /* Accumulate combined throughput. */ nwipe_misc_thread_data->throughput += c[i]->throughput; } /* child running */ /* Accumulate the error count. */ nwipe_misc_thread_data->errors += c[i]->pass_errors; nwipe_misc_thread_data->errors += c[i]->verify_errors; } /* for statistics */ return nwipe_active; } void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_bytes, time_t speedring_now ) { if( speedring->timeslast == 0 ) { /* Ignore the first sample and initialize. */ speedring->timeslast = speedring_now; return; } if( speedring_now - speedring->timeslast < NWIPE_KNOB_SPEEDRING_GRANULARITY ) { /* Avoid jitter caused by frequent updates. */ return; } /* Subtract the oldest speed sample from the accumulator. */ speedring->bytestotal -= speedring->bytes[ speedring->position ]; speedring->timestotal -= speedring->times[ speedring->position ]; /* Put the lastest bytes-per-second sample into the ring buffer. */ speedring->bytes[ speedring->position ] = speedring_bytes - speedring->byteslast; speedring->times[ speedring->position ] = speedring_now - speedring->timeslast; /* Add the newest speed sample to the accumulator. */ speedring->bytestotal += speedring->bytes[ speedring->position ]; speedring->timestotal += speedring->times[ speedring->position ]; /* Remember the last sample. */ speedring->byteslast = speedring_bytes; speedring->timeslast = speedring_now; if( ++speedring->position >= NWIPE_KNOB_SPEEDRING_SIZE ) { speedring->position = 0; } } /* eof */ nwipe-0.24/src/gui.h000066400000000000000000000036421321204421400143030ustar00rootroot00000000000000/* * gui.h: An ncurses GUI for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef GUI_H_ #define GUI_H_ void nwipe_gui_free( void ); /* Stop the GUI. */ void nwipe_gui_init( void ); /* Start the GUI. */ void nwipe_gui_select( int count, nwipe_context_t** c ); /* Select devices to wipe. */ void *nwipe_gui_status( void *ptr ); /* Update operation progress. */ void nwipe_gui_method( void ); /* Change the method option. */ void nwipe_gui_options( void ); /* Update the options window. */ void nwipe_gui_prng( void ); /* Change the prng option. */ void nwipe_gui_rounds( void ); /* Change the rounds option. */ void nwipe_gui_verify( void ); /* Change the verify option. */ void nwipe_gui_noblank( void ); /* Change the noblank option. */ int compute_stats(void *ptr); void nwipe_update_speedring( nwipe_speedring_t* speedring, u64 speedring_done, time_t speedring_now ); #endif /* GUI_H_ */ /* eof */ nwipe-0.24/src/isaac_rand.c000066400000000000000000000073101321204421400155720ustar00rootroot00000000000000/* ------------------------------------------------------------------------------ rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain. MODIFIED: 960327: Creation (addition of randinit, really) 970719: use context, not global variables, for internal state 980324: added main (ifdef'ed out), also rearranged randinit() 010626: Note that this is public domain ------------------------------------------------------------------------------ */ #ifndef STANDARD #include "isaac_standard.h" #endif #ifndef RAND #include "isaac_rand.h" #endif #define ind(mm,x) (*(ub4 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<2)))) #define rngstep(mix,a,b,mm,m,m2,r,x) \ { \ x = *m; \ a = (a^(mix)) + *(m2++); \ *(m++) = y = ind(mm,x) + a + b; \ *(r++) = b = ind(mm,y>>RANDSIZL) + x; \ } void isaac(ctx) randctx *ctx; { register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend; mm=ctx->randmem; r=ctx->randrsl; a = ctx->randa; b = ctx->randb + (++ctx->randc); for (m = mm, mend = m2 = m+(RANDSIZ/2); m>6 , a, b, mm, m, m2, r, x); rngstep( a<<2 , a, b, mm, m, m2, r, x); rngstep( a>>16, a, b, mm, m, m2, r, x); } for (m2 = mm; m2>6 , a, b, mm, m, m2, r, x); rngstep( a<<2 , a, b, mm, m, m2, r, x); rngstep( a>>16, a, b, mm, m, m2, r, x); } ctx->randb = b; ctx->randa = a; } #define mix(a,b,c,d,e,f,g,h) \ { \ a^=b<<11; d+=a; b+=c; \ b^=c>>2; e+=b; c+=d; \ c^=d<<8; f+=c; d+=e; \ d^=e>>16; g+=d; e+=f; \ e^=f<<10; h+=e; f+=g; \ f^=g>>4; a+=f; g+=h; \ g^=h<<8; b+=g; h+=a; \ h^=a>>9; c+=h; a+=b; \ } /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */ void randinit(ctx, flag) randctx *ctx; word flag; { word i; ub4 a,b,c,d,e,f,g,h; ub4 *m,*r; ctx->randa = ctx->randb = ctx->randc = 0; m=ctx->randmem; r=ctx->randrsl; a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ for (i=0; i<4; ++i) /* scramble it */ { mix(a,b,c,d,e,f,g,h); } if (flag) { /* initialize using the contents of r[] as the seed */ for (i=0; irandcnt=RANDSIZ; /* prepare to use the first set of results */ } #ifdef NEVER int main() { ub4 i,j; randctx ctx; ctx.randa=ctx.randb=ctx.randc=(ub4)0; for (i=0; i<256; ++i) ctx.randrsl[i]=(ub4)0; randinit(&ctx, TRUE); for (i=0; i<2; ++i) { isaac(&ctx); for (j=0; j<256; ++j) { printf("%.8lx",ctx.randrsl[j]); if ((j&7)==7) printf("\n"); } } } #endif nwipe-0.24/src/isaac_rand.h000066400000000000000000000031151321204421400155760ustar00rootroot00000000000000/* ------------------------------------------------------------------------------ rand.h: definitions for a random number generator By Bob Jenkins, 1996, Public Domain MODIFIED: 960327: Creation (addition of randinit, really) 970719: use context, not global variables, for internal state 980324: renamed seed to flag 980605: recommend RANDSIZL=4 for noncryptography. 010626: note this is public domain ------------------------------------------------------------------------------ */ #ifndef STANDARD #include "isaac_standard.h" #endif #ifndef RAND #define RAND #define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */ #define RANDSIZ (1<randcnt-- ? \ (isaac(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \ (r)->randrsl[(r)->randcnt]) #endif /* RAND */ nwipe-0.24/src/isaac_standard.h000066400000000000000000000031211321204421400164470ustar00rootroot00000000000000/* ------------------------------------------------------------------------------ Standard definitions and types, Bob Jenkins ------------------------------------------------------------------------------ */ #ifndef STANDARD # define STANDARD # ifndef STDIO # include # define STDIO # endif # ifndef STDDEF # include # define STDDEF # endif typedef unsigned long long ub8; #define UB8MAXVAL 0xffffffffffffffffLL #define UB8BITS 64 typedef signed long long sb8; #define SB8MAXVAL 0x7fffffffffffffffLL typedef unsigned long int ub4; /* unsigned 4-byte quantities */ #define UB4MAXVAL 0xffffffff typedef signed long int sb4; #define UB4BITS 32 #define SB4MAXVAL 0x7fffffff typedef unsigned short int ub2; #define UB2MAXVAL 0xffff #define UB2BITS 16 typedef signed short int sb2; #define SB2MAXVAL 0x7fff typedef unsigned char ub1; #define UB1MAXVAL 0xff #define UB1BITS 8 typedef signed char sb1; /* signed 1-byte quantities */ #define SB1MAXVAL 0x7f typedef int word; /* fastest type available */ #define bis(target,mask) ((target) |= (mask)) #define bic(target,mask) ((target) &= ~(mask)) #define bit(target,mask) ((target) & (mask)) #ifndef min # define min(a,b) (((a)<(b)) ? (a) : (b)) #endif /* min */ #ifndef max # define max(a,b) (((a)<(b)) ? (b) : (a)) #endif /* max */ #ifndef align # define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1))) #endif /* align */ #ifndef abs # define abs(a) (((a)>0) ? (a) : -(a)) #endif #define TRUE 1 #define FALSE 0 #define SUCCESS 0 /* 1 on VAX */ #endif /* STANDARD */ nwipe-0.24/src/logging.c000066400000000000000000000126301321204421400151350ustar00rootroot00000000000000/* * logging.c: Logging facilities for nwipe. * * Copyright Darik Horn . * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "logging.h" int const MAX_LOG_LINE_CHARS = 512; /* Global array to hold log values to print when logging to STDOUT */ char **log_lines; int log_current_element = 0; int log_elements_allocated = 0; pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; void nwipe_log( nwipe_log_t level, const char* format, ... ) { /** * Writes a message to the program log file. * */ /* A time buffer. */ time_t t; /* A pointer to the system time struct. */ struct tm* p; /* Get the current time. */ t = time( NULL ); p = localtime( &t ); pthread_mutex_lock( &mutex1 ); /* Increase the current log element pointer - we will write here */ if (log_current_element == log_elements_allocated) { log_elements_allocated++; log_lines = (char **) realloc (log_lines, (log_elements_allocated) * sizeof(char *)); log_lines[log_current_element] = malloc(MAX_LOG_LINE_CHARS * sizeof(char)); } /* Position of writing to current log string */ int line_current_pos = 0; /* Print the date. The rc script uses the same format. */ line_current_pos = snprintf( log_lines[log_current_element], MAX_LOG_LINE_CHARS, "[%i/%02i/%02i %02i:%02i:%02i] nwipe: ", \ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec ); switch( level ) { case NWIPE_LOG_NONE: /* Do nothing. */ break; case NWIPE_LOG_DEBUG: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "debug: " ); break; case NWIPE_LOG_INFO: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "info: " ); break; case NWIPE_LOG_NOTICE: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "notice: " ); break; case NWIPE_LOG_WARNING: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "warning: " ); break; case NWIPE_LOG_ERROR: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "error: " ); break; case NWIPE_LOG_FATAL: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "fatal: " ); break; case NWIPE_LOG_SANITY: /* TODO: Request that the user report the log. */ line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "sanity: " ); break; default: line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "level %i: ", level ); } /* The variable argument pointer. */ va_list ap; /* Fetch the argument list. */ va_start( ap, format ); /* Print the event. */ line_current_pos += vsnprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, format, ap ); /* if( level >= NWIPE_LOG_WARNING ) { vfprintf( stderr, format, ap ); } */ /* Release the argument list. */ va_end( ap ); /* if( level >= NWIPE_LOG_WARNING ) { fprintf( stderr, "\n" ); } */ /* A result buffer. */ int r; /* The log file pointer. */ FILE* fp; /* The log file descriptor. */ int fd; if (nwipe_options.logfile[0] == '\0') { if (nwipe_options.nogui) { printf( "%s\n", log_lines[log_current_element] ); } else { log_current_element++; } } else { /* Open the log file for appending. */ fp = fopen( nwipe_options.logfile, "a" ); if( fp == NULL ) { fprintf( stderr, "nwipe_log: Unable to open '%s' for logging.\n", nwipe_options.logfile ); return; } /* Get the file descriptor of the log file. */ fd = fileno( fp ); /* Block and lock. */ r = flock( fd, LOCK_EX ); if( r != 0 ) { perror( "nwipe_log: flock:" ); fprintf( stderr, "nwipe_log: Unable to lock '%s' for logging.\n", nwipe_options.logfile ); return; } fprintf( fp, "%s\n", log_lines[log_current_element] ); /* Unlock the file. */ r = flock( fd, LOCK_UN ); if( r != 0 ) { perror( "nwipe_log: flock:" ); fprintf( stderr, "Error: Unable to unlock '%s' after logging.\n", nwipe_options.logfile ); } /* Close the stream. */ r = fclose( fp ); if( r != 0 ) { perror( "nwipe_log: fclose:" ); fprintf( stderr, "Error: Unable to close '%s' after logging.\n", nwipe_options.logfile ); } } pthread_mutex_unlock( &mutex1 ); } /* nwipe_log */ void nwipe_perror( int nwipe_errno, const char* f, const char* s ) { /** * Wrapper for perror(). * * We may wish to tweak or squelch this later. * */ nwipe_log( NWIPE_LOG_ERROR, "%s: %s: %s", f, s, strerror( nwipe_errno ) ); } /* nwipe_perror */ /* eof */ nwipe-0.24/src/logging.h000066400000000000000000000032531321204421400151430ustar00rootroot00000000000000/* * logging.c: Logging facilities for nwipe. * * Copyright Darik Horn . * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef LOGGING_H_ #define LOGGING_H_ typedef enum nwipe_log_t_ { NWIPE_LOG_NONE = 0, NWIPE_LOG_DEBUG, /* TODO: Very verbose logging. */ NWIPE_LOG_INFO, /* TODO: Verbose logging. */ NWIPE_LOG_NOTICE, /* Most logging happens at this level. */ NWIPE_LOG_WARNING, /* Things that the user should know about. */ NWIPE_LOG_ERROR, /* Non-fatal errors that result in failure. */ NWIPE_LOG_FATAL, /* Errors that cause the program to exit. */ NWIPE_LOG_SANITY /* Programming errors. */ } nwipe_log_t; void nwipe_log( nwipe_log_t level, const char* format, ... ); void nwipe_perror( int nwipe_errno, const char* f, const char* s ); /* Global array to hold log values to print when logging to STDOUT */ //extern char **log_lines; //extern int log_current_element; //extern int log_elements_allocated; #endif /* LOGGING_H_ */ /* eof */ nwipe-0.24/src/method.c000066400000000000000000000574211321204421400147760ustar00rootroot00000000000000/* * method.c: Method implementations for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* HOWTO: Add another wipe method. * * 1. Create a new function here and add the prototype to the 'nwipe.h' file. * 2. Update nwipe_method_label() appropriately. * 3. Put the passes that you wish to run into a nwipe_patterns_t array. * 4. Call nwipe_runmethod() with your array of patterns. * 5. Cut-and-paste within the 'options.c' file so that the new method can be invoked. * 6. Optionally try to plug your function into 'gui.c'. * * * WARNING: Remember to pad all pattern arrays with { 0, NULL }. * * WARNING: Never change nwipe_options after calling a method. * * NOTE: The nwipe_runmethod function appends a final pass to all methods. * */ /* Why is this needed? Segfaults without it */ #include #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "pass.h" #include "logging.h" /* * Comment Legend * * "method" An ordered set of patterns. * "pattern" The magic bits that will be written to a device. * "pass" Reading or writing one pattern to an entire device. * "rounds" The number of times that a method will be applied to a device. * */ const char* nwipe_dod522022m_label = "DoD 5220.22-M"; const char* nwipe_dodshort_label = "DoD Short"; const char* nwipe_gutmann_label = "Gutmann Wipe"; const char* nwipe_ops2_label = "RCMP TSSIT OPS-II"; const char* nwipe_random_label = "PRNG Stream"; const char* nwipe_zero_label = "Quick Erase"; const char* nwipe_unknown_label = "Unknown Method (FIXME)"; const char* nwipe_method_label( void* method ) { /** * Returns a pointer to the name of the method function. * */ if( method == &nwipe_dod522022m ) { return nwipe_dod522022m_label; } if( method == &nwipe_dodshort ) { return nwipe_dodshort_label; } if( method == &nwipe_gutmann ) { return nwipe_gutmann_label; } if( method == &nwipe_ops2 ) { return nwipe_ops2_label; } if( method == &nwipe_random ) { return nwipe_random_label; } if( method == &nwipe_zero ) { return nwipe_zero_label; } /* else */ return nwipe_unknown_label; } /* nwipe_method_label */ void *nwipe_zero( void *ptr ) { /** * Fill the device with zeroes. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* Do nothing because nwipe_runmethod appends a zero-fill. */ nwipe_pattern_t patterns [] = { { 0, NULL } }; /* Run the method. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_zero */ void *nwipe_dod522022m( void *ptr ) { /** * United States Department of Defense 5220.22-M standard wipe. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* A result holder. */ int r; /* Random characters. (Elements 2 and 6 are unused.) */ char dod [7]; nwipe_pattern_t patterns [] = { { 1, &dod[0] }, /* Pass 1: A random character. */ { 1, &dod[1] }, /* Pass 2: The bitwise complement of pass 1. */ { -1, "" }, /* Pass 3: A random stream. */ { 1, &dod[3] }, /* Pass 4: A random character. */ { 1, &dod[4] }, /* Pass 5: A random character. */ { 1, &dod[5] }, /* Pass 6: The bitwise complement of pass 5. */ { -1, "" }, /* Pass 7: A random stream. */ { 0, NULL } }; /* Load the array with random characters. */ r = read( c->entropy_fd, &dod, sizeof( dod ) ); /* NOTE: Only the random data in dod[0], dod[3], and dod[4] is actually used. */ /* Check the result. */ if( r != sizeof( dod ) ) { r = errno; nwipe_perror( r, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the %s method.", nwipe_dod522022m_label ); /* Ensure a negative return. */ if( r < 0 ) { c->result = r; return NULL; } else { c->result = -1; return NULL; } } /* Pass 2 is the bitwise complement of Pass 1. */ dod[1] = ~ dod[0]; /* Pass 4 is the bitwise complement of Pass 3. */ dod[5] = ~ dod[4]; /* Run the DoD 5220.22-M method. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_dod522022m */ void *nwipe_dodshort( void *ptr ) { /** * United States Department of Defense 5220.22-M short wipe. * This method is comprised of passes 1,2,7 from the standard wipe. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* A result holder. */ int r; /* Random characters. (Element 3 is unused.) */ char dod [3]; nwipe_pattern_t patterns [] = { { 1, &dod[0] }, /* Pass 1: A random character. */ { 1, &dod[1] }, /* Pass 2: The bitwise complement of pass 1. */ { -1, "" }, /* Pass 3: A random stream. */ { 0, NULL } }; /* Load the array with random characters. */ r = read( c->entropy_fd, &dod, sizeof( dod ) ); /* NOTE: Only the random data in dod[0] is actually used. */ /* Check the result. */ if( r != sizeof( dod ) ) { r = errno; nwipe_perror( r, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the %s method.", nwipe_dodshort_label ); /* Ensure a negative return. */ if( r < 0 ) { c->result = r; return NULL; } else { c->result = -1; return NULL; } } /* Pass 2 is the bitwise complement of Pass 1. */ dod[1] = ~ dod[0]; /* Run the DoD 5220.022-M short method. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_dodshort */ void *nwipe_gutmann( void *ptr ) { /** * Peter Gutmann's wipe. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* A result buffer. */ int r; /* The number of patterns in the Guttman Wipe, also used to index the 'patterns' array. */ int i = 35; /* An index into the 'book' array. */ int j; /* The N-th element that has not been used. */ int n; /* Define the Gutmann method. */ nwipe_pattern_t book [] = { { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { 3, "\x55\x55\x55" }, /* Static pass: 0x555555 01010101 01010101 01010101 */ { 3, "\xAA\xAA\xAA" }, /* Static pass: 0XAAAAAA 10101010 10101010 10101010 */ { 3, "\x92\x49\x24" }, /* Static pass: 0x924924 10010010 01001001 00100100 */ { 3, "\x49\x24\x92" }, /* Static pass: 0x492492 01001001 00100100 10010010 */ { 3, "\x24\x92\x49" }, /* Static pass: 0x249249 00100100 10010010 01001001 */ { 3, "\x00\x00\x00" }, /* Static pass: 0x000000 00000000 00000000 00000000 */ { 3, "\x11\x11\x11" }, /* Static pass: 0x111111 00010001 00010001 00010001 */ { 3, "\x22\x22\x22" }, /* Static pass: 0x222222 00100010 00100010 00100010 */ { 3, "\x33\x33\x33" }, /* Static pass: 0x333333 00110011 00110011 00110011 */ { 3, "\x44\x44\x44" }, /* Static pass: 0x444444 01000100 01000100 01000100 */ { 3, "\x55\x55\x55" }, /* Static pass: 0x555555 01010101 01010101 01010101 */ { 3, "\x66\x66\x66" }, /* Static pass: 0x666666 01100110 01100110 01100110 */ { 3, "\x77\x77\x77" }, /* Static pass: 0x777777 01110111 01110111 01110111 */ { 3, "\x88\x88\x88" }, /* Static pass: 0x888888 10001000 10001000 10001000 */ { 3, "\x99\x99\x99" }, /* Static pass: 0x999999 10011001 10011001 10011001 */ { 3, "\xAA\xAA\xAA" }, /* Static pass: 0xAAAAAA 10101010 10101010 10101010 */ { 3, "\xBB\xBB\xBB" }, /* Static pass: 0xBBBBBB 10111011 10111011 10111011 */ { 3, "\xCC\xCC\xCC" }, /* Static pass: 0xCCCCCC 11001100 11001100 11001100 */ { 3, "\xDD\xDD\xDD" }, /* Static pass: 0xDDDDDD 11011101 11011101 11011101 */ { 3, "\xEE\xEE\xEE" }, /* Static pass: 0xEEEEEE 11101110 11101110 11101110 */ { 3, "\xFF\xFF\xFF" }, /* Static pass: 0xFFFFFF 11111111 11111111 11111111 */ { 3, "\x92\x49\x24" }, /* Static pass: 0x924924 10010010 01001001 00100100 */ { 3, "\x49\x24\x92" }, /* Static pass: 0x492492 01001001 00100100 10010010 */ { 3, "\x24\x92\x49" }, /* Static pass: 0x249249 00100100 10010010 01001001 */ { 3, "\x6D\xB6\xDB" }, /* Static pass: 0x6DB6DB 01101101 10110110 11011011 */ { 3, "\xB6\xDB\x6D" }, /* Static pass: 0xB6DB6D 10110110 11011011 01101101 */ { 3, "\xDB\x6D\xB6" }, /* Static pass: 0XDB6DB6 11011011 01101101 10110110 */ { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { -1, "" }, /* Random pass. */ { 0, NULL } }; /* Put the book array into this array in random order. */ nwipe_pattern_t patterns [36]; /* An entropy buffer. */ u16 s [i]; /* Load the array with random characters. */ r = read( c->entropy_fd, &s, sizeof( s ) ); if( r != sizeof( s ) ) { r = errno; nwipe_perror( r, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the %s method.", nwipe_gutmann_label ); /* Ensure a negative return. */ if( r < 0 ) { c->result = r; return NULL; } else { c->result = -1; return NULL; } } while( --i >= 0 ) { /* Get a random integer that is less than the first index 'i'. */ n = (int)( (double)( s[i] ) / (double)( 0x0000FFFF + 1 ) * (double)( i + 1 ) ); /* Initialize the secondary index. */ j = -1; while( n-- >= 0 ) { /* Advance 'j' by 'n' positions... */ j += 1; /* ... but don't count 'book' elements that have already been copied. */ while( book[j].length == 0 ) { j += 1; } } /* Copy the element. */ patterns[i] = book[j]; /* Mark this element as having been used. */ book[j].length = 0; nwipe_log( NWIPE_LOG_DEBUG, "nwipe_gutmann: Set patterns[%i] = book[%i].", i, j ); } /* Ensure that the array is terminated. */ patterns[35].length = 0; patterns[35].s = NULL; /* Run the Gutmann method. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_gutmann */ void *nwipe_ops2( void *ptr ) { /** * Royal Canadian Mounted Police * Technical Security Standard for Information Technology * Appendix OPS-II: Media Sanitization * * NOTE: The last pass of this method is specially handled by nwipe_runmethod. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* A generic array index. */ int i; /* A generic result buffer. */ int r; /* A buffer for random characters. */ char* s; /* A buffer for the bitwise complements of 's'. */ char* t; /* The element count of 's' and 't'. */ u32 u; /* The pattern array for this method is dynamically allocated. */ nwipe_pattern_t* patterns; /* The element count of 'patterns'. */ u32 q; /* We need one random character per round. */ u = 1 * nwipe_options.rounds; /* Allocate the array of random characters. */ s = malloc( sizeof( char ) * u ); if( s == NULL ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate the random character array." ); c->result = -1; return NULL; } /* Allocate the array of complement characters. */ t = malloc( sizeof( char ) * u ); if( s == NULL ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate the complement character array." ); c->result = -1; return NULL; } /* We need eight pattern elements per round, plus one for padding. */ q = 8 * u + 1; /* Allocate the pattern array. */ patterns = malloc( sizeof( nwipe_pattern_t ) * q ); if( patterns == NULL ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate the pattern array." ); c->result = -1; return NULL; } /* Load the array of random characters. */ r = read( c->entropy_fd, s, u ); if( r != u ) { r = errno; nwipe_perror( r, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the %s method.", nwipe_ops2_label ); /* Ensure a negative return. */ if( r < 0 ) { c->result = r; return NULL; } else { c->result = -1; return NULL; } } for( i = 0 ; i < u ; i += 1 ) { /* Populate the array of complements. */ t[i] = ~s[i]; } for( i = 0 ; i < u ; i += 8 ) { /* Populate the array of patterns. */ /* Even elements point to the random characters. */ patterns[i*4 +0].length = 1; patterns[i*4 +0].s = &s[i]; patterns[i*4 +2].length = 1; patterns[i*4 +2].s = &s[i]; patterns[i*4 +4].length = 1; patterns[i*4 +4].s = &s[i]; patterns[i*4 +6].length = 1; patterns[i*4 +6].s = &s[i]; /* Odd elements point to the complement characters. */ patterns[i*4 +1].length = 1; patterns[i*4 +1].s = &t[i]; patterns[i*4 +3].length = 1; patterns[i*4 +3].s = &t[i]; patterns[i*4 +5].length = 1; patterns[i*4 +5].s = &t[i]; patterns[i*4 +7].length = 1; patterns[i*4 +7].s = &t[i]; } /* Ensure that the array is terminated. */ patterns[q-1].length = 0; patterns[q-1].s = NULL; /* Run the TSSIT OPS-II method. */ r = nwipe_runmethod( c, patterns ); /* Release the random character buffer. */ free( s ); /* Release the complement character buffer */ free( t ); /* Release the pattern buffer. */ free( patterns ); /* We're done. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_ops2 */ void *nwipe_random( void *ptr ) { /** * Fill the device with a stream from the PRNG. * */ nwipe_context_t *c; c = (nwipe_context_t *) ptr; /* Define the random method. */ nwipe_pattern_t patterns [] = { { -1, "" }, { 0, NULL } }; /* Run the method. */ c->result = nwipe_runmethod( c, patterns ); /* Finished. Set the thread ID to 0 so that the GUI knows */ c->thread = 0; return NULL; } /* nwipe_random */ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns ) { /** * Writes patterns to the device. * */ /* The result holder. */ int r; /* An index variable. */ int i = 0; /* The zero-fill pattern for the final pass of most methods. */ nwipe_pattern_t pattern_zero = { 1, "\x00" }; /* Create the PRNG state buffer. */ c->prng_seed.length = NWIPE_KNOB_PRNG_STATE_LENGTH; c->prng_seed.s = malloc( c->prng_seed.length ); /* Check the memory allocation. */ if( ! c->prng_seed.s ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the prng seed buffer." ); return -1; } /* Count the number of patterns in the array. */ while( patterns[i].length ) { i += 1; } /* Tell the parent the number of device passes that will be run in one round. */ c->pass_count = i; /* Set the number of bytes that will be written across all passes in one round. */ c->pass_size = c->pass_count * c->device_size; if( nwipe_options.verify == NWIPE_VERIFY_ALL ) { /* We must read back all passes, so double the byte count. */ c->pass_size *= 2; } /* Tell the parent the number of rounds that will be run. */ c->round_count = nwipe_options.rounds; /* Set the number of bytes that will be written across all rounds. */ c->round_size = c->round_count * c->pass_size; /* The final pass is always a zero fill, except ops2 which is random. */ /* Do not add if there is no blanking pass. */ if ( nwipe_options.noblank == 0 ) { c->round_size += c->device_size; } /* Set the round total count down */ c->result = c->round_size; if((nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL) && nwipe_options.noblank == 0 ) { /* We must read back the last pass to verify it. */ c->round_size += c->device_size; } /* Initialize the working round counter. */ c->round_working = 0; nwipe_log( NWIPE_LOG_NOTICE, "Invoking method '%s' on device '%s'.", \ nwipe_method_label( nwipe_options.method ), c->device_name ); while( c->round_working < c->round_count ) { /* Increment the round counter. */ c->round_working += 1; nwipe_log( NWIPE_LOG_NOTICE, "Starting round %i of %i on device '%s'.", \ c->round_working, c->round_count, c->device_name ); /* Initialize the working pass counter. */ c->pass_working = 0; for( i = 0 ; i < c->pass_count ; i++ ) { /* Increment the working pass. */ c->pass_working += 1; nwipe_log( NWIPE_LOG_NOTICE, "Starting pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name ); if( patterns[i].length == 0 ) { /* Caught insanity. */ nwipe_log( NWIPE_LOG_SANITY, "nwipe_runmethod: A non-terminating pattern element has zero length." ); return -1; } if( patterns[i].length > 0 ) { /* Write a static pass. */ c->pass_type = NWIPE_PASS_WRITE; r = nwipe_static_pass( c, &patterns[i] ); c->pass_type = NWIPE_PASS_NONE; /* Log number of bytes written to disk */ nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to device '%s'.", \ c->pass_done, c->device_name ); /* Check for a fatal error. */ if( r < 0 ) { return r; } if( nwipe_options.verify == NWIPE_VERIFY_ALL ) { nwipe_log( NWIPE_LOG_NOTICE, "Verifying pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name ); /* Verify this pass. */ c->pass_type = NWIPE_PASS_VERIFY; r = nwipe_static_verify( c, &patterns[i] ); c->pass_type = NWIPE_PASS_NONE; /* Check for a fatal error. */ if( r < 0 ) { return r; } nwipe_log( NWIPE_LOG_NOTICE, "Verified pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name ); } } /* static pass */ else { c->pass_type = NWIPE_PASS_WRITE; /* Seed the PRNG. */ r = read( c->entropy_fd, 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_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." ); return -1; } /* Check for a partial read. */ if( r != c->prng_seed.length ) { /* TODO: Handle partial reads. */ nwipe_log( NWIPE_LOG_FATAL, "Insufficient entropy is available." ); return -1; } /* Write the random pass. */ r = nwipe_random_pass( c ); c->pass_type = NWIPE_PASS_NONE; /* Log number of bytes written to disk */ nwipe_log( NWIPE_LOG_NOTICE, "%llu bytes written to device '%s'.", \ c->pass_done, c->device_name ); /* Check for a fatal error. */ if( r < 0 ) { return r; } if( nwipe_options.verify == NWIPE_VERIFY_ALL ) { nwipe_log( NWIPE_LOG_NOTICE, "Verifying pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name ); /* Verify this pass. */ c->pass_type = NWIPE_PASS_VERIFY; r = nwipe_random_verify( c ); c->pass_type = NWIPE_PASS_NONE; /* Check for a fatal error. */ if( r < 0 ) { return r; } nwipe_log( NWIPE_LOG_NOTICE, "Verified pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, nwipe_method_label( nwipe_options.method ) ); } } /* random pass */ nwipe_log( NWIPE_LOG_NOTICE, "Finished pass %i of %i, round %i of %i, on device '%s'.", \ c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name ); } /* for passes */ nwipe_log( NWIPE_LOG_NOTICE, "Finished round %i of %i on device '%s'.", \ c->round_working, c->round_count, c->device_name ); } /* while rounds */ if( nwipe_options.method == &nwipe_ops2 ) { /* NOTE: The OPS-II method specifically requires that a random pattern be left on the device. */ /* Tell the parent that we are running the final pass. */ c->pass_type = NWIPE_PASS_FINAL_OPS2; /* Seed the PRNG. */ r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length ); /* Check the result. */ if( r < 0 ) { nwipe_perror( errno, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." ); return -1; } /* Check for a partial read. */ if( r != c->prng_seed.length ) { /* TODO: Handle partial reads. */ nwipe_log( NWIPE_LOG_FATAL, "Insufficient entropy is available." ); return -1; } nwipe_log( NWIPE_LOG_NOTICE, "Writing final random pattern to '%s'.", c->device_name ); /* The final ops2 pass. */ r = nwipe_random_pass( c ); /* Check for a fatal error. */ if( r < 0 ) { return r; } if( nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL ) { nwipe_log( NWIPE_LOG_NOTICE, "Verifying the final random pattern on '%s' is empty.", c->device_name ); /* Verify the final zero pass. */ r = nwipe_random_verify( c ); /* Check for a fatal error. */ if( r < 0 ) { return r; } nwipe_log( NWIPE_LOG_NOTICE, "Verified the final random pattern on '%s' is empty.", c->device_name ); } nwipe_log( NWIPE_LOG_NOTICE, "Wrote final random pattern to '%s'.", c->device_name ); } /* final ops2 */ else if (nwipe_options.noblank == 0) { /* Tell the user that we are on the final pass. */ c->pass_type = NWIPE_PASS_FINAL_BLANK; nwipe_log( NWIPE_LOG_NOTICE, "Blanking device '%s'.", c->device_name ); /* The final zero pass. */ r = nwipe_static_pass( c, &pattern_zero ); /* Check for a fatal error. */ if( r < 0 ) { return r; } if( nwipe_options.verify == NWIPE_VERIFY_LAST || nwipe_options.verify == NWIPE_VERIFY_ALL ) { nwipe_log( NWIPE_LOG_NOTICE, "Verifying that '%s' is empty.", c->device_name ); /* Verify the final zero pass. */ r = nwipe_static_verify( c, &pattern_zero ); /* Check for a fatal error. */ if( r < 0 ) { return r; } nwipe_log( NWIPE_LOG_NOTICE, "Verified that '%s' is empty.", c->device_name ); } nwipe_log( NWIPE_LOG_NOTICE, "Blanked device '%s'.", c->device_name ); } /* final blank */ /* Release the state buffer. */ c->prng_seed.length = 0; free( c->prng_seed.s ); /* Tell the parent that we have fininshed the final pass. */ c->pass_type = NWIPE_PASS_NONE; if( c->verify_errors > 0 ) { /* We finished, but with non-fatal verification errors. */ nwipe_log( NWIPE_LOG_ERROR, "%llu verification errors on device '%s'.", c->verify_errors, c->device_name ); } if( c->pass_errors > 0 ) { /* We finished, but with non-fatal wipe errors. */ nwipe_log( NWIPE_LOG_ERROR, "%llu wipe errors on device '%s'.", c->pass_errors, c->device_name ); } /* FIXME: The 'round_errors' context member is not being used. */ if( c->pass_errors > 0 || c->round_errors > 0 || c->verify_errors > 0 ) { /* We finished, but with non-fatal errors. */ return 1; } /* We finished successfully. */ return 0; } /* nwipe_runmethod */ /* eof */ nwipe-0.24/src/method.h000066400000000000000000000036161321204421400150000ustar00rootroot00000000000000/* * methods.c: Method implementations for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef METHOD_H_ #define METHOD_H_ /* The argument list for nwipe methods. */ #define NWIPE_METHOD_SIGNATURE nwipe_context_t* c typedef enum nwipe_verify_t_ { NWIPE_VERIFY_NONE = 0, /* Do not read anything back from the device. */ NWIPE_VERIFY_LAST, /* Check the last pass. */ NWIPE_VERIFY_ALL, /* Check all passes. */ } nwipe_verify_t; /* The typedef of the function that will do the wipe. */ typedef int(*nwipe_method_t)( void *ptr ); typedef struct /* nwipe_pattern_t */ { int length; /* Length of the pattern in bytes, -1 means random. */ char* s; /* The actual bytes of the pattern. */ } nwipe_pattern_t; const char* nwipe_method_label( void* method ); int nwipe_runmethod( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* patterns ); void *nwipe_dod522022m( void *ptr ); void *nwipe_dodshort( void *ptr ); void *nwipe_gutmann( void *ptr ); void *nwipe_ops2( void *ptr ); void *nwipe_random( void *ptr ); void *nwipe_zero( void *ptr ); #endif /* METHOD_H_ */ /* eof */ nwipe-0.24/src/mt19937ar-cok.c000066400000000000000000000103021321204421400156330ustar00rootroot00000000000000/* This code is modified for use in nwipe. A C-program for MT19937, with initialization improved 2002/2/10. Coded by Takuji Nishimura and Makoto Matsumoto. This is a faster version by taking Shawn Cokus's optimization, Matthe Bellew's simplification, Isaku Wada's real version. Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.keio.ac.jp/matumoto/emt.html email: matumoto@math.keio.ac.jp */ #include #include "mt19937ar-cok.h" /* initializes state[N] with a seed */ void init_genrand( twister_state_t* state, unsigned long s) { int j; state->array[0]= s & 0xffffffffUL; for( j = 1; j < N; j++ ) { state->array[j] = (1812433253UL * (state->array[j-1] ^ (state->array[j-1] >> 30)) + j); state->array[j] &= 0xffffffffUL; /* for >32 bit machines */ } state->left = 1; state->initf = 1; } void twister_init( twister_state_t* state, unsigned long init_key[], unsigned long key_length ) { int i = 1; int j = 0; int k = ( N > key_length ? N : key_length ); init_genrand( state, 19650218UL ); for( ; k; k-- ) { state->array[i] = (state->array[i] ^ ((state->array[i-1] ^ (state->array[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; state->array[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ ++i; ++j; if ( i >= N ) { state->array[0] = state->array[N-1]; i = 1; } if ( j >= key_length ) { j = 0; } } for( k = N -1; k; k-- ) { state->array[i] = (state->array[i] ^ ((state->array[i-1] ^ (state->array[i-1] >> 30)) * 1566083941UL)) - i; state->array[i] &= 0xffffffffUL; ++i; if ( i >= N ) { state->array[0] = state->array[N-1]; i = 1; } } state->array[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ state->left = 1; state->initf = 1; } static void next_state( twister_state_t* state ) { unsigned long *p = state->array; int j; if( state->initf == 0) { init_genrand( state, 5489UL ); } state->left = N; state->next = state->array; for( j = N - M + 1; --j; p++ ) { *p = p[M] ^ TWIST(p[0], p[1]); } for( j = M; --j; p++ ) { *p = p[M-N] ^ TWIST(p[0], p[1]); } *p = p[M-N] ^ TWIST(p[0], state->array[0]); } /* generates a random number on [0,0xffffffff]-interval */ unsigned long twister_genrand_int32( twister_state_t* state ) { unsigned long y; if ( --state->left == 0 ) { next_state( state ); } y = *state->next++; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } nwipe-0.24/src/mt19937ar-cok.h000066400000000000000000000016201321204421400156430ustar00rootroot00000000000000/* * mt19937ar-cok.h: The Mersenne Twister PRNG implementation for nwipe. * */ #ifndef MT19937AR_H_ #define MT19937AR_H_ /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UMASK 0x80000000UL /* most significant w-r bits */ #define LMASK 0x7fffffffUL /* least significant r bits */ #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) typedef struct twister_state_t_ { unsigned long array[N]; int left; int initf; unsigned long *next; } twister_state_t; /* Initialize the MT state. ( 0 < key_length <= 624 ). */ void twister_init( twister_state_t* state, unsigned long init_key[], unsigned long key_length); /* Generate a random integer on the [0,0xffffffff] interval. */ unsigned long twister_genrand_int32( twister_state_t* state ); #endif /* MT19937AR_H_ */ nwipe-0.24/src/nwipe.c000066400000000000000000000566451321204421400146470ustar00rootroot00000000000000/* vi: tabstop=3 * * nwipe.c: Darik's Wipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include #include #include #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "device.h" #include "logging.h" #include "gui.h" #include /* FIXME: Twice Included */ #include #include #include #include int main( int argc, char** argv ) { int nwipe_optind; /* The result of nwipe_options(). */ int nwipe_enumerated; /* The number of contexts that have been enumerated. */ int nwipe_error = 0; /* An error counter. */ int nwipe_selected = 0; /* The number of contexts that have been selected. */ pthread_t nwipe_gui_thread; /* The thread ID of the GUI thread. */ pthread_t nwipe_sigint_thread; /* The thread ID of the sigint handler. */ /* The entropy source file handle. */ int nwipe_entropy; /* The generic index variables. */ int i; int j; /* The generic result buffer. */ int r; /* Two arrays are used, containing pointers to the the typedef for each disk */ /* The first array (c1) points to all devices, the second points to only */ /* the disks selected for wiping. */ /* The array of pointers to enumerated contexts. */ /* Initialised and populated in device scan. */ nwipe_context_t **c1 = 0; /* Parse command line options. */ nwipe_optind = nwipe_options_parse( argc, argv ); if( nwipe_optind == argc ) { /* File names were not given by the user. Scan for devices. */ nwipe_enumerated = nwipe_device_scan( &c1 ); if( nwipe_enumerated == 0 ) { nwipe_log( NWIPE_LOG_ERROR, "Storage devices not found." ); return -1; } else { nwipe_log( NWIPE_LOG_INFO, "Automatically enumerated %i devices.", nwipe_enumerated ); } } else { argv += nwipe_optind; argc -= nwipe_optind; nwipe_enumerated = nwipe_device_get( &c1, argv, argc ); if ( nwipe_enumerated == 0 ) { exit(1); } } /* The array of pointers to contexts that will actually be wiped. */ nwipe_context_t **c2 = (nwipe_context_t **)malloc(nwipe_enumerated * sizeof(nwipe_context_t *)); /* 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 ); 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; sigemptyset(&sigset); sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGQUIT); sigaddset(&sigset, SIGINT); sigaddset(&sigset, SIGUSR1); pthread_sigmask(SIG_SETMASK, &sigset, NULL); /* Create a signal handler thread. This thread will catch all */ /* signals and decide what to do with them. This will only */ /* catch nondirected signals. (I.e., if a thread causes a SIGFPE */ /* then that thread will get that signal. */ /* Pass a pointer to a struct containing all data to the signal handler. */ nwipe_misc_thread_data_t nwipe_misc_thread_data; nwipe_thread_data_ptr_t nwipe_thread_data_ptr; nwipe_thread_data_ptr.c = c2; nwipe_misc_thread_data.nwipe_enumerated = nwipe_enumerated; if( !nwipe_options.nogui ) nwipe_misc_thread_data.gui_thread = &nwipe_gui_thread; nwipe_thread_data_ptr.nwipe_misc_thread_data = &nwipe_misc_thread_data; if( !nwipe_options.nosignals ) { pthread_attr_t pthread_attr; pthread_attr_init(&pthread_attr); pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED); pthread_create( &nwipe_sigint_thread, &pthread_attr, signal_hand, &nwipe_thread_data_ptr); } /* A context struct for each device has already been created. */ /* Now set specific nwipe options */ 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. */ //TODO - partitions //if( c1[i].device_part == 0 ) { c1[i].select = NWIPE_SELECT_TRUE; } //else { c1[i].select = NWIPE_SELECT_TRUE_PARENT; } c1[i]->select = NWIPE_SELECT_TRUE; } else { /* The user must manually select devices. */ c1[i]->select = NWIPE_SELECT_FALSE; } /* Set the PRNG implementation. */ c1[i]->prng = nwipe_options.prng; c1[i]->prng_seed.length = 0; c1[i]->prng_seed.s = 0; c1[i]->prng_state = 0; } /* file arguments */ /* Check for initialization errors. */ if( nwipe_error ) { return -1; } /* Start the ncurses interface. */ if( !nwipe_options.nogui ) nwipe_gui_init(); if( nwipe_options.autonuke == 1 ) { /* Print the options window. */ if( !nwipe_options.nogui ) nwipe_gui_options(); } else { /* Get device selections from the user. */ if( nwipe_options.nogui ) { printf("--nogui option must be used with autonuke option\n"); exit(1); } else { nwipe_gui_select( nwipe_enumerated, c1 ); } } /* Count the number of selected contexts. */ for( i = 0 ; i < nwipe_enumerated ; i++ ) { if( c1[i]->select == NWIPE_SELECT_TRUE ) { nwipe_selected += 1; } } /* Pass the number selected to the struct for other threads */ nwipe_misc_thread_data.nwipe_selected = nwipe_selected; /* Populate the array of selected contexts. */ for( i = 0, j = 0 ; i < nwipe_enumerated ; i++ ) { if( c1[i]->select == NWIPE_SELECT_TRUE ) { /* Copy the context. */ c2[j++] = c1[i]; } } /* for */ /* TODO: free c1 and c2 memory. */ for( i = 0 ; i < nwipe_selected ; i++ ) { /* A result buffer for the BLKGETSIZE64 ioctl. */ u64 size64; /* Open the file for reads and writes. */ c2[i]->device_fd = open( c2[i]->device_name, O_RDWR ); /* Check the open() result. */ if( c2[i]->device_fd < 0 ) { nwipe_perror( errno, __FUNCTION__, "open" ); nwipe_log( NWIPE_LOG_WARNING, "Unable to open device '%s'.", c2[i]->device_name ); c2[i]->select = NWIPE_SELECT_DISABLED; continue; } /* Stat the file. */ if( fstat( c2[i]->device_fd, &c2[i]->device_stat ) != 0 ) { nwipe_perror( errno, __FUNCTION__, "fstat"); nwipe_log( NWIPE_LOG_ERROR, "Unable to stat file '%s'.", c2[i]->device_name ); nwipe_error++; continue; } /* Check that the file is a block device. */ if( ! S_ISBLK( c2[i]->device_stat.st_mode ) ) { nwipe_log( NWIPE_LOG_ERROR, "'%s' is not a block device.", c2[i]->device_name ); nwipe_error++; continue; } /* TODO: Lock the file for exclusive access. */ /* if( flock( c2[i]->device_fd, LOCK_EX | LOCK_NB ) != 0 ) { nwipe_perror( errno, __FUNCTION__, "flock" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to lock the '%s' file.", c2[i]->device_name ); nwipe_error++; continue; } */ /* Print serial number of device if it exists. */ if ( strlen(c2[i]->identity.serial_no) ) { nwipe_log( NWIPE_LOG_INFO, "Device %s has serial number %s", c2[i]->device_name, c2[i]->identity.serial_no); } /* Do sector size and block size checking. */ if( ioctl( c2[i]->device_fd, BLKSSZGET, &c2[i]->sector_size ) == 0 ) { nwipe_log( NWIPE_LOG_INFO, "Device '%s' has sector size %i.", c2[i]->device_name, c2[i]->sector_size ); if( ioctl( c2[i]->device_fd, BLKBSZGET, &c2[i]->block_size ) == 0 ) { if( c2[i]->block_size != c2[i]->sector_size ) { nwipe_log( NWIPE_LOG_WARNING, "Changing '%s' block size from %i to %i.", c2[i]->device_name, c2[i]->block_size, c2[i]->sector_size ); if( ioctl( c2[i]->device_fd, BLKBSZSET, &c2[i]->sector_size ) == 0 ) { c2[i]->block_size = c2[i]->sector_size; } else { nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKBSZSET ioctl.", c2[i]->device_name ); } } } else { nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKBSZGET ioctl.", c2[i]->device_name ); c2[i]->block_size = 0; } } else { nwipe_log( NWIPE_LOG_WARNING, "Device '%s' failed BLKSSZGET ioctl.", c2[i]->device_name ); c2[i]->sector_size = 0; c2[i]->block_size = 0; } /* The st_size field is zero for block devices. */ /* ioctl( c2[i]->device_fd, BLKGETSIZE64, &c2[i]->device_size ); */ /* Seek to the end of the device to determine its size. */ c2[i]->device_size = lseek( c2[i]->device_fd, 0, SEEK_END ); /* Also ask the driver for the device size. */ /* if( ioctl( c2[i]->device_fd, BLKGETSIZE64, &size64 ) ) */ if( ioctl( c2[i]->device_fd, _IOR(0x12,114,size_t), &size64 ) ) { /* The ioctl failed. */ fprintf( stderr, "Error: BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name ); nwipe_log( NWIPE_LOG_ERROR, "BLKGETSIZE64 failed on '%s'.\n", c2[i]->device_name ); nwipe_error++; } c2[i]->device_size = size64; /* Check whether the two size values agree. */ if( c2[i]->device_size != size64 ) { /* This could be caused by the linux last-odd-block problem. */ fprintf( stderr, "Error: Last-odd-block detected on '%s'.\n", c2[i]->device_name ); nwipe_log( NWIPE_LOG_ERROR, "Last-odd-block detected on '%s'.", c2[i]->device_name ); nwipe_error++; } if( c2[i]->device_size == (long long)-1 ) { /* We cannot determine the size of this device. */ nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to determine the size of '%s'.", c2[i]->device_name ); nwipe_error++; } else { /* Reset the file pointer. */ r = lseek( c2[i]->device_fd, 0, SEEK_SET ); if( r == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to reset the '%s' file offset.", c2[i]->device_name ); nwipe_error++; } } if( c2[i]->device_size == 0 ) { nwipe_log( NWIPE_LOG_ERROR, "Device '%s' is size %llu.", c2[i]->device_name, c2[i]->device_size ); nwipe_error++; continue; } else { nwipe_log( NWIPE_LOG_INFO, "Device '%s' is size %llu.", c2[i]->device_name, c2[i]->device_size ); } /* Fork a child process. */ errno = pthread_create( &c2[i]->thread, NULL, nwipe_options.method, (void*) c2[i]); if ( errno ) { nwipe_perror( errno, __FUNCTION__, "pthread_create" ); if( !nwipe_options.nogui ) nwipe_gui_free(); return errno; } } /* new thread */ /* Change the terminal mode to non-blocking input. */ nodelay( stdscr, 0 ); /* Set getch to delay in order to slow screen updates. */ halfdelay( NWIPE_KNOB_SLEEP * 10 ); /* Set up data structs to pass the GUI thread the data it needs. */ nwipe_thread_data_ptr_t nwipe_gui_data; if( !nwipe_options.nogui ) { nwipe_gui_data.c = c2; nwipe_gui_data.nwipe_misc_thread_data = &nwipe_misc_thread_data; /* Fork the GUI thread. */ errno = pthread_create( &nwipe_gui_thread, NULL, nwipe_gui_status, &nwipe_gui_data); } /* Wait for all the wiping threads to finish. */ for( i = 0 ; i < nwipe_selected ; i++ ) { if ( c2[i]->thread ) { pthread_join( c2[i]->thread, NULL); /* Close the device file descriptor. */ close( c2[i]->device_fd ); } } /* Kill the GUI thread */ /* It may not be running if the program was interrupted */ if ( nwipe_gui_thread ) { pthread_join( nwipe_gui_thread, NULL ); nocbreak(); // timeout(-1); /* Wait for enter key to be pressed unless --nowait was specified. */ if( !nwipe_options.nowait ) getch(); /* Release the gui. */ nwipe_gui_free(); } nwipe_log( NWIPE_LOG_NOTICE, "Nwipe exited." ); for( i = 0 ; i < nwipe_selected ; i++ ) { /* Check for fatal errors. */ if( c2[i]->result < 0 ){ return -1; } } for( i = 0 ; i < nwipe_selected ; i++ ) { /* Check for non-fatal errors. */ if( c2[i]->result > 0 ){ return 1; } } /* Flush any remaining logs. */ for (i=0; i < log_current_element; i++) { printf("%s\n", log_lines[i]); } /* Success. */ return 0; } /* main */ void *signal_hand(void *ptr) { int sig; // Define signals that this handler should react to sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGQUIT); sigaddset(&sigset, SIGINT); sigaddset(&sigset, SIGUSR1); int i; /* Set up the structs we will use for the data required. */ nwipe_thread_data_ptr_t *nwipe_thread_data_ptr; nwipe_context_t **c; nwipe_misc_thread_data_t *nwipe_misc_thread_data; /* Retrieve from the pointer passed to the function. */ nwipe_thread_data_ptr = (nwipe_thread_data_ptr_t *) ptr; c = nwipe_thread_data_ptr->c; nwipe_misc_thread_data = nwipe_thread_data_ptr->nwipe_misc_thread_data; while (1) { /* wait for a signal to arrive */ sigwait(&sigset,&sig); switch ( sig ) { // Log current status. All values are automatically updated by the GUI case SIGUSR1 : { compute_stats(ptr); for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ ) { if ( c[i]->thread ) { char *status = ""; switch( c[i]->pass_type ) { case NWIPE_PASS_FINAL_BLANK: status = "[blanking]"; break; case NWIPE_PASS_FINAL_OPS2: status = "[OPS-II final]"; break; case NWIPE_PASS_WRITE: status = "[writing]"; break; case NWIPE_PASS_VERIFY: status = "[verifying]"; break; case NWIPE_PASS_NONE: break; } if( c[i]->sync_status ) { status = "[syncing]"; } nwipe_log( NWIPE_LOG_INFO, "%s: %05.2f%%, round %i of %i, pass %i of %i %s", \ c[i]->device_name, c[i]->round_percent, c[i]->round_working, c[i]->round_count, c[i]->pass_working, c[i]->pass_count, status ); } else { if( c[i]->result == 0 ) { nwipe_log( NWIPE_LOG_INFO, "%s: Success", c[i]->device_name ); } else if( c[i]->signal ) { nwipe_log( NWIPE_LOG_INFO, "%s: Failure: signal %i", c[i]->device_name, c[i]->signal ); } else { nwipe_log( NWIPE_LOG_INFO, "%s: Failure: code %i", c[i]->device_name, c[i]->result ); } } } break; } case SIGHUP : case SIGINT : case SIGQUIT : case SIGTERM : { for( i = 0; i < nwipe_misc_thread_data->nwipe_selected; i++ ) { if ( c[i]->thread ) { pthread_cancel( c[i]->thread ); } } // Kill the GUI thread if( !nwipe_options.nogui ) { if ( nwipe_misc_thread_data->gui_thread ) { pthread_cancel( *nwipe_misc_thread_data->gui_thread ); *nwipe_misc_thread_data->gui_thread = 0; } } if( !nwipe_options.nogui ) nwipe_gui_free(); /* Flush any remaining logs. */ for (i=0; i < log_current_element; i++) { printf("%s\n", log_lines[i]); } printf("Program interrupted (caught signal %d)\n", sig); // Cleanup // TODO: All other cleanup required exit(0); } /* end case */ } /* end switch */ } /* end of while */ return((void *)0); } /* end of signal_hand */ /* eof */ nwipe-0.24/src/nwipe.h000066400000000000000000000052031321204421400146340ustar00rootroot00000000000000/* * nwipe.h: The header file of the nwipe program. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef NWIPE_H_ #define NWIPE_H_ #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif /* workaround for Fedora */ #ifndef off64_t # define off64_t off_t #endif /* Busybox headers. */ #ifdef BB_VER #include "busybox.h" #endif /* System headers. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" /* System errors. */ extern int errno; /* Global array to hold log values to print when logging to STDOUT */ extern char **log_lines; extern int log_current_element; extern int log_elements_allocated; extern pthread_mutex_t mutex1; /* Ncurses headers. */ #ifdef NCURSES_IN_SUBDIR #include #else #include #endif #ifdef PANEL_IN_SUBDIR #include #else #include #endif /* Kernel device headers. */ #include /* These types are usually defined in for __KERNEL__ code. */ typedef unsigned long long u64; typedef unsigned long u32; typedef unsigned short u16; typedef unsigned char u8; /* This is required for ioctl BLKGETSIZE64, but it conflicts with . */ /* #include */ /* Define ioctls that cannot be included. */ #define BLKSSZGET _IO(0x12,104) #define BLKBSZGET _IOR(0x12,112,size_t) #define BLKBSZSET _IOW(0x12,113,size_t) #define BLKGETSIZE64 _IOR(0x12,114,sizeof(u64)) /* This is required for ioctl FDFLUSH. */ #include void *signal_hand(void *); #endif /* NWIPE_H_ */ /* eof */ nwipe-0.24/src/options.c000066400000000000000000000266671321204421400152210ustar00rootroot00000000000000/* * options.c: Command line processing routines for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "logging.h" #include "version.h" /* The global options struct. */ nwipe_options_t nwipe_options; int nwipe_options_parse( int argc, char** argv ) { extern char* optarg; /* The working getopt option argument. */ extern int optind; /* The working getopt index into argv. */ extern int optopt; /* The last unhandled getopt option. */ extern int opterr; /* The last getopt error number. */ extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; /* The getopt() result holder. */ int nwipe_opt; /* Array index variable. */ int i; /* The list of acceptable short options. */ char nwipe_options_short [] = "Vhl:hm:p:r:"; /* The list of acceptable long options. */ static struct option nwipe_options_long [] = { /* Set when the user wants to wipe without a confirmation prompt. */ { "autonuke", no_argument, 0, 0 }, /* A GNU standard option. Corresponds to the 'h' short option. */ { "help", no_argument, 0, 'h' }, /* The wipe method. Corresponds to the 'm' short option. */ { "method", required_argument, 0, 'm' }, /* Log file. Corresponds to the 'l' short option. */ { "logfile", required_argument, 0, 'l' }, /* The Pseudo Random Number Generator. */ { "prng", required_argument, 0, 'p' }, /* The number of times to run the method. */ { "rounds", required_argument, 0, 'r' }, /* Whether to blank the disk after wiping. */ { "noblank", no_argument, 0, 0 }, /* Whether to exit after wiping or wait for a keypress. */ { "nowait", no_argument, 0, 0 }, /* Whether to allow signals to interrupt a wipe. */ { "nosignals", no_argument, 0, 0 }, /* Whether to exit after wiping or wait for a keypress. */ { "nogui", no_argument, 0, 0 }, /* A flag to indicate whether the devices whould be opened in sync mode. */ { "sync", no_argument, 0, 0 }, /* Verify that wipe patterns are being written to the device. */ { "verify", required_argument, 0, 0 }, /* Display program version. */ { "version", no_argument, 0, 'V' }, /* Requisite padding for getopt(). */ { 0, 0, 0, 0 } }; /* Set default options. */ nwipe_options.autonuke = 0; nwipe_options.method = &nwipe_dodshort; nwipe_options.prng = &nwipe_twister; nwipe_options.rounds = 1; nwipe_options.noblank = 0; nwipe_options.nowait = 0; nwipe_options.nosignals= 0; nwipe_options.nogui = 0; nwipe_options.sync = 0; nwipe_options.verify = NWIPE_VERIFY_LAST; memset( nwipe_options.logfile, '\0', sizeof(nwipe_options.logfile) ); /* Parse command line options. */ while( 1 ) { /* Get the next command line option with (3)getopt. */ nwipe_opt = getopt_long( argc, argv, nwipe_options_short, nwipe_options_long, &i ); /* Break when we have processed all of the given options. */ if( nwipe_opt < 0 ) { break; } switch( nwipe_opt ) { case 0: /* Long options without short counterparts. */ if( strcmp( nwipe_options_long[i].name, "autonuke" ) == 0 ) { nwipe_options.autonuke = 1; break; } if( strcmp( nwipe_options_long[i].name, "noblank" ) == 0 ) { nwipe_options.noblank = 1; break; } if( strcmp( nwipe_options_long[i].name, "nowait" ) == 0 ) { nwipe_options.nowait = 1; break; } if( strcmp( nwipe_options_long[i].name, "nosignals" ) == 0 ) { nwipe_options.nosignals = 1; break; } if( strcmp( nwipe_options_long[i].name, "nogui" ) == 0 ) { nwipe_options.nogui = 1; nwipe_options.nowait = 1; break; } if( strcmp( nwipe_options_long[i].name, "sync" ) == 0 ) { nwipe_options.sync = 1; break; } if( strcmp( nwipe_options_long[i].name, "verify" ) == 0 ) { if( strcmp( optarg, "0" ) == 0 || strcmp( optarg, "off" ) == 0 ) { nwipe_options.verify = NWIPE_VERIFY_NONE; break; } if( strcmp( optarg, "1" ) == 0 || strcmp( optarg, "last" ) == 0 ) { nwipe_options.verify = NWIPE_VERIFY_LAST; break; } if( strcmp( optarg, "2" ) == 0 || strcmp( optarg, "all" ) == 0 ) { nwipe_options.verify = NWIPE_VERIFY_ALL; break; } /* Else we do not know this verification level. */ fprintf( stderr, "Error: Unknown verification level '%s'.\n", optarg ); exit( EINVAL ); } case 'm': /* Method option. */ if( strcmp( optarg, "dod522022m" ) == 0 || strcmp( optarg, "dod" ) == 0 ) { nwipe_options.method = &nwipe_dod522022m; break; } if( strcmp( optarg, "dodshort" ) == 0 || strcmp( optarg, "dod3pass" ) == 0 ) { nwipe_options.method = &nwipe_dodshort; break; } if( strcmp( optarg, "gutmann" ) == 0 ) { nwipe_options.method = &nwipe_gutmann; break; } if( strcmp( optarg, "ops2" ) == 0 ) { nwipe_options.method = &nwipe_ops2; break; } if( strcmp( optarg, "random" ) == 0 || strcmp( optarg, "prng" ) == 0 || strcmp( optarg, "stream" ) == 0 ) { nwipe_options.method= &nwipe_random; break; } if( strcmp( optarg, "zero" ) == 0 || strcmp( optarg, "quick" ) == 0 ) { nwipe_options.method = &nwipe_zero; break; } /* Else we do not know this wipe method. */ fprintf( stderr, "Error: Unknown wipe method '%s'.\n", optarg ); exit( EINVAL ); case 'l': /* Log file option. */ nwipe_options.logfile[strlen(optarg)] = '\0'; strncpy(nwipe_options.logfile, optarg, sizeof(nwipe_options.logfile)); break; case 'h': /* Display help. */ display_help(); break; case 'p': /* PRNG option. */ if( strcmp( optarg, "mersenne" ) == 0 || strcmp( optarg, "twister" ) == 0 ) { nwipe_options.prng = &nwipe_twister; break; } if( strcmp( optarg, "isaac" ) == 0 ) { nwipe_options.prng = &nwipe_isaac; break; } /* Else we do not know this PRNG. */ fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg ); exit( EINVAL ); case 'r': /* Rounds option. */ if( sscanf( optarg, " %i", &nwipe_options.rounds ) != 1 \ || nwipe_options.rounds < 1 ) { fprintf( stderr, "Error: The rounds argument must be a positive integer.\n" ); exit( EINVAL ); } break; case 'V': /* Rounds option. */ printf ( "%s version %s\n", program_name, version_string ); exit( EXIT_SUCCESS ); default: /* Bogus command line argument. */ display_help(); exit( EINVAL ); } /* method */ } /* command line options */ /* Return the number of options that were processed. */ return optind; } /* nwipe_options_parse */ void nwipe_options_log( void ) { /** * Prints a manifest of options to the log. * */ nwipe_log( NWIPE_LOG_NOTICE, "Program options are set as follows..." ); if( nwipe_options.autonuke ) { nwipe_log( NWIPE_LOG_NOTICE, " autonuke = %i (on)", nwipe_options.autonuke ); } else { nwipe_log( NWIPE_LOG_NOTICE, " autonuke = %i (off)", nwipe_options.autonuke ); } if( nwipe_options.noblank ) { nwipe_log( NWIPE_LOG_NOTICE, " do not perform a final blank pass" ); } if( nwipe_options.nowait ) { nwipe_log( NWIPE_LOG_NOTICE, " do not wait for a key before exiting" ); } if( nwipe_options.nosignals ) { nwipe_log( NWIPE_LOG_NOTICE, " do not allow signals to interrupt a wipe" ); } if( nwipe_options.nogui ) { nwipe_log( NWIPE_LOG_NOTICE, " do not show GUI interface" ); } nwipe_log( NWIPE_LOG_NOTICE, " banner = %s", banner ); nwipe_log( NWIPE_LOG_NOTICE, " method = %s", nwipe_method_label( nwipe_options.method ) ); nwipe_log( NWIPE_LOG_NOTICE, " rounds = %i", nwipe_options.rounds ); nwipe_log( NWIPE_LOG_NOTICE, " sync = %i", nwipe_options.sync ); switch( nwipe_options.verify ) { case NWIPE_VERIFY_NONE: nwipe_log( NWIPE_LOG_NOTICE, " verify = %i (off)", nwipe_options.verify ); break; case NWIPE_VERIFY_LAST: nwipe_log( NWIPE_LOG_NOTICE, " verify = %i (last pass)", nwipe_options.verify ); break; case NWIPE_VERIFY_ALL: nwipe_log( NWIPE_LOG_NOTICE, " verify = %i (all passes)", nwipe_options.verify ); break; default: nwipe_log( NWIPE_LOG_NOTICE, " verify = %i", nwipe_options.verify ); break; } } /* nwipe_options_log */ /** * display_help * displays the help section to STDOUT and exits */ void display_help() { printf("Usage: %s [options] [device1] [device2] ...\n", program_name); printf("Options:\n" ); puts(" -V, --version Prints the version number"); puts(" -h, --help Prints this help"); puts(" --autonuke If no devices have been specified on the command line, starts wiping all"); puts(" devices immediately. If devices have been specified, starts wiping only"); puts(" those specified devices immediately."); puts(" --sync Open devices in sync mode"); puts(" --verify=TYPE Whether to perform verification of erasure (default: last)"); puts(" off - Do not verify"); puts(" last - Verify after the last pass"); puts(" all - Verify every pass"); puts(" -m, --method=METHOD The wiping method (default: dodshort). See man page for more details."); puts(" dod522022m / dod - 7 pass DOD 5220.22-M method"); puts(" dodshort / dod3pass - 3 pass DOD method"); puts(" gutmann - Peter Gutmann's Algorithm"); puts(" ops2 - RCMP TSSIT OPS-II"); puts(" random / prng / stream - PRNG Stream"); puts(" zero / quick - Overwrite with zeros"); puts(" -l, --logfile=FILE Filename to log to. Default is STDOUT"); puts(" -p, --prng=METHOD PRNG option (mersenne|twister|isaac)" ); puts(" -r, --rounds=NUM Number of times to wipe the device using the selected method (default: 1)" ); puts(" --noblank Do not blank disk after wipe (default is to complete a final blank pass)" ); puts(" --nowait Do not wait for a key before exiting (default is to wait)" ); puts(" --nosignals Do not allow signals to interrupt a wipe (default is to allow)" ); puts(" --nogui Do not show the GUI interface. Automatically invokes the nowait option" ); puts(" Must be used with --autonuke option. Send SIGUSR1 to log current stats"); puts(""); exit( EXIT_SUCCESS ); } /* eof */ nwipe-0.24/src/options.h000066400000000000000000000061271321204421400152130ustar00rootroot00000000000000/* * options.h: Command line processing routines for nwipe. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef OPTIONS_H_ #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" #define NWIPE_KNOB_LOG_BUFFERSIZE 1024 /* Maximum length of a log event. */ #define NWIPE_KNOB_PARTITIONS "/proc/partitions" #define NWIPE_KNOB_PARTITIONS_PREFIX "/dev/" #define NWIPE_KNOB_PRNG_STATE_LENGTH 512 /* 128 words */ #define NWIPE_KNOB_SCSI "/proc/scsi/scsi" #define NWIPE_KNOB_SLEEP 1 #define NWIPE_KNOB_STAT "/proc/stat" /* Function prototypes for loading options from the environment and command line. */ int nwipe_options_parse( int argc, char** argv ); void nwipe_options_log( void ); /* Function to display help text */ void display_help(); typedef struct /* nwipe_options_t */ { int autonuke; /* Do not prompt the user for confirmation when set. */ int noblank; /* Do not perform a final blanking pass. */ int nowait; /* Do not wait for a final key before exiting. */ int nosignals; /* Do not allow signals to interrupt a wipe. */ int nogui ; /* Do not show the GUI. */ char* banner; /* The product banner shown on the top line of the screen. */ // nwipe_method_t method; /* A function pointer to the wipe method that will be used. */ void* method; /* A function pointer to the wipe method that will be used. */ char logfile[FILENAME_MAX]; /* The filename to log the output to */ nwipe_prng_t* prng; /* The pseudo random number generator implementation. */ int rounds; /* The number of times that the wipe method should be called. */ int sync; /* A flag to indicate whether writes should be sync'd. */ nwipe_verify_t verify; /* A flag to indicate whether writes should be verified. */ } nwipe_options_t; extern nwipe_options_t nwipe_options; #endif /* OPTIONS_H_ */ /* eof */ nwipe-0.24/src/pass.c000066400000000000000000000433631321204421400144640ustar00rootroot00000000000000/* * pass.c: Routines that read and write patterns to block devices. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ /* Why is this needed? Segfaults without it */ #include #include "nwipe.h" #include "context.h" #include "method.h" #include "prng.h" #include "options.h" #include "pass.h" #include "logging.h" int nwipe_random_verify( nwipe_context_t* c ) { /** * Verifies that a random pass was correctly written to the device. * */ /* The result holder. */ int r; /* The IO size. */ size_t blocksize; /* The result buffer for calls to lseek. */ off64_t offset; /* The input buffer. */ char* b; /* The pattern buffer that is used to check the input buffer. */ char* d; /* The number of bytes remaining in the pass. */ u64 z = c->device_size; if( c->prng_seed.s == NULL ) { nwipe_log( NWIPE_LOG_SANITY, "Null seed pointer." ); return -1; } if( c->prng_seed.length <= 0 ) { nwipe_log( NWIPE_LOG_SANITY, "The entropy length member is %i.", c->prng_seed.length ); return -1; } /* Create the input buffer. */ b = malloc( c->device_stat.st_blksize ); /* Check the memory allocation. */ if( ! b ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the input buffer." ); return -1; } /* Create the pattern buffer */ d = malloc( c->device_stat.st_blksize ); /* Check the memory allocation. */ if( ! d ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the pattern buffer." ); return -1; } /* Reset the file pointer. */ offset = lseek( c->device_fd, 0, SEEK_SET ); /* Reset the pass byte counter. */ c->pass_done = 0; if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to reset the '%s' file offset.", c->device_name ); return -1; } if( offset != 0 ) { /* This is system insanity. */ nwipe_log( NWIPE_LOG_SANITY, "lseek() returned a bogus offset on '%s'.", c->device_name ); return -1; } /* Tell our parent that we are syncing the device. */ c->sync_status = 1; /* Sync the device. */ r = fdatasync( c->device_fd ); /* Tell our parent that we have finished syncing the device. */ c->sync_status = 0; if( r != 0 ) { /* FIXME: Is there a better way to handle this? */ nwipe_perror( errno, __FUNCTION__, "fdatasync" ); nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name ); } /* Reseed the PRNG. */ c->prng->init( &c->prng_state, &c->prng_seed ); while( z > 0 ) { if( c->device_stat.st_blksize <= z ) { blocksize = c->device_stat.st_blksize; } else { /* This is a seatbelt for buggy drivers and programming errors because */ /* the device size should always be an even multiple of its blocksize. */ blocksize = z; nwipe_log( NWIPE_LOG_WARNING, "%s: The size of '%s' is not a multiple of its block size %i.", __FUNCTION__, c->device_name, c->device_stat.st_blksize ); } /* Fill the output buffer with the random pattern. */ c->prng->read( &c->prng_state, d, blocksize ); /* Read the buffer in from the device. */ r = read( c->device_fd, b, blocksize ); /* Check the result. */ if( r < 0 ) { nwipe_perror( errno, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to read from '%s'.", c->device_name ); return -1; } /* Check for a partial read. */ if( r != blocksize ) { /* TODO: Handle a partial read. */ /* The number of bytes that were not read. */ int s = blocksize - r; nwipe_log( NWIPE_LOG_WARNING, "%s: Partial read from '%s', %i bytes short.", __FUNCTION__, c->device_name, s ); /* Increment the error count. */ c->verify_errors += 1; /* Bump the file pointer to the next block. */ offset = lseek( c->device_fd, s, SEEK_CUR ); if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial read.", c->device_name ); return -1; } } /* partial read */ /* Compare buffer contents. */ if( memcmp( b, d, blocksize ) != 0 ) { c->verify_errors += 1; } /* Decrement the bytes remaining in this pass. */ z -= r; /* Increment the total progress counters. */ c->pass_done += r; c->round_done += r; pthread_testcancel(); } /* while bytes remaining */ /* Release the buffers. */ free( b ); free( d ); /* We're done. */ return 0; } /* nwipe_random_verify */ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE ) { /** * Writes a random pattern to the device. * */ /* The result holder. */ int r; /* The IO size. */ size_t blocksize; /* The result buffer for calls to lseek. */ off64_t offset; /* The output buffer. */ char* b; /* The number of bytes remaining in the pass. */ u64 z = c->device_size; if( c->prng_seed.s == NULL ) { nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: Null seed pointer." ); return -1; } if( c->prng_seed.length <= 0 ) { nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: The entropy length member is %i.", c->prng_seed.length ); return -1; } /* Create the output buffer. */ b = malloc( c->device_stat.st_blksize ); /* Check the memory allocation. */ if( ! b ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the output buffer." ); return -1; } /* Seed the PRNG. */ c->prng->init( &c->prng_state, &c->prng_seed ); /* Reset the file pointer. */ offset = lseek( c->device_fd, 0, SEEK_SET ); /* Reset the pass byte counter. */ c->pass_done = 0; if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to reset the '%s' file offset.", c->device_name ); return -1; } if( offset != 0 ) { /* This is system insanity. */ nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: lseek() returned a bogus offset on '%s'.", c->device_name ); return -1; } while( z > 0 ) { if( c->device_stat.st_blksize <= z ) { blocksize = c->device_stat.st_blksize; } else { /* This is a seatbelt for buggy drivers and programming errors because */ /* the device size should always be an even multiple of its blocksize. */ blocksize = z; nwipe_log( NWIPE_LOG_WARNING, "%s: The size of '%s' is not a multiple of its block size %i.", __FUNCTION__, c->device_name, c->device_stat.st_blksize ); } /* Fill the output buffer with the random pattern. */ c->prng->read( &c->prng_state, b, blocksize ); /* Write the next block out to the device. */ r = write( c->device_fd, b, blocksize ); /* Check the result for a fatal error. */ if( r < 0 ) { nwipe_perror( errno, __FUNCTION__, "write" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to read from '%s'.", c->device_name ); return -1; } /* Check for a partial write. */ if( r != blocksize ) { /* TODO: Handle a partial write. */ /* The number of bytes that were not written. */ int s = blocksize - r; /* Increment the error count by the number of bytes that were not written. */ c->pass_errors += s; nwipe_log( NWIPE_LOG_WARNING, "Partial write on '%s', %i bytes short.", c->device_name, s ); /* Bump the file pointer to the next block. */ offset = lseek( c->device_fd, s, SEEK_CUR ); if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial write.", c->device_name ); return -1; } } /* partial write */ /* Decrement the bytes remaining in this pass. */ z -= r; /* Increment the total progress counters. */ c->pass_done += r; c->round_done += r; pthread_testcancel(); } /* remaining bytes */ /* Release the output buffer. */ free( b ); /* Tell our parent that we are syncing the device. */ c->sync_status = 1; /* Sync the device. */ r = fdatasync( c->device_fd ); /* Tell our parent that we have finished syncing the device. */ c->sync_status = 0; if( r != 0 ) { /* FIXME: Is there a better way to handle this? */ nwipe_perror( errno, __FUNCTION__, "fdatasync" ); nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name ); } /* We're done. */ return 0; } /* nwipe_random_pass */ int nwipe_static_verify( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern ) { /** * Verifies that a static pass was correctly written to the device. * */ /* The result holder. */ int r; /* The IO size. */ size_t blocksize; /* The result buffer for calls to lseek. */ off64_t offset; /* The input buffer. */ char* b; /* The pattern buffer that is used to check the input buffer. */ char* d; /* A pointer into the pattern buffer. */ char* q; /* The pattern buffer window offset. */ int w = 0; /* The number of bytes remaining in the pass. */ u64 z = c->device_size; if( pattern == NULL ) { /* Caught insanity. */ nwipe_log( NWIPE_LOG_SANITY, "nwipe_static_verify: Null entropy pointer." ); return -1; } if( pattern->length <= 0 ) { /* Caught insanity. */ nwipe_log( NWIPE_LOG_SANITY, "nwipe_static_verify: The pattern length member is %i.", pattern->length ); return -1; } /* Create the input buffer. */ b = malloc( c->device_stat.st_blksize ); /* Check the memory allocation. */ if( ! b ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the input buffer." ); return -1; } /* Create the pattern buffer */ d = malloc( c->device_stat.st_blksize + pattern->length * 2 ); /* Check the memory allocation. */ if( ! d ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the pattern buffer." ); return -1; } for( q = d ; q < d + c->device_stat.st_blksize + pattern->length ; q += pattern->length ) { /* Fill the pattern buffer with the pattern. */ memcpy( q, pattern->s, pattern->length ); } /* Tell our parent that we are syncing the device. */ c->sync_status = 1; /* Sync the device. */ r = fdatasync( c->device_fd ); /* Tell our parent that we have finished syncing the device. */ c->sync_status = 0; if( r != 0 ) { /* FIXME: Is there a better way to handle this? */ nwipe_perror( errno, __FUNCTION__, "fdatasync" ); nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name ); } /* Reset the file pointer. */ offset = lseek( c->device_fd, 0, SEEK_SET ); /* Reset the pass byte counter. */ c->pass_done = 0; if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to reset the '%s' file offset.", c->device_name ); return -1; } if( offset != 0 ) { /* This is system insanity. */ nwipe_log( NWIPE_LOG_SANITY, "nwipe_static_verify: lseek() returned a bogus offset on '%s'.", c->device_name ); return -1; } while( z > 0 ) { if( c->device_stat.st_blksize <= z ) { blocksize = c->device_stat.st_blksize ; } else { /* This is a seatbelt for buggy drivers and programming errors because */ /* the device size should always be an even multiple of its blocksize. */ blocksize = z; nwipe_log( NWIPE_LOG_WARNING, "%s: The size of '%s' is not a multiple of its block size %i.", __FUNCTION__, c->device_name, c->device_stat.st_blksize ); } /* Fill the output buffer with the random pattern. */ /* Read the buffer in from the device. */ r = read( c->device_fd, b, blocksize ); /* Check the result. */ if( r < 0 ) { nwipe_perror( errno, __FUNCTION__, "read" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to read from '%s'.", c->device_name ); return -1; } /* Check for a partial read. */ if( r == blocksize ) { /* Check every byte in the buffer. */ if( memcmp( b, &d[w], r ) != 0 ) { c->verify_errors += 1; } } else { /* The number of bytes that were not read. */ int s = blocksize - r; /* TODO: Handle a partial read. */ /* Increment the error count. */ c->verify_errors += 1; nwipe_log( NWIPE_LOG_WARNING, "Partial read on '%s', %i bytes short.", c->device_name, s ); /* Bump the file pointer to the next block. */ offset = lseek( c->device_fd, s, SEEK_CUR ); if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial read.", c->device_name ); return -1; } } /* partial read */ /* Adjust the window. */ w = ( c->device_stat.st_blksize + w ) % pattern->length; /* Intuition check: * If the pattern length evenly divides the block size * then ( w == 0 ) always. */ /* Decrement the bytes remaining in this pass. */ z -= r; /* Increment the total progress counters. */ c->pass_done += r; c->round_done += r; pthread_testcancel(); } /* while bytes remaining */ /* Release the buffers. */ free( b ); free( d ); /* We're done. */ return 0; } /* nwipe_static_verify */ int nwipe_static_pass( NWIPE_METHOD_SIGNATURE, nwipe_pattern_t* pattern ) { /** * Writes a static pattern to the device. * */ /* The result holder. */ int r; /* The IO size. */ size_t blocksize; /* The result buffer for calls to lseek. */ off64_t offset; /* The output buffer. */ char* b; /* A pointer into the output buffer. */ char* p; /* The output buffer window offset. */ int w = 0; /* The number of bytes remaining in the pass. */ u64 z = c->device_size; if( pattern == NULL ) { /* Caught insanity. */ nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: Null pattern pointer." ); return -1; } if( pattern->length <= 0 ) { /* Caught insanity. */ nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: The pattern length member is %i.", pattern->length ); return -1; } /* Create the output buffer. */ b = malloc( c->device_stat.st_blksize + pattern->length * 2 ); /* Check the memory allocation. */ if( ! b ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the pattern buffer." ); return -1; } for( p = b ; p < b + c->device_stat.st_blksize + pattern->length ; p += pattern->length ) { /* Fill the output buffer with the pattern. */ memcpy( p, pattern->s, pattern->length ); } /// /* Reset the file pointer. */ offset = lseek( c->device_fd, 0, SEEK_SET ); /* Reset the pass byte counter. */ c->pass_done = 0; if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to reset the '%s' file offset.", c->device_name ); return -1; } if( offset != 0 ) { /* This is system insanity. */ nwipe_log( NWIPE_LOG_SANITY, "__FUNCTION__: lseek() returned a bogus offset on '%s'.", c->device_name ); return -1; } while( z > 0 ) { if( c->device_stat.st_blksize <= z ) { blocksize = c->device_stat.st_blksize ; } else { /* This is a seatbelt for buggy drivers and programming errors because */ /* the device size should always be an even multiple of its blocksize. */ blocksize = z; nwipe_log( NWIPE_LOG_WARNING, "%s: The size of '%s' is not a multiple of its block size %i.", __FUNCTION__, c->device_name, c->device_stat.st_blksize ); } /* Fill the output buffer with the random pattern. */ /* Write the next block out to the device. */ r = write( c->device_fd, &b[w], blocksize ); /* Check the result for a fatal error. */ if( r < 0 ) { nwipe_perror( errno, __FUNCTION__, "write" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to write to '%s'.", c->device_name ); return -1; } /* Check for a partial write. */ if( r != blocksize ) { /* TODO: Handle a partial write. */ /* The number of bytes that were not written. */ int s = blocksize - r; /* Increment the error count. */ c->pass_errors += s; nwipe_log( NWIPE_LOG_WARNING, "Partial write on '%s', %i bytes short.", c->device_name, s ); /* Bump the file pointer to the next block. */ offset = lseek( c->device_fd, s, SEEK_CUR ); if( offset == (off64_t)-1 ) { nwipe_perror( errno, __FUNCTION__, "lseek" ); nwipe_log( NWIPE_LOG_ERROR, "Unable to bump the '%s' file offset after a partial write.", c->device_name ); return -1; } } /* partial write */ /* Adjust the window. */ w = ( c->device_stat.st_blksize + w ) % pattern->length; /* Intuition check: * * If the pattern length evenly divides the block size * then ( w == 0 ) always. */ /* Decrement the bytes remaining in this pass. */ z -= r; /* Increment the total progress counterr. */ c->pass_done += r; c->round_done += r; pthread_testcancel(); } /* remaining bytes */ /* Tell our parent that we are syncing the device. */ c->sync_status = 1; /* Sync the device. */ r = fdatasync( c->device_fd ); /* Tell our parent that we have finished syncing the device. */ c->sync_status = 0; if( r != 0 ) { /* FIXME: Is there a better way to handle this? */ nwipe_perror( errno, __FUNCTION__, "fdatasync" ); nwipe_log( NWIPE_LOG_WARNING, "Buffer flush failure on '%s'.", c->device_name ); } /* Release the output buffer. */ free( b ); /* We're done. */ return 0; } /* nwipe_static_pass */ /* eof */ nwipe-0.24/src/pass.h000066400000000000000000000023401321204421400144570ustar00rootroot00000000000000/* * pass.h: Routines that read and write patterns to block devices. * * Copyright Darik Horn . * * Modifications to original dwipe Copyright Andy Beverley * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef PASS_H_ #define PASS_H_ int nwipe_random_pass ( nwipe_context_t* c ); int nwipe_random_verify( nwipe_context_t* c ); int nwipe_static_pass ( nwipe_context_t* c, nwipe_pattern_t* pattern ); int nwipe_static_verify( nwipe_context_t* c, nwipe_pattern_t* pattern ); void test_functionn( int count, nwipe_context_t** c ); #endif /* PASS_H_ */ /* eof */ nwipe-0.24/src/prng.c000066400000000000000000000073551321204421400144650ustar00rootroot00000000000000/* * prng.c: Pseudo Random Number Generator abstractions for nwipe. * * Copyright Darik Horn . * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "nwipe.h" #include "prng.h" #include "logging.h" #include "mt19937ar-cok.h" #include "isaac_rand.h" nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read }; nwipe_prng_t nwipe_isaac = { "ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read }; /* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian*/ int nwipe_u32tobuffer(u8 *buffer, u32 rand, int len) { int i; u8 c; //single char if (len > sizeof(u32)) { nwipe_log( NWIPE_LOG_FATAL, "Tried to print longer number than the value passed." ); len = sizeof(u32); } for (i=0 ; i < len; i++) { c=rand & 0xFFUL; rand = rand >> 8; buffer[i]=c; } return 0; } int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE ) { if( *state == NULL ) { /* This is the first time that we have been called. */ *state = malloc( sizeof( twister_state_t ) ); } twister_init( (twister_state_t*)*state, (u32*)( seed->s ), seed->length / sizeof( u32 ) ); return 0; } int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE ) { u32 i=0; u32 ii; u32 words = count / SIZE_OF_TWISTER ; // the values of twister_genrand_int32 is strictly 4 bytes u32 remain = count % SIZE_OF_TWISTER ; // the values of twister_genrand_int32 is strictly 4 bytes /* Twister returns 4-bytes per call, so progress by 4 bytes. */ for( ii = 0; ii < words; ++ii ) { nwipe_u32tobuffer((u8*)(buffer+i), twister_genrand_int32( (twister_state_t*)*state ), SIZE_OF_TWISTER) ; i = i + SIZE_OF_TWISTER; } /* If there is some remainder copy only relevant number of bytes to not * overflow the buffer. */ if ( remain > 0 ) { nwipe_u32tobuffer((u8*)(buffer+i), twister_genrand_int32( (twister_state_t*)*state ), remain) ; } return 0; } int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE ) { int count; randctx* isaac_state = *state; if( *state == NULL ) { /* This is the first time that we have been called. */ *state = malloc( sizeof( randctx ) ); isaac_state = *state; /* Check the memory allocation. */ if( isaac_state == 0 ) { nwipe_perror( errno, __FUNCTION__, "malloc" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the isaac state." ); return -1; } } /* Take the minimum of the isaac seed size and available entropy. */ if( sizeof( isaac_state->randrsl ) < seed->length ) { count = sizeof( isaac_state->randrsl ); } else { memset( isaac_state->randrsl, 0, sizeof( isaac_state->randrsl ) ); count = seed->length; } if( count == 0 ) { /* Start ISACC without a seed. */ randinit( isaac_state, 0 ); } else { /* Seed the ISAAC state with entropy. */ memcpy( isaac_state->randrsl, seed->s, count ); /* The second parameter indicates that randrsl is non-empty. */ randinit( isaac_state, 1 ); } return 0; } int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE ) { return 0; } /* eof */ nwipe-0.24/src/prng.h000066400000000000000000000041031321204421400144560ustar00rootroot00000000000000/* * prng.h: Pseudo Random Number Generator abstractions for nwipe. * * Copyright Darik Horn . * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef PRNG_H_ #define PRNG_H_ /* A chunk of random data. */ typedef struct /* nwipe_entropy_t */ { size_t length; /* Length of the entropy string in bytes. */ u8* s; /* The actual bytes of the entropy string. */ } nwipe_entropy_t; #define NWIPE_PRNG_INIT_SIGNATURE void** state, nwipe_entropy_t* seed #define NWIPE_PRNG_READ_SIGNATURE void** state, void* buffer, size_t count /* Function pointers for PRNG actions. */ typedef int(*nwipe_prng_init_t)( NWIPE_PRNG_INIT_SIGNATURE ); typedef int(*nwipe_prng_read_t)( NWIPE_PRNG_READ_SIGNATURE ); /* The generic PRNG definition. */ typedef struct /* nwipe_prng_t */ { const char* label; /* The name of the pseudo random number generator. */ nwipe_prng_init_t init; /* Inialize the prng state with the seed. */ nwipe_prng_read_t read; /* Read data from the prng. */ } nwipe_prng_t; /* Mersenne Twister prototypes. */ int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE ); int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE ); /* ISAAC prototypes. */ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE ); int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE ); /* Size of the twister is not derived from the architecture, but it is strictly 4 bytes */ #define SIZE_OF_TWISTER 4 #endif /* PRNG_H_ */ /* eof */ nwipe-0.24/src/version.c000066400000000000000000000014531321204421400151750ustar00rootroot00000000000000/** * version_string and program_name are used by siege * and configure; author_name and email_address are * used by configure to dynamically assign those values * to documentation files. */ const char *version_string = "0.24"; const char *program_name = "nwipe"; const char *author_name = "Martijn van Brummelen"; const char *email_address = "git@brumit.nl"; const char *years = "2017"; const char *copyright = "Copyright Darik Horn \n\ Modifications to original dwipe Copyright Andy Beverley \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.24 (based on DBAN's dwipe - Darik's Wipe)"; nwipe-0.24/src/version.h000066400000000000000000000003351321204421400152000ustar00rootroot00000000000000#ifndef __VERSION_H #define __VERSION_H extern char *version_string; extern char *program_name; extern char *author_name; extern char *email_address; extern char *copyright; extern char *banner; #endif/*__VERSION_H*/