aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile28
-rw-r--r--info/libpassphrase.texinfo32
-rw-r--r--src/echoes.c90
-rw-r--r--src/passphrase.c287
-rw-r--r--src/passphrase.h11
-rw-r--r--src/passphrase_helper.h11
-rw-r--r--src/test.c3
-rw-r--r--src/wipe.c75
-rwxr-xr-xtest-all-options.sh4
9 files changed, 416 insertions, 125 deletions
diff --git a/Makefile b/Makefile
index a5ee1bc..344d1e1 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ LICENSEDIR = $(DATADIR)/licenses
PKGNAME = libpassphrase
# Options with which to compile the library
-OPTIONS =
+OPTIONS = PASSPHRASE_METER
# PASSPHRASE_ECHO: Do not hide the passphrase
# PASSPHRASE_STAR: Use "*" for each character instead of no echo
# PASSPHRASE_TEXT: Use "(empty)" and "(not empty)" instead of no echo
@@ -42,6 +42,7 @@ OPTIONS =
# PASSPHRASE_DEDICATED: Enable use of dedicated keys
# DEFAULT_INSERT: Use insert mode as default
# PASSPHRASE_INVALID: Prevent duplication of non-initialised memory
+# PASSPHRASE_METER: Enable passphrase strength meter.
# Text to use instead of "*"
PASSPHRASE_STAR_CHAR = *
@@ -82,6 +83,11 @@ CC_FLAGS = $(CPPFLAGS_) $(CFLAGS_) $(OPTIMISE)
LD_FLAGS = $(LDFLAGS_) $(CFLAGS_) $(OPTIMISE)
+# Object files for the library
+OBJ_ = passphrase echoes wipe
+OBJ = $(foreach O,$(OBJ_),obj/$(O).o)
+
+
.PHONY: default
default: lib info
@@ -107,25 +113,25 @@ a: bin/libpassphrase.a
.PHONY: test
test: bin/test
-bin/libpassphrase.so: obj/passphrase.o
+bin/test: bin/libpassphrase.so obj/test.o
+ $(CC) $(LD_FLAGS) -Lbin -lpassphrase -o "$@" obj/test.o $(LDFLAGS)
+
+obj/test.o: src/test.c src/*.h
+ @mkdir -p "$(shell dirname "$@")"
+ $(CC) $(CC_FLAGS) -o "$@" -c "$<" $(CFLAGS) $(CPPFLAGS)
+
+bin/libpassphrase.so: $(OBJ)
@mkdir -p bin
$(CC) $(LD_FLAGS) -shared -Wl,-soname,libpassphrase.so -o "$@" $^ $(LDFLAGS)
-bin/libpassphrase.a: obj/passphrase.o
+bin/libpassphrase.a: $(OBJ)
@mkdir -p bin
ar rcs "$@" $^
-bin/test: bin/libpassphrase.so obj/test.o
- $(CC) $(LD_FLAGS) -Lbin -lpassphrase -o "$@" obj/test.o $(LDFLAGS)
-
-obj/passphrase.o: src/passphrase.c src/*.h
+obj/%.o: src/%.c src/*.h
@mkdir -p "$(shell dirname "$@")"
$(CC) $(CC_FLAGS) -fPIC -o "$@" -c "$<" $(CFLAGS) $(CPPFLAGS)
-obj/test.o: src/test.c src/passphrase.h
- @mkdir -p "$(shell dirname "$@")"
- $(CC) $(CC_FLAGS) -o "$@" -c "$<" $(CFLAGS) $(CPPFLAGS)
-
.PHONY: info
info: bin/libpassphrase.info
bin/%.info: info/%.texinfo
diff --git a/info/libpassphrase.texinfo b/info/libpassphrase.texinfo
index d55d12d..32f19c3 100644
--- a/info/libpassphrase.texinfo
+++ b/info/libpassphrase.texinfo
@@ -194,6 +194,7 @@ and is equivalent to
@code{passphrase_reenable_echo1(STDIN_FILENO)}.
@item void passphrase_wipe(char*, size_t)
+@itemx void passphrase_wipe1(char*)
When you are done using passhprase you should
erase it from the memory before freeing its
allocation. To do this securtly, call
@@ -201,6 +202,9 @@ allocation. To do this securtly, call
as the first argument and the length of the
passphrase as the second argument.
+@code{passphrase_wipe1} will determine the
+length of the passphrase by itself.
+
@end table
These three functions could be made into one
@@ -218,7 +222,6 @@ been disabled.
#include <passphrase.h> /* For libpassphrase */
#include <stdio.h> /* For output */
#include <stdlib.h> /* For free */
-#include <string.h> /* For strlen */
#include <fcntl.h> /* For open, O_RDONLY */
#include <unistd.h> /* For close */
@@ -257,7 +260,7 @@ int main(int argc, char** argv)
printf("You entered: %s\n", passphrase);
/* Wipe and free the passphrase */
- passphrase_wipe(passphrase, strlen(passphrase));
+ passphrase_wipe1(passphrase);
free(passphrase);
/* Stop hiding user input */
@@ -389,6 +392,31 @@ This options is not really needed, but not
using it means that you can get warnings
in @command{valgrind}.
+@item @code{PASSPHRASE_METER}
+When the @code{PASSPHRASE_READ_METER} flag
+is used, and @code{PASSPHRASE_READ_SCREEN_FREE}
+or @code{PASSPHRASE_READ_BELOW_FREE}, use
+@command{passcheck} to evaluate the strenght
+of the passphrase and display a passphrase
+strenght meter. @command{passcheck} will be
+started by the real user, not the effective
+user, and the real group.
+
+It possibly to select another program than
+@command{passcheck} by specifying it setting
+the environment variable @env{LIBPASSPHRASE_METER}.
+@env{LIBPASSPHRASE_METER} will be treated as
+one argument. The selected program must behave
+similar to @command{passcheck}: for each line
+to stdin, it must print a non-negative int
+integer, optinally coloured with one signal
+escape sequence, followed by a new line or
+whitespace; the rest of the is ignored. The
+program must also accept the flag @code{-r},
+telling it not to discard any input.
+
+
+
@end table
diff --git a/src/echoes.c b/src/echoes.c
new file mode 100644
index 0000000..e1a0e63
--- /dev/null
+++ b/src/echoes.c
@@ -0,0 +1,90 @@
+/**
+ * libpassphrase – Personalisable library for TTY passphrase reading
+ *
+ * Copyright © 2013, 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <unistd.h>
+#include <termios.h>
+
+#define PASSPHRASE_USE_DEPRECATED
+#include "passphrase.h"
+#include "passphrase_helper.h"
+
+
+
+#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
+/**
+ * The original TTY settings
+ */
+static struct termios saved_stty;
+#endif /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
+
+
+
+/**
+ * Disable echoing and do anything else to the terminal settnings `passphrase_read` requires
+ */
+void passphrase_disable_echo(void)
+{
+ passphrase_disable_echo1(STDIN_FILENO);
+}
+
+
+/**
+ * Undo the actions of `passphrase_disable_echo`
+ */
+void passphrase_reenable_echo(void)
+{
+ passphrase_reenable_echo1(STDIN_FILENO);
+}
+
+/**
+ * Disable echoing and do anything else to the terminal settnings `passphrase_read2` requires
+ *
+ * @param fdin File descriptor for input
+ */
+void passphrase_disable_echo1(int fdin)
+{
+#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
+ struct termios stty;
+
+ tcgetattr(fdin, &stty);
+ saved_stty = stty;
+ stty.c_lflag &= (tcflag_t)~ECHO;
+# if defined(PASSPHRASE_STAR) || defined(PASSPHRASE_TEXT) || defined(PASSPHRASE_MOVE)
+ stty.c_lflag &= (tcflag_t)~ICANON;
+# endif /* PASSPHRASE_STAR || PASSPHRASE_TEXT || PASSPHRASE_MOVE */
+ tcsetattr(fdin, TCSAFLUSH, &stty);
+#else /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
+ (void) fdin;
+#endif /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
+}
+
+
+/**
+ * Undo the actions of `passphrase_disable_echo1`
+ *
+ * @param fdin File descriptor for input
+ */
+void passphrase_reenable_echo1(int fdin)
+{
+#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
+ tcsetattr(fdin, TCSAFLUSH, &saved_stty);
+#else /* !PASSPHRASE_ECHO || !PASSPHRASE_MOVE */
+ (void) fdin;
+#endif /* !PASSPHRASE_ECHO || !PASSPHRASE_MOVE */
+}
+
diff --git a/src/passphrase.c b/src/passphrase.c
index 9c42c0f..1430a47 100644
--- a/src/passphrase.c
+++ b/src/passphrase.c
@@ -18,26 +18,33 @@
*/
#include <stdlib.h>
#include <stdio.h>
-#include <termios.h>
#include <unistd.h>
-#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/wait.h>
#define PASSPHRASE_USE_DEPRECATED
#include "passphrase.h"
#include "passphrase_helper.h"
-#define START_PASSPHRASE_LIMIT 32
-
+#ifndef START_PASSPHRASE_LIMIT
+# define START_PASSPHRASE_LIMIT 32
+#endif
+#ifndef DEFAULT_PASSPHRASE_METER
+# define DEFAULT_PASSPHRASE_METER "passcheck"
+#endif
-#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
-/**
- * The original TTY settings
- */
-static struct termios saved_stty;
-#endif /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
+#ifdef PASSPHRASE_METER
+struct passcheck_state
+{
+ int pipe_rw[2];
+ pid_t pid;
+ int flags;
+};
+#endif /* PASSPHRASE_METER */
@@ -58,6 +65,136 @@ static char* xrealloc(char* array, size_t cur_size, size_t new_size)
#endif /* !PASSPHRASE_REALLOC */
+#ifdef PASSPHRASE_METER
+static void passcheck_start(struct passcheck_state* state, int flags)
+{
+ const char* command;
+ int pipe_rw[2] = { -1, -1 };
+ int exec_rw[2] = { -1, -1 };
+ pid_t pid;
+ ssize_t n;
+ int i = 0;
+
+ state->pid = -1;
+ state->flags = (flags & PASSPHRASE_READ_NEW) ? (flags ^ PASSPHRASE_READ_NEW) : 0;
+ if (state->flags == 0)
+ return;
+
+ command = getenv("LIBPASSPHRASE_METER");
+ if (!command || !*command)
+ command = DEFAULT_PASSPHRASE_METER;
+
+ xpipe(state->pipe_rw);
+ xpipe(pipe_rw);
+ xpipe(exec_rw);
+ /* ‘Their integer values shall be the two lowest available at the time of the pipe() call’ [man 3p pipe]
+ * This guarantees (unless the application is doing something stupid) that the file desriptors
+ * in exec_rw[1] is not stdin, stdout, stderr, or 0 (required by FD_CLOEXEC to take affect), assuming
+ * stdin, stdout, and stderr are 0, 1, and 2, respectively, as specified in `man 3p stdin`. */
+
+ if (fcntl(exec_rw[1], F_SETFD, FD_CLOEXEC) == -1)
+ goto fail;
+
+ pid = fork();
+ if (pid == -1)
+ {
+ state->flags = 0;
+ goto fail;
+ }
+
+ close(exec_rw[!!pid]), exec_rw[!!pid] = -1;
+ close(state->pipe_rw[!!pid]), state->pipe_rw[!!pid] = -1;
+ close(pipe_rw[!pid]), pipe_rw[!pid] = -1;
+ state->pipe_rw[!!pid] = pipe_rw[!!pid], pipe_rw[!!pid] = -1;
+
+ if (pid == 0)
+ {
+ gid_t gid = getgid(), egid = getegid();
+ uid_t uid = getuid(), euid = geteuid();
+
+ if ((state->pipe_rw[0] != STDIN_FILENO) && (state->pipe_rw[1] == STDIN_FILENO))
+ {
+ pipe_rw[1] = dup(state->pipe_rw[1]);
+ if (pipe_rw[1] == -1)
+ goto child_fail;
+ state->pipe_rw[1] = pipe_rw[1], pipe_rw[1] = -1;
+ }
+ for (i = 0; i <= 1; i++)
+ if (state->pipe_rw[i] != i)
+ {
+ close(i);
+ pipe_rw[i] = dup2(state->pipe_rw[i], i);
+ if (pipe_rw[i] == -1)
+ goto child_fail;
+ close(state->pipe_rw[i]), state->pipe_rw[i] = pipe_rw[i];
+ }
+
+ if (egid != gid)
+ if (setregid(gid, gid) && gid)
+ goto child_fail;
+ if (euid != uid)
+ if (setreuid(uid, uid) && uid)
+ goto child_fail;
+
+ execlp(command, command, "-r", NULL);
+ child_fail:
+ n = write(exec_rw[1], &i, sizeof(i));
+ _exit(!!n);
+ }
+
+ rewait:
+ n = read(exec_rw[0], &i, sizeof(i));
+ if ((n < 0) && (errno == EINTR))
+ goto rewait;
+ if (n)
+ {
+ rereap:
+ if ((waitpid(pid, &i, 0) == -1) && (errno == EINTR))
+ goto rereap;
+ goto fail;
+ }
+
+ close(exec_rw[0]);
+ state->pid = pid;
+ return;
+ fail:
+ if (state->pipe_rw[0] >= 0) close(state->pipe_rw[0]);
+ if (state->pipe_rw[1] >= 0) close(state->pipe_rw[1]);
+ if (pipe_rw[0] >= 0) close(pipe_rw[0]);
+ if (pipe_rw[1] >= 0) close(pipe_rw[1]);
+ if (exec_rw[0] >= 0) close(exec_rw[0]);
+ if (exec_rw[1] >= 0) close(exec_rw[1]);
+ state->pid = -1;
+ state->flags = 0;
+}
+
+static void passcheck_stop(struct passcheck_state* state)
+{
+ int _status;
+
+ if (state->flags == 0)
+ return;
+
+ close(state->pipe_rw[0]);
+ close(state->pipe_rw[1]);
+
+rereap:
+ if ((waitpid(state->pid, &_status, 0) == -1) && (errno == EINTR))
+ goto rereap;
+
+ /* TODO cleanup */
+}
+
+static void passcheck_update(struct passcheck_state* state, char* passphrase, size_t len)
+{
+ if (state->flags == 0)
+ return;
+
+ /* TODO */
+}
+#endif /* PASSPHRASE_METER */
+
+
static int fdgetc(int fd)
{
unsigned char c;
@@ -117,17 +254,6 @@ static int get_key(int c, int fdin)
/**
* Reads the passphrase from stdin
*
- * @return The passphrase, should be wiped and `free`:ed, `NULL` on error
- */
-char* passphrase_read(void)
-{
- return passphrase_read2(STDIN_FILENO, 0);
-}
-
-
-/**
- * Reads the passphrase from stdin
- *
* @param fdin File descriptor for input
* @param flags Settings, a combination of the constants:
* * PASSPHRASE_READ_EXISTING
@@ -157,11 +283,17 @@ char* passphrase_read2(int fdin, int flags)
#ifdef PASSPHRASE_MOVE
int cc;
#endif
- (void) flags;
+#ifdef PASSPHRASE_METER
+ struct passcheck_state passcheck;
+#endif /* PASSPHRASE_METER */
if (rc == NULL)
return NULL;
+#ifdef PASSPHRASE_METER
+ passcheck_start(&passcheck, flags);
+#endif /* PASSPHRASE_METER */
+
#ifdef PASSPHRASE_TEXT
xprintf("%s%zn", PASSPHRASE_TEXT_EMPTY, &printed_len);
if (printed_len)
@@ -174,8 +306,16 @@ char* passphrase_read2(int fdin, int flags)
for (;;)
{
c = fdgetc(fdin);
- if ((c < 0) || (c == '\n')) break;
- if (c == 0) continue;
+ if ((c < 0) || (c == '\n'))
+ {
+#ifdef PASSPHRASE_METER
+ passcheck_stop(&passcheck);
+ xflush();
+#endif /* PASSPHRASE_METER */
+ break;
+ }
+ if (c == 0)
+ continue;
#if defined(PASSPHRASE_MOVE)
cc = get_key(c, fdin);
@@ -215,6 +355,11 @@ char* passphrase_read2(int fdin, int flags)
continue;
erase_prev();
print_erase();
+
+#ifdef PASSPHRASE_METER
+ passcheck_update(&passcheck, rc, len);
+#endif /* PASSPHRASE_METER */
+
xflush();
# ifdef DEBUG
goto debug;
@@ -228,6 +373,10 @@ char* passphrase_read2(int fdin, int flags)
append_char();
#endif /* PASSPHRASE_MOVE, PASSPHRASE_STAR || PASSPHRASE_TEXT */
+#ifdef PASSPHRASE_METER
+ passcheck_update(&passcheck, rc, len);
+#endif /* PASSPHRASE_METER */
+
xflush();
if (len == size)
{
@@ -264,96 +413,20 @@ char* passphrase_read2(int fdin, int flags)
fprintf(stderr, "\n");
#endif /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
return rc;
-}
-
-
-#ifdef __GNUC__
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
-# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
-#endif
-/* Must positively absolutely not be flagged as possible to optimise away as it depends on configurations,
- and programs that uses this library must not be forced to be recompiled if the library is reconfigured. */
-
-
-/**
- * Used to make sure that `passphrase_wipe` is not optimised away even within this library
- */
-volatile sig_atomic_t passphrase_wipe_volatile________________ = 1;
-
-/**
- * Forcable write NUL characters to a passphrase
- *
- * @param ptr The password to wipe
- * @param n The number of characters to wipe
- */
-#ifdef __GNUC__
-__attribute__((optimize("-O0")))
-#endif
-void passphrase_wipe(volatile char* ptr, size_t n)
-{
- size_t i;
- for (i = 0; (i < n) && passphrase_wipe_volatile________________; i++)
- *(ptr + i) = 0;
-}
-
-
-/**
- * Disable echoing and do anything else to the terminal settnings `passphrase_read` requires
- */
-void passphrase_disable_echo(void)
-{
- passphrase_disable_echo1(STDIN_FILENO);
-}
-
-
-/**
- * Undo the actions of `passphrase_disable_echo`
- */
-void passphrase_reenable_echo(void)
-{
- passphrase_reenable_echo1(STDIN_FILENO);
-}
-
-/**
- * Disable echoing and do anything else to the terminal settnings `passphrase_read2` requires
- *
- * @param fdin File descriptor for input
- */
-void passphrase_disable_echo1(int fdin)
-{
-#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
- struct termios stty;
- tcgetattr(fdin, &stty);
- saved_stty = stty;
- stty.c_lflag &= (tcflag_t)~ECHO;
-# if defined(PASSPHRASE_STAR) || defined(PASSPHRASE_TEXT) || defined(PASSPHRASE_MOVE)
- stty.c_lflag &= (tcflag_t)~ICANON;
-# endif /* PASSPHRASE_STAR || PASSPHRASE_TEXT || PASSPHRASE_MOVE */
- tcsetattr(fdin, TCSAFLUSH, &stty);
-#else /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
- (void) fdin;
-#endif /* !PASSPHRASE_ECHO || PASSPHRASE_MOVE */
+#ifndef PASSPHRASE_METER
+ (void) flags;
+#endif /* !PASSPHRASE_METER */
}
/**
- * Undo the actions of `passphrase_disable_echo1`
+ * Reads the passphrase from stdin
*
- * @param fdin File descriptor for input
+ * @return The passphrase, should be wiped and `free`:ed, `NULL` on error
*/
-void passphrase_reenable_echo1(int fdin)
+char* passphrase_read(void)
{
-#if !defined(PASSPHRASE_ECHO) || defined(PASSPHRASE_MOVE)
- tcsetattr(fdin, TCSAFLUSH, &saved_stty);
-#else /* !PASSPHRASE_ECHO || !PASSPHRASE_MOVE */
- (void) fdin;
-#endif /* !PASSPHRASE_ECHO || !PASSPHRASE_MOVE */
+ return passphrase_read2(STDIN_FILENO, 0);
}
-
-#ifdef __GNUC__
-# pragma GCC diagnostic pop
-#endif
-
diff --git a/src/passphrase.h b/src/passphrase.h
index d24e66e..24ee71b 100644
--- a/src/passphrase.h
+++ b/src/passphrase.h
@@ -93,12 +93,19 @@ char* passphrase_read(void);
char* passphrase_read2(int, int);
/**
- * Forcable write NUL characters to a passphrase
+ * Forcefully write NUL characters to a passphrase
*
* @param ptr The password to wipe
* @param n The number of characters to wipe
*/
-void passphrase_wipe(volatile char*, size_t);
+void passphrase_wipe(char*, size_t);
+
+/**
+ * Forcefully write NUL characters to a passphrase
+ *
+ * @param ptr The password to wipe
+ */
+void passphrase_wipe1(char*);
/**
* Disable echoing and do anything else to the terminal settnings `passphrase_read` requires
diff --git a/src/passphrase_helper.h b/src/passphrase_helper.h
index 792498e..b8abb3a 100644
--- a/src/passphrase_helper.h
+++ b/src/passphrase_helper.h
@@ -379,6 +379,17 @@
#endif
+#define xpipe(pair) \
+ do { \
+ if (pipe(pair)) \
+ { \
+ pair[0] = pair[1] = -1; \
+ goto fail; \
+ } \
+ } while (0)
+
+
+
#endif
diff --git a/src/test.c b/src/test.c
index 36e9afc..a962bd5 100644
--- a/src/test.c
+++ b/src/test.c
@@ -19,7 +19,6 @@
#include "passphrase.h"
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@@ -67,7 +66,7 @@ int main(int argc, char** argv)
printf("You entered: %s\n", passphrase);
/* Wipe and free the passphrase */
- passphrase_wipe(passphrase, strlen(passphrase));
+ passphrase_wipe1(passphrase);
free(passphrase);
/* Stop hiding user input */
diff --git a/src/wipe.c b/src/wipe.c
new file mode 100644
index 0000000..ca67eb1
--- /dev/null
+++ b/src/wipe.c
@@ -0,0 +1,75 @@
+/**
+ * libpassphrase – Personalisable library for TTY passphrase reading
+ *
+ * Copyright © 2013, 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <string.h>
+
+#define PASSPHRASE_USE_DEPRECATED
+#include "passphrase.h"
+#include "passphrase_helper.h"
+
+
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+#endif
+/* Must positively absolutely not be flagged as possible to optimise away as it depends on configurations,
+ and programs that uses this library must not be forced to be recompiled if the library is reconfigured. */
+
+
+/**
+ * `memset`, except calls to it cannot be removed by the compiler.
+ */
+void* (*volatile passphrase_explicit_memset________________)(void*, int, size_t) = memset;
+
+
+/**
+ * Forcefully write NUL characters to a passphrase
+ *
+ * @param ptr The password to wipe
+ * @param n The number of characters to wipe
+ */
+#ifdef __GNUC__
+__attribute__((optimize("-O0")))
+#endif
+void passphrase_wipe(char* ptr, size_t n)
+{
+
+ passphrase_explicit_memset________________(ptr, 0, n);
+}
+
+/**
+ * Forcefully write NUL characters to a passphrase
+ *
+ * @param ptr The password to wipe
+ */
+#ifdef __GNUC__
+__attribute__((optimize("-O0")))
+#endif
+void passphrase_wipe1(char* ptr)
+{
+
+ passphrase_explicit_memset________________(ptr, 0, strlen(ptr));
+}
+
+
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
diff --git a/test-all-options.sh b/test-all-options.sh
index 9572be2..c93fe27 100755
--- a/test-all-options.sh
+++ b/test-all-options.sh
@@ -9,7 +9,9 @@ for a in PASSPHRASE_ECHO PASSPHRASE_STAR PASSPHRASE_TEXT ""; do
for g in PASSPHRASE_CONTROL ""; do
for h in PASSPHRASE_DEDICATED ""; do
for i in DEFAULT_INSERT ""; do
- make libpassphrase -B OPTIONS="$a $b $c $d $e $f $g $h $i" || exit 1
+ for j in PASSPHRASE_METER ""; do
+ make libpassphrase -B OPTIONS="$a $b $c $d $e $f $g $h $i $j" || exit 1
+ done
done
done
done