diff options
-rw-r--r-- | sbin/mount_vnd/Makefile | 14 | ||||
-rw-r--r-- | sbin/mount_vnd/mount_vnd | 96 | ||||
-rw-r--r-- | sbin/mount_vnd/mount_vnd.8 | 202 | ||||
-rw-r--r-- | sbin/mount_vnd/mount_vnd.c | 346 | ||||
-rw-r--r-- | sbin/mount_vnd/pkcs5_pbkdf2.c | 253 | ||||
-rw-r--r-- | sbin/mount_vnd/pkcs5_pbkdf2.h | 47 |
6 files changed, 834 insertions, 124 deletions
diff --git a/sbin/mount_vnd/Makefile b/sbin/mount_vnd/Makefile index 33a7137f794..6b869d77050 100644 --- a/sbin/mount_vnd/Makefile +++ b/sbin/mount_vnd/Makefile @@ -1,9 +1,13 @@ -# $OpenBSD: Makefile,v 1.1 2007/04/14 11:54:00 grunk Exp $ +# $OpenBSD: Makefile,v 1.2 2007/05/26 03:37:45 grunk Exp $ -MAN=mount_vnd.8 +PROG= mount_vnd +SRCS= mount_vnd.c pkcs5_pbkdf2.c +LDADD= -lutil -lcrypto +DPADD= ${LIBUTIL} -beforeinstall: - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ - ${.CURDIR}/mount_vnd ${DESTDIR}${BINDIR}/mount_vnd +LINKS= ${BINDIR}/mount_vnd ${BINDIR}/vnconfig +MLINKS= mount_vnd.8 vnconfig.8 + +MAN= mount_vnd.8 .include <bsd.prog.mk> diff --git a/sbin/mount_vnd/mount_vnd b/sbin/mount_vnd/mount_vnd deleted file mode 100644 index ec0d6834c18..00000000000 --- a/sbin/mount_vnd/mount_vnd +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -# $OpenBSD: mount_vnd,v 1.2 2007/05/02 20:13:13 david Exp $ -# -# Copyright (c) 2005, 2006, 2007 David Krause <david@openbsd.org> -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -progname=`basename "$0"` -usage() { - cat 1>&2 <<-EOF - usage: $progname [-k] [-K rounds] [-o options] [-S saltfile] image node - EOF - exit 1 -} - -kflag= -ROUNDS= -SALTFILE= - -args=`getopt kK:o:S: $*` -if [ $? -ne 0 ]; then - usage -fi - -set -eu - -set -- $args -while [ $# -ge 0 ]; do - case "$1" in - -k) - kflag="$1"; shift;; - -K) - ROUNDS="$2"; shift; shift;; - -o) - # currently, no mount options have effect for vnd - shift; shift;; - -S) - SALTFILE="$2"; shift; shift;; - --) - shift; break;; - esac -done - -if [ $# -ne 2 ]; then - usage -fi - -IMAGE="$1" -VND="$2" - -if [ -n "${ROUNDS}" -a ! -n "${SALTFILE}" ]; then - SALTFILE="${IMAGE}.slt" -fi - -if [ -n "${ROUNDS}" -a -n "${kflag}" ]; then - echo "$progname: -k and -K are mutually exclusive" 1>&2 - exit 1 -elif [ -n "${SALTFILE}" -a ! -n "${ROUNDS}" ]; then - echo "$progname: -S only makes sense when used with -K" 1>&2 - exit 1 -elif [ ! -b "${IMAGE}" -a ! -f "${IMAGE}" ]; then - echo "$progname: ${IMAGE}: No such file or block device" 1>&2 - exit 1 -elif [ -n "${SALTFILE}" -a ! -f "${SALTFILE}" ]; then - echo "$progname: ${SALTFILE}: No such file" 1>&2 - exit 1 -elif [ ! -b "${VND}" ]; then - echo "$progname: ${VND}: No such block device" 1>&2 - exit 1 -fi - -vnconfig -l ${VND} > /dev/null -if vnconfig -l ${VND} | fgrep -q covering; then - echo "$progname: ${VND} is already in use" 1>&2 - exit 1 -fi - -echo "${IMAGE} on ${VND}" -if [ -n "${ROUNDS}" ]; then - vnconfig -K ${ROUNDS} -S ${SALTFILE} ${VND} ${IMAGE} -elif [ -n "${kflag}" ]; then - vnconfig -k ${VND} ${IMAGE} -else - vnconfig ${VND} ${IMAGE} -fi diff --git a/sbin/mount_vnd/mount_vnd.8 b/sbin/mount_vnd/mount_vnd.8 index 63f6884a6ed..86922ba49f9 100644 --- a/sbin/mount_vnd/mount_vnd.8 +++ b/sbin/mount_vnd/mount_vnd.8 @@ -1,4 +1,39 @@ -.\" $OpenBSD: mount_vnd.8,v 1.2 2007/04/14 13:17:24 jmc Exp $ +.\" $OpenBSD: mount_vnd.8,v 1.3 2007/05/26 03:37:45 grunk Exp $ +.\" +.\" Copyright (c) 1993 University of Utah. +.\" Copyright (c) 1980, 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Systems Programming Group of the University of Utah Computer +.\" Science Department. +.\" +.\" 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. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)vnconfig.8 8.1 (Berkeley) 6/5/93 +.\" .\" .\" Copyright (c) 2007 Alexander von Gernler <grunk@openbsd.org> .\" @@ -14,29 +49,74 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd April 11, 2007 +.Dd May 18, 2007 .Dt MOUNT_VND 8 .Os .Sh NAME -.Nm mount_vnd -.Nd configure a vnd image +.Nm mount_vnd , +.Nm vnconfig +.Nd "configure vnode disks for file swapping or pseudo file systems" .Sh SYNOPSIS .Nm mount_vnd +.Bk -words .Op Fl k .Op Fl K Ar rounds .Op Fl o Ar options .Op Fl S Ar saltfile .Ar image -.Ar node +.Ar vnd_dev +.Ek +.Nm vnconfig +.Bk -words +.Op Fl ckluv +.Op Fl K Ar rounds +.Op Fl S Ar saltfile +.Ar vnd_dev +.Ar image +.Ek .Sh DESCRIPTION The -.Nm -command configures an image file named +.Nm vnconfig +command configures vnode pseudo disk devices. +It will associate (or disassociate) the special file +.Ar rawdev +with the regular file +.Ar regular_file , +allowing the latter to be accessed as though it were a disk. +Hence a regular file within the file system can be used for swapping +or can contain a file system that is mounted in the name space. +.Pp +Both traditional devices, +.Xr vnd 4 , +and the cache-coherent devices, +.Pa svnd , +are configured through +.Nm vnconfig . +.Pa svnd +should be mounted with the +.Xr mount 8 +option +.Dq sync +if +.Ar regular_file +is being read from, +to ensure consistency in the buffer cache. +For normal operation this is not necessary. +.Pp +The +.Nm mount_vnd +works similarly to +.Nm vnconfig , +but it provides an interface that can be used by the +.Xr fstab 5 +infrastructure, so that an .Ar image -using -.Xr vnconfig 8 . +file can be configured to a device +.Ar node +while booting. .Pp -This command is invoked by +.Nm mount_vnd +is invoked by .Xr mount 8 when using the following syntax: .Bd -ragged -offset 4n @@ -47,18 +127,48 @@ when using the following syntax: .Pp The options are as follows: .Bl -tag -width Ds +.It Fl c +.Nm vnconfig +only. +Configures the device. +If successful, references to +.Ar rawdev +will access the contents of +.Ar regular_file . +This is the default operation. +.It Fl k +Associate an encryption key with the device. +All data will be encrypted using the Blowfish cipher before it is +written to the disk. +Encryption only works with +.Pa svnd . .It Fl K Ar rounds -Flag is passed on to -.Xr vnconfig 8 . -It is used to associate an encryption key using a salt file -and a specified number of +Associate an encryption key with the device. +All data will be encrypted using the Blowfish cipher before it is +written to the disk. +The user is asked for both a passphrase and the name of a salt file. +The salt file can also be specified on the command line using the +.Fl S +option. +The passphrase and salt are combined according to PKCS #5 PBKDF2 for the +specified number of +rounds to generate the actual key used. .Ar rounds -for PKCS #5 PBKDF2 with the vnd device. -.It Fl k -Flag is passed on to -.Xr vnconfig 8 . -It is used to associate an encryption key with the vnd device. +is a number between 1000 and +.Dv INT_MAX . +DO NOT LOSE THE SALT FILE. +Encryption only works with +.Pa svnd . +.It Fl l +.Nm vnconfig +only. +List the (s)vnd devices and indicate which ones are in use. +If a specific +.Ar rawdev +is given, then only that one will be described. .It Fl o Ar options +.Nm mount_vnd +only. Options are specified with a .Fl o flag followed by a comma separated string of options. @@ -71,16 +181,61 @@ At the moment, is only here for compatibility reasons, but no use is made of supplied options. .It Fl S Ar saltfile -Flag is passed on to -.Xr vnconfig 8 . -It is used to specify the name of the saltfile used with -.Fl K . +When +.Fl K +is used, specify the +.Pa saltfile . If the salt filename is not specified using .Fl S , it defaults to .Ar image Ns .slt . +.It Fl u +.Nm vnconfig +only. +Unconfigures a +.Ar rawdev . +.It Fl v +.Nm vnconfig +only. +Print messages to stdout describing actions taken. +.El +.Sh FILES +.Bl -tag -width /etc/rvnd?? -compact +.It Pa /dev/{,r}{,s}vnd* .El .Sh EXAMPLES +Configure a CD-ROM or DVD image file as vnode disk svnd0 +and mount the ISO 9660 file system contained in it: +.Bd -literal -offset indent +# vnconfig svnd0 /tmp/diskimage +# mount -t cd9660 /dev/svnd0c /mnt +.Ed +.Pp +Configure an encrypted image file as vnode disk svnd0 and mount the FFS +file system contained in it. +The encryption key does not echo and must be entered every time +the vnode disk is configured. +.Bd -literal -offset indent +# vnconfig -k svnd0 /tmp/cryptimg +Encryption key: +# mount /dev/svnd0c /mnt +.Ed +.Pp +Same as above, but now configure the vnode using PKCS #5 PBKDF2 and +a salt file with 20000 rounds: +.Bd -literal -offset indent +# vnconfig -K 20000 svnd0 /tmp/cryptimg +Encryption key: +Salt file: /tmp/cryptsalt +# mount /dev/svnd0c /mnt +.Ed +.Pp +Unmount the file system and unconfigure the vnode device: +.Bd -literal -offset indent +# umount /mnt +# vnconfig -u svnd0 +.Ed +.Pp Some possible vnd configurations for .Pa /etc/fstab are listed below. @@ -120,6 +275,7 @@ from checking the file system for the same reasons. .Xr vnd 4 , .Xr fstab 5 , .Xr mount 8 , +.Xr swapon 8 , .Xr umount 8 .Sh HISTORY The diff --git a/sbin/mount_vnd/mount_vnd.c b/sbin/mount_vnd/mount_vnd.c new file mode 100644 index 00000000000..19239cbbe7d --- /dev/null +++ b/sbin/mount_vnd/mount_vnd.c @@ -0,0 +1,346 @@ +/* $OpenBSD: mount_vnd.c,v 1.1 2007/05/26 03:37:45 grunk Exp $ */ +/* + * Copyright (c) 1993 University of Utah. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: Utah $Hdr: vnconfig.c 1.1 93/12/15$ + * + * @(#)vnconfig.c 8.1 (Berkeley) 12/15/93 + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include <sys/stat.h> + +#include <dev/vndioctl.h> + +#include <blf.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <util.h> + +#include "pkcs5_pbkdf2.h" + +#define DEFAULT_VND "vnd0" + +#define VND_CONFIG 1 +#define VND_UNCONFIG 2 +#define VND_GET 3 + +int verbose = 0; +int run_mount_vnd = 0; + +__dead void usage(void); +int config(char *, char *, int, char *, size_t); +int getinfo(const char *); +char *get_pkcs_key(char *, char *); + +int +main(int argc, char **argv) +{ + int ch, rv, action, opt_c, opt_k, opt_K, opt_l, opt_u; + char *key, *mntopts, *rounds, *saltopt; + size_t keylen = 0; + extern char *__progname; + + if (strcasecmp(__progname, "mount_vnd") == 0) + run_mount_vnd = 1; + + opt_c = opt_k = opt_K = opt_l = opt_u = 0; + key = mntopts = rounds = saltopt = NULL; + action = VND_CONFIG; + + while ((ch = getopt(argc, argv, "ckK:lo:S:uv")) != -1) { + switch (ch) { + case 'c': + opt_c = 1; + break; + case 'k': + opt_k = 1; + break; + case 'K': + opt_K = 1; + rounds = optarg; + break; + case 'l': + opt_l = 1; + break; + case 'o': + mntopts = optarg; + break; + case 'S': + saltopt = optarg; + break; + case 'u': + opt_u = 1; + break; + case 'v': + verbose = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (opt_c + opt_l + opt_u > 1) + errx(1, "-c, -l and -u are mutually exclusive options"); + + if (opt_l) + action = VND_GET; + else if (opt_u) + action = VND_UNCONFIG; + else + action = VND_CONFIG; /* default behavior */ + + if (saltopt && (!opt_K)) + errx(1, "-S only makes sense when used with -K"); + + if (action == VND_CONFIG && argc == 2) { + int ind_raw, ind_reg; + + if (opt_k) { + if (opt_K) + errx(1, "-k and -K are mutually exclusive"); + key = getpass("Encryption key: "); + if (key == NULL || (keylen = strlen(key)) == 0) + errx(1, "Need an encryption key"); + } else if (opt_K) { + key = get_pkcs_key(rounds, saltopt); + keylen = BLF_MAXUTILIZED; + } + + /* fix order of arguments. */ + if (run_mount_vnd) { + ind_raw = 1; + ind_reg = 0; + } else { + ind_raw = 0; + ind_reg = 1; + } + rv = config(argv[ind_raw], argv[ind_reg], action, key, keylen); + } else if (action == VND_UNCONFIG && argc == 1) + rv = config(argv[0], NULL, action, NULL, 0); + else if (action == VND_GET) + rv = getinfo(argc ? argv[0] : NULL); + else + usage(); + + exit(rv); +} + +char * +get_pkcs_key(char *arg, char *saltopt) +{ + char keybuf[128], saltbuf[128], saltfilebuf[PATH_MAX]; + char *saltfile; + char *key = NULL; + const char *errstr; + int rounds; + + rounds = strtonum(arg, 1000, INT_MAX, &errstr); + if (errstr) + err(1, "rounds: %s", errstr); + key = getpass("Encryption key: "); + if (!key || strlen(key) == 0) + errx(1, "Need an encryption key"); + strncpy(keybuf, key, sizeof(keybuf)); + if (saltopt) + saltfile = saltopt; + else { + printf("Salt file: "); + fflush(stdout); + saltfile = fgets(saltfilebuf, sizeof(saltfilebuf), stdin); + } + if (!saltfile || saltfile[0] == '\n') { + warnx("Skipping salt file, insecure"); + saltfile = NULL; + } else { + size_t len = strlen(saltfile); + if (saltfile[len - 1] == '\n') + saltfile[len - 1] = 0; + } + if (saltfile) { + int fd; + + fd = open(saltfile, O_RDONLY); + if (fd == -1) { + int *s; + + fprintf(stderr, "Salt file not found, attempting to create one\n"); + fd = open(saltfile, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd == -1) + err(1, "Unable to create salt file: '%s'", + saltfile); + for (s = (int *)saltbuf; + s < (int *)(saltbuf + sizeof(saltbuf)); s++) + *s = arc4random(); + if (write(fd, saltbuf, sizeof(saltbuf)) + != sizeof(saltbuf)) + err(1, "Unable to write salt file: '%s'", saltfile); + fprintf(stderr, "Salt file created as '%s'\n", saltfile); + } else { + if (read(fd, saltbuf, sizeof(saltbuf)) + != sizeof(saltbuf)) + err(1, "Unable to read salt file: '%s'", saltfile); + } + close(fd); + } else { + memset(saltbuf, 0, sizeof(saltbuf)); + } + if (pkcs5_pbkdf2((u_int8_t**)&key, BLF_MAXUTILIZED, keybuf, + sizeof(keybuf), saltbuf, sizeof(saltbuf), rounds, 0)) + errx(1, "pkcs5_pbkdf2 failed"); + + return (key); +} + +int +getinfo(const char *vname) +{ + int vd, print_all = 0; + struct vnd_user vnu; + + if (vname == NULL) { + vname = DEFAULT_VND; + print_all = 1; + } + + vd = opendev((char *)vname, O_RDONLY, OPENDEV_PART, NULL); + if (vd < 0) + err(1, "open: %s", vname); + + vnu.vnu_unit = -1; + +query: + if (ioctl(vd, VNDIOCGET, &vnu) == -1) { + if (print_all && errno == ENXIO && vnu.vnu_unit > 0) { + close(vd); + return (0); + } else { + err(1, "ioctl: %s", vname); + } + } + + fprintf(stdout, "vnd%d: ", vnu.vnu_unit); + + if (!vnu.vnu_ino) + fprintf(stdout, "not in use\n"); + else + fprintf(stdout, "covering %s on %s, inode %d\n", vnu.vnu_file, + devname(vnu.vnu_dev, S_IFBLK), vnu.vnu_ino); + + if (print_all) { + vnu.vnu_unit++; + goto query; + } + + close(vd); + + return (0); +} + +int +config(char *dev, char *file, int action, char *key, size_t keylen) +{ + struct vnd_ioctl vndio; + FILE *f; + char *rdev; + int rv; + + if (opendev(dev, O_RDONLY, OPENDEV_PART, &rdev) < 0) + err(4, "%s", rdev); + f = fopen(rdev, "r"); + if (f == NULL) { + warn("%s", rdev); + rv = -1; + goto out; + } + vndio.vnd_file = file; + vndio.vnd_key = (u_char *)key; + vndio.vnd_keylen = keylen; + + /* + * Clear (un-configure) the device + */ + if (action == VND_UNCONFIG) { + rv = ioctl(fileno(f), VNDIOCCLR, &vndio); + if (rv) + warn("VNDIOCCLR"); + else if (verbose) + printf("%s: cleared\n", dev); + } + /* + * Configure the device + */ + if (action == VND_CONFIG) { + rv = ioctl(fileno(f), VNDIOCSET, &vndio); + if (rv) + warn("VNDIOCSET"); + else if (verbose) + printf("%s: %llu bytes on %s\n", dev, vndio.vnd_size, + file); + } + + fclose(f); + fflush(stdout); + out: + if (key) + memset(key, 0, keylen); + return (rv < 0); +} + +__dead void +usage(void) +{ + extern char *__progname; + + if (run_mount_vnd) + (void)fprintf(stderr, + "usage: %s [-ckluv] [-o mntopts] [-K rounds] " + "[-S saltfile] image vnd_dev\n", __progname); + else + (void)fprintf(stderr, + "usage: %s [-ckluv] [-K rounds] [-S saltfile] vnd_dev " + "image\n", __progname); + + exit(1); +} diff --git a/sbin/mount_vnd/pkcs5_pbkdf2.c b/sbin/mount_vnd/pkcs5_pbkdf2.c new file mode 100644 index 00000000000..b88ee815b8e --- /dev/null +++ b/sbin/mount_vnd/pkcs5_pbkdf2.c @@ -0,0 +1,253 @@ +/* $NetBSD: pkcs5_pbkdf2.c,v 1.5 2004/03/17 01:29:13 dan Exp $ */ + +/*- + * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Roland C. Dowdeswell. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * This code is an implementation of PKCS #5 PBKDF2 which is described + * in: + * + * ``PKCS #5 v2.0: Password-Based Cryptography Standard'', RSA Laboratories, + * March 25, 1999. + * + * and can be found at the following URL: + * + * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/ + * + * It was also republished as RFC 2898. + */ + + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include <openssl/hmac.h> + +#include "pkcs5_pbkdf2.h" + +static void int_encode(u_int8_t *, int); +static void prf_iterate(u_int8_t *, const u_int8_t *, int, + const u_int8_t *, int, int, int); +static int pkcs5_pbkdf2_time(int, int); + +void +memxor(void *res, const void *src, size_t len) +{ + int i; + char *r; + const char *s; + + r = res; + s = src; + for (i=0; i < len; i++) + r[i] ^= s[i]; +} + +#define PRF_BLOCKLEN 20 + +/* + * int_encode encodes i as a four octet integer, most significant + * octet first. (from the end of Step 3). + */ + +static void +int_encode(u_int8_t *res, int i) +{ + + *res++ = (i >> 24) & 0xff; + *res++ = (i >> 16) & 0xff; + *res++ = (i >> 8) & 0xff; + *res = (i ) & 0xff; +} + +static void +prf_iterate(u_int8_t *r, const u_int8_t *P, int Plen, + const u_int8_t *S, int Slen, int c, int ind) +{ + int first_time = 1; + int i; + int datalen; + int tmplen; + u_int8_t *data; + u_int8_t tmp[EVP_MAX_MD_SIZE]; + + data = malloc(Slen + 4); + if (!data) + err(1, "prf_iterate"); + memcpy(data, S, Slen); + int_encode(data + Slen, ind); + datalen = Slen + 4; + + for (i=0; i < c; i++) { + HMAC(EVP_sha1(), P, Plen, data, datalen, tmp, &tmplen); + + assert(tmplen == PRF_BLOCKLEN); + + if (first_time) { + memcpy(r, tmp, PRF_BLOCKLEN); + first_time = 0; + } else + memxor(r, tmp, PRF_BLOCKLEN); + memcpy(data, tmp, PRF_BLOCKLEN); + datalen = PRF_BLOCKLEN; + } + free(data); +} + +/* + * pkcs5_pbkdf2 takes all of its lengths in bytes. + */ + +int +pkcs5_pbkdf2(u_int8_t **r, int dkLen, const u_int8_t *P, int Plen, + const u_int8_t *S, int Slen, int c, int compat) +{ + int i; + int l; + + /* sanity */ + if (!r) + return -1; + if (dkLen <= 0) + return -1; + if (c < 1) + return -1; + + /* Step 2 */ + l = (dkLen + PRF_BLOCKLEN - 1) / PRF_BLOCKLEN; + + /* allocate the output */ + *r = malloc(l * PRF_BLOCKLEN); + if (!*r) + return -1; + + /* Step 3 */ + for (i=0; i < l; i++) + prf_iterate(*r + (PRF_BLOCKLEN * i), P, Plen, S, Slen, c, + (compat?i:i+1)); + + /* Step 4 and 5 + * by the structure of the code, we do not need to concatenate + * the blocks, they're already concatenated. We do not extract + * the first dkLen octets, since we [naturally] assume that the + * calling function will use only the octets that it needs and + * the free(3) will free all of the allocated memory. + */ + return 0; +} + +/* + * We use predefined lengths for the password and salt to ensure that + * no analysis can be done on the output of the calibration based on + * those parameters. We do not do the same for dkLen because: + * 1. dkLen is known to the attacker if they know the iteration + * count, and + * 2. using the wrong dkLen will skew the calibration by an + * integral factor n = (dkLen / 160). + */ + +#define CAL_PASSLEN 64 +#define CAL_SALTLEN 64 +#define CAL_TIME 30000 /* Minimum number of microseconds that + * are considered significant. + */ + +/* + * We return the user time in milliseconds that c iterations + * of the algorithm take. + */ + +static int +pkcs5_pbkdf2_time(int dkLen, int c) +{ + struct rusage start; + struct rusage end; + int ret; + u_int8_t *r = NULL; + u_int8_t P[CAL_PASSLEN]; + u_int8_t S[CAL_SALTLEN]; + + getrusage(RUSAGE_SELF, &start); + /* XXX compat flag at end to be removed when _OLD keygen method is */ + ret = pkcs5_pbkdf2(&r, dkLen, P, sizeof(P), S, sizeof(S), c, 0); + if (ret) + return ret; + getrusage(RUSAGE_SELF, &end); + free(r); + + return (end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000 + + (end.ru_utime.tv_usec - start.ru_utime.tv_usec); +} + +int +pkcs5_pbkdf2_calibrate(int dkLen, int milliseconds) +{ + int c; + int t = 0; + int ret; + + /* + * First we get a meaningfully long time by doubling the + * iteration count until it takes longer than CAL_TIME. This + * should take approximately 2 * CAL_TIME. + */ + for (c=1;; c *= 2) { + t = pkcs5_pbkdf2_time(dkLen, c); + if (t > CAL_TIME) + break; + } + + /* Now that we know that, we scale it. */ + ret = (int) ((u_int64_t) c * milliseconds / t); + + /* + * Since it is quite important to not get this wrong, + * we test the result. + */ + + t = pkcs5_pbkdf2_time(dkLen, 10000); + + /* if we are over 5% off, return an error */ + if (abs(milliseconds - t) > (milliseconds / 20)) + return -1; + + return ret; +} diff --git a/sbin/mount_vnd/pkcs5_pbkdf2.h b/sbin/mount_vnd/pkcs5_pbkdf2.h new file mode 100644 index 00000000000..443e3e4298c --- /dev/null +++ b/sbin/mount_vnd/pkcs5_pbkdf2.h @@ -0,0 +1,47 @@ +/* $NetBSD: pkcs5_pbkdf2.h,v 1.3 2004/03/17 01:29:13 dan Exp $ */ + +/*- + * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Roland C. Dowdeswell. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef PKCS5_PBKDF2_H +#define PKCS5_PBKDF2_H + +__BEGIN_DECLS +int pkcs5_pbkdf2(u_int8_t **, int, const u_int8_t *, int, + const u_int8_t *, int, int, int); +int pkcs5_pbkdf2_calibrate(int, int); +__END_DECLS +#endif |