xref: /freebsd/contrib/libarchive/libarchive_fe/passphrase.c (revision f061a2215f9bf0bea98ac601a34750f89428db67)
1cdf63a70SMartin Matuska /*-
2cdf63a70SMartin Matuska  * Copyright (c) 2014 Michihiro NAKAJIMA
3cdf63a70SMartin Matuska  * All rights reserved.
4cdf63a70SMartin Matuska  *
5cdf63a70SMartin Matuska  * Redistribution and use in source and binary forms, with or without
6cdf63a70SMartin Matuska  * modification, are permitted provided that the following conditions
7cdf63a70SMartin Matuska  * are met:
8cdf63a70SMartin Matuska  * 1. Redistributions of source code must retain the above copyright
9cdf63a70SMartin Matuska  *    notice, this list of conditions and the following disclaimer
10cdf63a70SMartin Matuska  *    in this position and unchanged.
11cdf63a70SMartin Matuska  * 2. Redistributions in binary form must reproduce the above copyright
12cdf63a70SMartin Matuska  *    notice, this list of conditions and the following disclaimer in the
13cdf63a70SMartin Matuska  *    documentation and/or other materials provided with the distribution.
14cdf63a70SMartin Matuska  *
15cdf63a70SMartin Matuska  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16cdf63a70SMartin Matuska  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17cdf63a70SMartin Matuska  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18cdf63a70SMartin Matuska  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19cdf63a70SMartin Matuska  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20cdf63a70SMartin Matuska  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21cdf63a70SMartin Matuska  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22cdf63a70SMartin Matuska  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23cdf63a70SMartin Matuska  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24cdf63a70SMartin Matuska  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25cdf63a70SMartin Matuska  */
26cdf63a70SMartin Matuska /*	$OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $	*/
27cdf63a70SMartin Matuska /*
28cdf63a70SMartin Matuska  * Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com>
29cdf63a70SMartin Matuska  *
30cdf63a70SMartin Matuska  * Permission to use, copy, modify, and distribute this software for any
31cdf63a70SMartin Matuska  * purpose with or without fee is hereby granted, provided that the above
32cdf63a70SMartin Matuska  * copyright notice and this permission notice appear in all copies.
33cdf63a70SMartin Matuska  *
34cdf63a70SMartin Matuska  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
35cdf63a70SMartin Matuska  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
36cdf63a70SMartin Matuska  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
37cdf63a70SMartin Matuska  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38cdf63a70SMartin Matuska  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
39cdf63a70SMartin Matuska  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
40cdf63a70SMartin Matuska  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41cdf63a70SMartin Matuska  *
42cdf63a70SMartin Matuska  * Sponsored in part by the Defense Advanced Research Projects
43cdf63a70SMartin Matuska  * Agency (DARPA) and Air Force Research Laboratory, Air Force
44cdf63a70SMartin Matuska  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
45cdf63a70SMartin Matuska  */
46cdf63a70SMartin Matuska 
47cdf63a70SMartin Matuska /* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
48cdf63a70SMartin Matuska 
49cdf63a70SMartin Matuska 
50cdf63a70SMartin Matuska #include "lafe_platform.h"
51cdf63a70SMartin Matuska __FBSDID("$FreeBSD$");
52cdf63a70SMartin Matuska 
53cdf63a70SMartin Matuska #include <errno.h>
54cdf63a70SMartin Matuska #ifdef HAVE_STDLIB_H
55cdf63a70SMartin Matuska #include <stdlib.h>
56cdf63a70SMartin Matuska #endif
57cdf63a70SMartin Matuska #ifdef HAVE_UNISTD_H
58cdf63a70SMartin Matuska #include <unistd.h>
59cdf63a70SMartin Matuska #endif
60cdf63a70SMartin Matuska #ifdef HAVE_READPASSPHRASE_H
61cdf63a70SMartin Matuska #include <readpassphrase.h>
62cdf63a70SMartin Matuska #endif
63cdf63a70SMartin Matuska 
64cdf63a70SMartin Matuska #include "err.h"
65cdf63a70SMartin Matuska #include "passphrase.h"
66cdf63a70SMartin Matuska 
67cdf63a70SMartin Matuska #ifndef HAVE_READPASSPHRASE
68cdf63a70SMartin Matuska 
69cdf63a70SMartin Matuska #define RPP_ECHO_OFF    0x00		/* Turn off echo (default). */
70cdf63a70SMartin Matuska #define RPP_ECHO_ON     0x01		/* Leave echo on. */
71cdf63a70SMartin Matuska #define RPP_REQUIRE_TTY 0x02		/* Fail if there is no tty. */
72cdf63a70SMartin Matuska #define RPP_FORCELOWER  0x04		/* Force input to lower case. */
73cdf63a70SMartin Matuska #define RPP_FORCEUPPER  0x08		/* Force input to upper case. */
74cdf63a70SMartin Matuska #define RPP_SEVENBIT    0x10		/* Strip the high bit from input. */
75cdf63a70SMartin Matuska #define RPP_STDIN       0x20		/* Read from stdin, not /dev/tty */
76cdf63a70SMartin Matuska 
77cdf63a70SMartin Matuska 
78cdf63a70SMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
79cdf63a70SMartin Matuska #include <windows.h>
80cdf63a70SMartin Matuska 
81cdf63a70SMartin Matuska static char *
82cdf63a70SMartin Matuska readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
83cdf63a70SMartin Matuska {
84cdf63a70SMartin Matuska 	HANDLE hStdin, hStdout;
85cdf63a70SMartin Matuska 	DWORD mode, rbytes;
86cdf63a70SMartin Matuska 	BOOL success;
87cdf63a70SMartin Matuska 
88cdf63a70SMartin Matuska 	(void)flags;
89cdf63a70SMartin Matuska 
90cdf63a70SMartin Matuska 	hStdin = GetStdHandle(STD_INPUT_HANDLE);
91cdf63a70SMartin Matuska 	if (hStdin == INVALID_HANDLE_VALUE)
92cdf63a70SMartin Matuska 		return (NULL);
93cdf63a70SMartin Matuska 	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
94cdf63a70SMartin Matuska 	if (hStdout == INVALID_HANDLE_VALUE)
95cdf63a70SMartin Matuska 		return (NULL);
96cdf63a70SMartin Matuska 
97cdf63a70SMartin Matuska 	success = GetConsoleMode(hStdin, &mode);
98cdf63a70SMartin Matuska 	if (!success)
99cdf63a70SMartin Matuska 		return (NULL);
100cdf63a70SMartin Matuska 	mode &= ~ENABLE_ECHO_INPUT;
101cdf63a70SMartin Matuska 	mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
102cdf63a70SMartin Matuska 	success = SetConsoleMode(hStdin, mode);
103cdf63a70SMartin Matuska 	if (!success)
104cdf63a70SMartin Matuska 		return (NULL);
105cdf63a70SMartin Matuska 
106cdf63a70SMartin Matuska 	success = WriteFile(hStdout, prompt, (DWORD)strlen(prompt),
107cdf63a70SMartin Matuska 		NULL, NULL);
108cdf63a70SMartin Matuska 	if (!success)
109cdf63a70SMartin Matuska 		return (NULL);
110cdf63a70SMartin Matuska 	success = ReadFile(hStdin, buf, (DWORD)bufsiz - 1, &rbytes, NULL);
111cdf63a70SMartin Matuska 	if (!success)
112cdf63a70SMartin Matuska 		return (NULL);
113cdf63a70SMartin Matuska 	WriteFile(hStdout, "\r\n", 2, NULL, NULL);
114cdf63a70SMartin Matuska 	buf[rbytes] = '\0';
115cdf63a70SMartin Matuska 	/* Remove trailing carriage return(s). */
116cdf63a70SMartin Matuska 	if (rbytes > 2 && buf[rbytes - 2] == '\r' && buf[rbytes - 1] == '\n')
117cdf63a70SMartin Matuska 		buf[rbytes - 2] = '\0';
118cdf63a70SMartin Matuska 
119cdf63a70SMartin Matuska 	return (buf);
120cdf63a70SMartin Matuska }
121cdf63a70SMartin Matuska 
122cdf63a70SMartin Matuska #else /* _WIN32 && !__CYGWIN__ */
123cdf63a70SMartin Matuska 
124*f061a221SMartin Matuska #include <assert.h>
125cdf63a70SMartin Matuska #include <ctype.h>
126cdf63a70SMartin Matuska #include <fcntl.h>
127cdf63a70SMartin Matuska #ifdef HAVE_PATHS_H
128cdf63a70SMartin Matuska #include <paths.h>
129cdf63a70SMartin Matuska #endif
130*f061a221SMartin Matuska #include <signal.h>
131cdf63a70SMartin Matuska #include <string.h>
132*f061a221SMartin Matuska #include <termios.h>
133cdf63a70SMartin Matuska #include <unistd.h>
134cdf63a70SMartin Matuska 
135cdf63a70SMartin Matuska #ifdef TCSASOFT
136cdf63a70SMartin Matuska # define _T_FLUSH	(TCSAFLUSH|TCSASOFT)
137cdf63a70SMartin Matuska #else
138cdf63a70SMartin Matuska # define _T_FLUSH	(TCSAFLUSH)
139cdf63a70SMartin Matuska #endif
140cdf63a70SMartin Matuska 
141cdf63a70SMartin Matuska /* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
142cdf63a70SMartin Matuska #if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
143cdf63a70SMartin Matuska #  define _POSIX_VDISABLE       VDISABLE
144cdf63a70SMartin Matuska #endif
145cdf63a70SMartin Matuska 
146*f061a221SMartin Matuska #define M(a,b) (a > b ? a : b)
147*f061a221SMartin Matuska #define MAX_SIGNO M(M(M(SIGALRM, SIGHUP), \
148*f061a221SMartin Matuska                       M(SIGINT, SIGPIPE)), \
149*f061a221SMartin Matuska                     M(M(SIGQUIT, SIGTERM), \
150*f061a221SMartin Matuska                       M(M(SIGTSTP, SIGTTIN), SIGTTOU)))
151*f061a221SMartin Matuska 
152*f061a221SMartin Matuska static volatile sig_atomic_t signo[MAX_SIGNO + 1];
153cdf63a70SMartin Matuska 
154cdf63a70SMartin Matuska static void
155cdf63a70SMartin Matuska handler(int s)
156cdf63a70SMartin Matuska {
157*f061a221SMartin Matuska 	assert(s <= MAX_SIGNO);
158cdf63a70SMartin Matuska 	signo[s] = 1;
159cdf63a70SMartin Matuska }
160cdf63a70SMartin Matuska 
161cdf63a70SMartin Matuska static char *
162cdf63a70SMartin Matuska readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
163cdf63a70SMartin Matuska {
164cdf63a70SMartin Matuska 	ssize_t nr;
165cdf63a70SMartin Matuska 	int input, output, save_errno, i, need_restart;
166cdf63a70SMartin Matuska 	char ch, *p, *end;
167cdf63a70SMartin Matuska 	struct termios term, oterm;
168cdf63a70SMartin Matuska 	struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
169cdf63a70SMartin Matuska 	struct sigaction savetstp, savettin, savettou, savepipe;
170cdf63a70SMartin Matuska 
171cdf63a70SMartin Matuska 	/* I suppose we could alloc on demand in this case (XXX). */
172cdf63a70SMartin Matuska 	if (bufsiz == 0) {
173cdf63a70SMartin Matuska 		errno = EINVAL;
174cdf63a70SMartin Matuska 		return(NULL);
175cdf63a70SMartin Matuska 	}
176cdf63a70SMartin Matuska 
177cdf63a70SMartin Matuska restart:
178*f061a221SMartin Matuska 	for (i = 0; i <= MAX_SIGNO; i++)
179cdf63a70SMartin Matuska 		signo[i] = 0;
180cdf63a70SMartin Matuska 	nr = -1;
181cdf63a70SMartin Matuska 	save_errno = 0;
182cdf63a70SMartin Matuska 	need_restart = 0;
183cdf63a70SMartin Matuska 	/*
184cdf63a70SMartin Matuska 	 * Read and write to /dev/tty if available.  If not, read from
185cdf63a70SMartin Matuska 	 * stdin and write to stderr unless a tty is required.
186cdf63a70SMartin Matuska 	 */
187cdf63a70SMartin Matuska 	if ((flags & RPP_STDIN) ||
188cdf63a70SMartin Matuska 	    (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
189cdf63a70SMartin Matuska 		if (flags & RPP_REQUIRE_TTY) {
190cdf63a70SMartin Matuska 			errno = ENOTTY;
191cdf63a70SMartin Matuska 			return(NULL);
192cdf63a70SMartin Matuska 		}
193cdf63a70SMartin Matuska 		input = STDIN_FILENO;
194cdf63a70SMartin Matuska 		output = STDERR_FILENO;
195cdf63a70SMartin Matuska 	}
196cdf63a70SMartin Matuska 
197cdf63a70SMartin Matuska 	/*
198cdf63a70SMartin Matuska 	 * Catch signals that would otherwise cause the user to end
199cdf63a70SMartin Matuska 	 * up with echo turned off in the shell.  Don't worry about
200cdf63a70SMartin Matuska 	 * things like SIGXCPU and SIGVTALRM for now.
201cdf63a70SMartin Matuska 	 */
202cdf63a70SMartin Matuska 	sigemptyset(&sa.sa_mask);
203cdf63a70SMartin Matuska 	sa.sa_flags = 0;		/* don't restart system calls */
204cdf63a70SMartin Matuska 	sa.sa_handler = handler;
205*f061a221SMartin Matuska 	/* Keep this list in sync with MAX_SIGNO! */
206cdf63a70SMartin Matuska 	(void)sigaction(SIGALRM, &sa, &savealrm);
207cdf63a70SMartin Matuska 	(void)sigaction(SIGHUP, &sa, &savehup);
208cdf63a70SMartin Matuska 	(void)sigaction(SIGINT, &sa, &saveint);
209cdf63a70SMartin Matuska 	(void)sigaction(SIGPIPE, &sa, &savepipe);
210cdf63a70SMartin Matuska 	(void)sigaction(SIGQUIT, &sa, &savequit);
211cdf63a70SMartin Matuska 	(void)sigaction(SIGTERM, &sa, &saveterm);
212cdf63a70SMartin Matuska 	(void)sigaction(SIGTSTP, &sa, &savetstp);
213cdf63a70SMartin Matuska 	(void)sigaction(SIGTTIN, &sa, &savettin);
214cdf63a70SMartin Matuska 	(void)sigaction(SIGTTOU, &sa, &savettou);
215cdf63a70SMartin Matuska 
216cdf63a70SMartin Matuska 	/* Turn off echo if possible. */
217cdf63a70SMartin Matuska 	if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
218cdf63a70SMartin Matuska 		memcpy(&term, &oterm, sizeof(term));
219cdf63a70SMartin Matuska 		if (!(flags & RPP_ECHO_ON))
220cdf63a70SMartin Matuska 			term.c_lflag &= ~(ECHO | ECHONL);
221cdf63a70SMartin Matuska #ifdef VSTATUS
222cdf63a70SMartin Matuska 		if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
223cdf63a70SMartin Matuska 			term.c_cc[VSTATUS] = _POSIX_VDISABLE;
224cdf63a70SMartin Matuska #endif
225cdf63a70SMartin Matuska 		(void)tcsetattr(input, _T_FLUSH, &term);
226cdf63a70SMartin Matuska 	} else {
227cdf63a70SMartin Matuska 		memset(&term, 0, sizeof(term));
228cdf63a70SMartin Matuska 		term.c_lflag |= ECHO;
229cdf63a70SMartin Matuska 		memset(&oterm, 0, sizeof(oterm));
230cdf63a70SMartin Matuska 		oterm.c_lflag |= ECHO;
231cdf63a70SMartin Matuska 	}
232cdf63a70SMartin Matuska 
233cdf63a70SMartin Matuska 	/* No I/O if we are already backgrounded. */
234cdf63a70SMartin Matuska 	if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) {
235cdf63a70SMartin Matuska 		if (!(flags & RPP_STDIN)) {
236cdf63a70SMartin Matuska 			int r = write(output, prompt, strlen(prompt));
237cdf63a70SMartin Matuska 			(void)r;
238cdf63a70SMartin Matuska 		}
239cdf63a70SMartin Matuska 		end = buf + bufsiz - 1;
240cdf63a70SMartin Matuska 		p = buf;
241cdf63a70SMartin Matuska 		while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
242cdf63a70SMartin Matuska 			if (p < end) {
243cdf63a70SMartin Matuska 				if ((flags & RPP_SEVENBIT))
244cdf63a70SMartin Matuska 					ch &= 0x7f;
245*f061a221SMartin Matuska 				if (isalpha((unsigned char)ch)) {
246cdf63a70SMartin Matuska 					if ((flags & RPP_FORCELOWER))
247*f061a221SMartin Matuska 						ch = (char)tolower((unsigned char)ch);
248cdf63a70SMartin Matuska 					if ((flags & RPP_FORCEUPPER))
249*f061a221SMartin Matuska 						ch = (char)toupper((unsigned char)ch);
250cdf63a70SMartin Matuska 				}
251cdf63a70SMartin Matuska 				*p++ = ch;
252cdf63a70SMartin Matuska 			}
253cdf63a70SMartin Matuska 		}
254cdf63a70SMartin Matuska 		*p = '\0';
255cdf63a70SMartin Matuska 		save_errno = errno;
256cdf63a70SMartin Matuska 		if (!(term.c_lflag & ECHO)) {
257cdf63a70SMartin Matuska 			int r = write(output, "\n", 1);
258cdf63a70SMartin Matuska 			(void)r;
259cdf63a70SMartin Matuska 		}
260cdf63a70SMartin Matuska 	}
261cdf63a70SMartin Matuska 
262cdf63a70SMartin Matuska 	/* Restore old terminal settings and signals. */
263cdf63a70SMartin Matuska 	if (memcmp(&term, &oterm, sizeof(term)) != 0) {
264cdf63a70SMartin Matuska 		while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
265cdf63a70SMartin Matuska 		    errno == EINTR)
266cdf63a70SMartin Matuska 			continue;
267cdf63a70SMartin Matuska 	}
268cdf63a70SMartin Matuska 	(void)sigaction(SIGALRM, &savealrm, NULL);
269cdf63a70SMartin Matuska 	(void)sigaction(SIGHUP, &savehup, NULL);
270cdf63a70SMartin Matuska 	(void)sigaction(SIGINT, &saveint, NULL);
271cdf63a70SMartin Matuska 	(void)sigaction(SIGQUIT, &savequit, NULL);
272cdf63a70SMartin Matuska 	(void)sigaction(SIGPIPE, &savepipe, NULL);
273cdf63a70SMartin Matuska 	(void)sigaction(SIGTERM, &saveterm, NULL);
274cdf63a70SMartin Matuska 	(void)sigaction(SIGTSTP, &savetstp, NULL);
275cdf63a70SMartin Matuska 	(void)sigaction(SIGTTIN, &savettin, NULL);
276cdf63a70SMartin Matuska 	(void)sigaction(SIGTTOU, &savettou, NULL);
277cdf63a70SMartin Matuska 	if (input != STDIN_FILENO)
278cdf63a70SMartin Matuska 		(void)close(input);
279cdf63a70SMartin Matuska 
280cdf63a70SMartin Matuska 	/*
281cdf63a70SMartin Matuska 	 * If we were interrupted by a signal, resend it to ourselves
282cdf63a70SMartin Matuska 	 * now that we have restored the signal handlers.
283cdf63a70SMartin Matuska 	 */
284*f061a221SMartin Matuska 	for (i = 0; i <= MAX_SIGNO; i++) {
285cdf63a70SMartin Matuska 		if (signo[i]) {
286cdf63a70SMartin Matuska 			kill(getpid(), i);
287cdf63a70SMartin Matuska 			switch (i) {
288cdf63a70SMartin Matuska 			case SIGTSTP:
289cdf63a70SMartin Matuska 			case SIGTTIN:
290cdf63a70SMartin Matuska 			case SIGTTOU:
291cdf63a70SMartin Matuska 				need_restart = 1;
292cdf63a70SMartin Matuska 			}
293cdf63a70SMartin Matuska 		}
294cdf63a70SMartin Matuska 	}
295cdf63a70SMartin Matuska 	if (need_restart)
296cdf63a70SMartin Matuska 		goto restart;
297cdf63a70SMartin Matuska 
298cdf63a70SMartin Matuska 	if (save_errno)
299cdf63a70SMartin Matuska 		errno = save_errno;
300cdf63a70SMartin Matuska 	return(nr == -1 ? NULL : buf);
301cdf63a70SMartin Matuska }
302cdf63a70SMartin Matuska #endif /* _WIN32 && !__CYGWIN__ */
303cdf63a70SMartin Matuska #endif /* HAVE_READPASSPHRASE */
304cdf63a70SMartin Matuska 
305cdf63a70SMartin Matuska char *
306cdf63a70SMartin Matuska lafe_readpassphrase(const char *prompt, char *buf, size_t bufsiz)
307cdf63a70SMartin Matuska {
308cdf63a70SMartin Matuska 	char *p;
309cdf63a70SMartin Matuska 
310cdf63a70SMartin Matuska 	p = readpassphrase(prompt, buf, bufsiz, RPP_ECHO_OFF);
311cdf63a70SMartin Matuska 	if (p == NULL) {
312cdf63a70SMartin Matuska 		switch (errno) {
313cdf63a70SMartin Matuska 		case EINTR:
314cdf63a70SMartin Matuska 			break;
315cdf63a70SMartin Matuska 		default:
316cdf63a70SMartin Matuska 			lafe_errc(1, errno, "Couldn't read passphrase");
317cdf63a70SMartin Matuska 			break;
318cdf63a70SMartin Matuska 		}
319cdf63a70SMartin Matuska 	}
320cdf63a70SMartin Matuska 	return (p);
321cdf63a70SMartin Matuska }
322cdf63a70SMartin Matuska 
323