PERFORCE change 166896 for review

Gleb Kurtsou gk at FreeBSD.org
Sat Aug 1 18:38:23 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166896

Change 166896 by gk at gk_h1 on 2009/08/01 18:37:48

	Implement changing directory key (pefs setkey)
	Implement key chaining
	Fix vop_link: forbid creation of link to unencrypted file, use same tweak and key for created link

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#2 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#2 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.c#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.h#1 add
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_mount.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#5 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#8 edit

Differences ...

==== //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#2 (text+ko) ====

@@ -5,7 +5,7 @@
 .PATH:	${MOUNT} ${SYS}/geom/eli ${SYS}/crypto/sha2
 
 PROG=	pefs
-SRCS=	pefs_ctl.c pefs_mount.c pefs_key.c
+SRCS=	pefs_ctl.c pefs_key.c pefs_keychain.c pefs_mount.c
 SRCS+=	getmntopts.c
 SRCS+=	g_eli_crypto.c pkcs5v2.c sha2.c
 

==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#2 (text+ko) ====

@@ -29,6 +29,8 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <assert.h>
+#include <ctype.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,6 +44,7 @@
 #include <fs/pefs/pefs.h>
 
 #include "pefs_ctl.h"
+#include "pefs_keychain.h"
 
 #define PATH_UMOUNT		"/sbin/umount"
 
@@ -50,9 +53,14 @@
 static int	pefs_setkey(int argc, char *argv[]);
 static int	pefs_delkey(int argc, char *argv[]);
 static int	pefs_flushkeys(int argc, char *argv[]);
-static int	pefs_status(int argc, char *argv[]);
+static int	pefs_setchain(int argc, char *argv[]);
+static int	pefs_delchain(int argc, char *argv[]);
+static int	pefs_randomchain(int argc, char *argv[]);
+static int	pefs_showkeys(int argc, char *argv[]);
+static int	pefs_showchain(int argc, char *argv[]);
 
 typedef int (*command_func_t)(int argc, char **argv);
+typedef int (*keyop_func_t)(struct pefs_keychain *kc, int fd);
 
 struct command {
 	const char *name;
@@ -67,88 +75,237 @@
 	{ "setkey", pefs_setkey },
 	{ "delkey", pefs_delkey },
 	{ "flushkeys", pefs_flushkeys },
-	{ "status", pefs_status },
+	{ "showkeys", pefs_showkeys },
+	{ "status", pefs_showkeys },
+	{ "randomchain", pefs_randomchain },
+	{ "setchain", pefs_setchain },
+	{ "delchain", pefs_delchain },
+	{ "showchain", pefs_showchain },
 	{ NULL, NULL },
 };
 
 static int
-pefs_addkey(int argc, char *argv[])
+checkargs_fs(int argc, char **argv __unused)
+{
+	if (argc != 1) {
+		if (argc == 0)
+			warnx("missing filesystem argument");
+		else
+			warnx("too many arguments");
+		return (0);
+	}
+
+	return (1);
+}
+
+uintmax_t
+pefs_keyid_as_int(char *keyid)
+{
+	uintmax_t r;
+	int i;
+
+	assert(sizeof(uintmax_t) >= PEFS_KEYID_SIZE);
+	for (i = 0, r = 0; i < PEFS_KEYID_SIZE; i++) {
+		if (i)
+			r <<= 8;
+		r |= keyid[i] & 0xff;
+	}
+
+	return (r);
+}
+
+static inline void
+pefs_key_show(struct pefs_xkey *xk, int ind)
+{
+	printf("\t%-4d %016jx %s\n", ind, pefs_keyid_as_int(xk->pxk_keyid), pefs_alg_name(xk->pxk_alg));
+}
+
+static int
+pefs_keyop(keyop_func_t func, int argc, char *argv[])
 {
 	struct pefs_xkey k;
-	int error, fd;
+	struct pefs_keychain *kc;
+	struct pefs_keyparam kp;
+	int error, fd, i;
+	int chain = PEFS_KEYCHAIN_IGNORE_MISSING;
 
-	error = pefs_get_key(&k, &argc, argv);
-	if (error != 0)
-		return (error);
+	pefs_keyparam_init(&kp);
+	while ((i = getopt(argc, argv, "pcCa:i:k:")) != -1)
+		switch(i) {
+		case 'a':
+			kp.kp_alg = optarg;
+			break;
+		case 'c':
+			chain = PEFS_KEYCHAIN_USE;
+			break;
+		case 'C':
+			chain = 0;
+			break;
+		case 'p':
+			kp.kp_nopassphrase = 1;
+			break;
+		case 'i':
+			kp.kp_iterations = atoi(optarg);
+			if (kp.kp_iterations <= 0) {
+				warnx("invalid iterations argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'k':
+			kp.kp_keyfile = optarg;
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
 
-	if (argc != 1) {
+	if (!checkargs_fs(argc, argv)) {
 		bzero(&k, sizeof(k));
-		if (argc == 0)
-			warnx("missing filesystem argument");
-		else if (getopt(argc, argv, "") == -1)
-			warnx("too many arguments");
 		pefs_usage();
 	}
 
+	error = pefs_key_get(&k, NULL, 0, &kp);
+	if (error != 0)
+		return (error);
+
+	kc = pefs_keychain_get(argv[0], chain, &k);
+	bzero(&k, sizeof(k));
+	if (kc == NULL) {
+		return (EX_DATAERR);
+	}
 	fd = open(argv[0], O_RDONLY);
 	if (fd == -1) {
-		bzero(&k, sizeof(k));
 		err(EX_IOERR, "cannot open %s", argv[0]);
 	}
-	if (ioctl(fd, PEFS_ADDKEY, &k) == -1) {
-		bzero(&k, sizeof(k));
-		err(EX_IOERR, "cannot add key");
+	
+	error = func(kc, fd);
+
+	pefs_keychain_free(kc);
+
+	close(fd);
+
+	return (error);
+}
+
+static int
+pefs_addkey_op(struct pefs_keychain *kc, int fd)
+{
+	for (; kc; kc = kc->kc_next) {
+		if (ioctl(fd, PEFS_ADDKEY, &kc->kc_key) == -1) {
+			warn("cannot add key");
+			return (-1);
+		}
 	}
-	bzero(&k, sizeof(k));
-	close(fd);
 
 	return (0);
 }
 
 static int
-pefs_setkey(int argc __unused, char *argv[] __unused)
+pefs_delkey_op(struct pefs_keychain *kc, int fd)
 {
-	pefs_usage();
+	for (; kc; kc = kc->kc_next) {
+		if (ioctl(fd, PEFS_DELKEY, &kc->kc_key) == -1) {
+			warn("cannot delete key");
+		}
+	}
 
 	return (0);
 }
 
 static int
+pefs_addkey(int argc, char *argv[])
+{
+	return (pefs_keyop(pefs_addkey_op, argc, argv));
+}
+
+static int
 pefs_delkey(int argc, char *argv[])
 {
+	return (pefs_keyop(pefs_delkey_op, argc, argv));
+}
+
+static int
+pefs_setkey(int argc, char *argv[])
+{
 	struct pefs_xkey k;
-	int error, fd;
+	struct pefs_keychain *kc;
+	struct pefs_keyparam kp;
+	int error, fd, i;
+	int addkey = 0;
+	int chain = PEFS_KEYCHAIN_IGNORE_MISSING;
+
+	pefs_keyparam_init(&kp);
+	while ((i = getopt(argc, argv, "xpcCa:i:k:")) != -1)
+		switch(i) {
+		case 'x':
+			addkey = 1;
+			break;
+		case 'a':
+			kp.kp_alg = optarg;
+			break;
+		case 'c':
+			chain = PEFS_KEYCHAIN_USE;
+			break;
+		case 'C':
+			chain = 0;
+			break;
+		case 'p':
+			kp.kp_nopassphrase = 1;
+			break;
+		case 'i':
+			kp.kp_iterations = atoi(optarg);
+			if (kp.kp_iterations <= 0) {
+				warnx("invalid iterations argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'k':
+			kp.kp_keyfile = optarg;
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
 
-	error = pefs_get_key(&k, &argc, argv);
-	if (error != 0)
-		return (error);
+	if (chain == PEFS_KEYCHAIN_USE && addkey)
+		errx(EX_USAGE, "invalid arguments: -x -c");
 
-	bzero(k.pxk_key, PEFS_KEY_SIZE);
 	if (argc != 1) {
-		bzero(&k, sizeof(k));
 		if (argc == 0)
-			warnx("missing filesystem argument");
-		else if (getopt(argc, argv, "") == -1)
+			warnx("missing directory argument");
+		else
 			warnx("too many arguments");
+		bzero(&k, sizeof(k));
 		pefs_usage();
 	}
 
+	error = pefs_key_get(&k, NULL, 0, &kp);
+	if (error != 0)
+		return (error);
+
+	kc = pefs_keychain_get(argv[0], chain, &k);
+	if (kc == NULL) {
+		return (EX_DATAERR);
+	}
+	pefs_keychain_free(kc);
+
+	bzero(k.pxk_key, PEFS_KEY_SIZE);
+
 	fd = open(argv[0], O_RDONLY);
 	if (fd == -1) {
-		bzero(&k, sizeof(k));
 		err(EX_IOERR, "cannot open %s", argv[0]);
 	}
-	if (ioctl(fd, PEFS_DELKEY, &k) == -1) {
-		bzero(&k, sizeof(k));
-		err(EX_IOERR, "cannot delete key");
+	
+	if (ioctl(fd, PEFS_SETKEY, &k) == -1) {
+		warn("cannot set key");
+		error = EX_OSERR;
 	}
-	bzero(&k, sizeof(k));
+
 	close(fd);
 
-	return (0);
-	pefs_usage();
-
-	return (0);
+	return (error);
 }
 
 static int
@@ -156,11 +313,7 @@
 {
 	int fd;
 
-	if (argc != 1) {
-		if (argc == 0)
-			warnx("missing filesystem argument");
-		else if (getopt(argc, argv, "") == -1)
-			warnx("too many arguments");
+	if (!checkargs_fs(argc, argv)) {
 		pefs_usage();
 	}
 
@@ -177,17 +330,22 @@
 }
 
 static int
-pefs_status(int argc, char *argv[])
+pefs_showkeys(int argc, char *argv[])
 {
 	struct pefs_xkey k;
-	char buf[PEFS_KEYID_SIZE * 2 + 1];
-	int fd, i;
+	int chain, fd, i;
+
+	chain = 1;
+	while ((i = getopt(argc, argv, "")) != -1)
+		switch(i) {
+		case '?':
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
 
-	if (argc != 1) {
-		if (argc == 0)
-			warnx("missing filesystem argument");
-		else if (getopt(argc, argv, "") == -1)
-			warnx("too many arguments");
+	if (!checkargs_fs(argc, argv)) {
 		pefs_usage();
 	}
 
@@ -205,11 +363,7 @@
 	} else {
 		printf("Keys:\n");
 		while (1) {
-			for (i = 0; i < PEFS_KEYID_SIZE; i++) {
-				snprintf(buf + i * 2, sizeof(buf) - i * 2, "%02x", 
-				    k.pxk_keyid[i] & 0xff);
-			}
-			printf("\t%-4d %16s %s\n", k.pxk_index, buf, pefs_alg_name(k.pxk_alg));
+			pefs_key_show(&k, k.pxk_index);
 			k.pxk_index++;
 			if (ioctl(fd, PEFS_GETKEY, &k) == -1)
 				break;
@@ -217,6 +371,9 @@
 	}
 	close(fd);
 
+	if (chain) {
+	}
+
 	return (0);
 }
 
@@ -235,14 +392,13 @@
 		default:
 			pefs_usage();
 		}
-	if (argc - optind == 0) {
-		warnx("missing filesystem argument");
+	argc -= optind;
+	argv += optind;
+	
+	if (!checkargs_fs(argc, argv)) {
 		pefs_usage();
 	}
-	if (argc - optind > 1) {
-		warnx("too many arguments");
-		pefs_usage();
-	}
+
 	nargv = malloc((argc + 2) * sizeof(*nargv));
 	for (i = 0; i < argc; i++)
 		nargv[i + 1] = argv[i];
@@ -251,19 +407,236 @@
 
 	if (execv(PATH_UMOUNT, nargv) == -1)
 		errx(EX_OSERR, "exec %s", PATH_UMOUNT);
+
+	return (0);
+}
+
+static int
+pefs_setchain(int argc, char *argv[])
+{
+	struct pefs_keychain *kc, *kci;
+	struct {
+		struct pefs_xkey k;
+		struct pefs_keyparam kp;
+	} p[2];
+	struct pefs_xkey *k1 = &p[0].k, *k2 = &p[1].k;
+	int error, i;
+
+	pefs_keyparam_init(&p[0].kp);
+	pefs_keyparam_init(&p[1].kp);
+	while ((i = getopt(argc, argv, "pPa:A:i:I:k:K:")) != -1)
+		switch(i) {
+		case 'a':
+		case 'A':
+			p[isupper(i) ? 1 : 0].kp.kp_alg = optarg;
+			break;
+		case 'p':
+		case 'P':
+			p[isupper(i) ? 1 : 0].kp.kp_nopassphrase = 1;
+			break;
+		case 'i':
+		case 'I':
+			if ((p[isupper(i) ? 1 : 0].kp.kp_iterations = atoi(optarg)) <= 0) {
+				warnx("invalid iterations argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'k':
+		case 'K':
+			p[isupper(i) ? 1 : 0].kp.kp_keyfile = optarg;
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+
+	if (!checkargs_fs(argc, argv)) {
+		bzero(p, sizeof(p));
+		pefs_usage();
+	}
+
+	error = pefs_key_get(k1, "parent key passphrase", 1, &p[0].kp);
+	if (error != 0) {
+		bzero(p, sizeof(p));
+		return (error);
+	}
+	error = pefs_key_get(k2, "chained key passphrase", 1, &p[1].kp);
+	if (error != 0) {
+		bzero(p, sizeof(p));
+		return (error);
+	}
+
+	kc = pefs_keychain_get(argv[0], PEFS_KEYCHAIN_IGNORE_MISSING, k1);
+	for (kci = kc; kci; kci = kci->kc_next) {
+		if (memcmp(k2->pxk_keyid, kci->kc_key.pxk_keyid, PEFS_KEYID_SIZE) == 0) {
+			pefs_keychain_free(kc);
+			bzero(k1->pxk_key, PEFS_KEY_SIZE);
+			bzero(k2->pxk_key, PEFS_KEY_SIZE);
+			errx(EX_DATAERR, "key chain is already set: %016jx -> %016jx",
+			    pefs_keyid_as_int(k1->pxk_keyid),
+			    pefs_keyid_as_int(k2->pxk_keyid));
+		}
+	}
+	if (kc->kc_next != NULL) {
+		bzero(k1->pxk_key, PEFS_KEY_SIZE);
+		bzero(k2->pxk_key, PEFS_KEY_SIZE);
+		warnx("key chain for parent key is already set: %016jx -> %016jx",
+		    pefs_keyid_as_int(kc->kc_key.pxk_keyid),
+		    pefs_keyid_as_int(kc->kc_next->kc_key.pxk_keyid));
+		pefs_keychain_free(kc);
+		exit(EX_DATAERR);
+	}
+
+	error = pefs_keychain_set(argv[0], k1, k2);
+	if (error)
+		return (EX_DATAERR);
+
 	return (0);
 }
 
+static int
+pefs_delchain(int argc, char *argv[])
+{
+	struct pefs_xkey k;
+	struct pefs_keyparam kp;
+	struct pefs_keychain *kc, *kci;
+	int error, i;
+	int force = 0;
+
+	pefs_keyparam_init(&kp);
+	while ((i = getopt(argc, argv, "fpa:i:k:")) != -1)
+		switch(i) {
+		case 'f':
+			force = 1;
+			break;
+		case 'a':
+			kp.kp_alg = optarg;
+			break;
+		case 'p':
+			kp.kp_nopassphrase = 1;
+			break;
+		case 'i':
+			kp.kp_iterations = atoi(optarg);
+			if (kp.kp_iterations <= 0) {
+				warnx("invalid iterations argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'k':
+			kp.kp_keyfile = optarg;
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (!checkargs_fs(argc, argv)) {
+		pefs_usage();
+	}
+
+	error = pefs_key_get(&k, NULL, 0, &kp);
+	if (error != 0)
+		return (error);
+
+	kc = pefs_keychain_get(argv[0], PEFS_KEYCHAIN_USE, &k);
+	if (kc == NULL) {
+		bzero(&k, sizeof(k));
+		return (EX_DATAERR);
+	}
+
+	for (kci = kc; kci != NULL && kci->kc_next != NULL; kci = kci->kc_next) {
+		pefs_keychain_del(argv[0], &kci->kc_key);
+		if (!force)
+			break;
+	}
+	pefs_keychain_free(kc);
+
+	return (0);
+}
+
+static int
+pefs_showchain(int argc, char *argv[])
+{
+	struct pefs_xkey k;
+	struct pefs_keyparam kp;
+	struct pefs_keychain *kc, *kci;
+	int error, i;
+
+	pefs_keyparam_init(&kp);
+	while ((i = getopt(argc, argv, "pa:i:k:")) != -1)
+		switch(i) {
+		case 'a':
+			kp.kp_alg = optarg;
+			break;
+		case 'p':
+			kp.kp_nopassphrase = 1;
+			break;
+		case 'i':
+			kp.kp_iterations = atoi(optarg);
+			if (kp.kp_iterations <= 0) {
+				warnx("invalid iterations argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'k':
+			kp.kp_keyfile = optarg;
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (!checkargs_fs(argc, argv)) {
+		pefs_usage();
+	}
+
+	error = pefs_key_get(&k, NULL, 0, &kp);
+	if (error != 0)
+		return (error);
+
+	kc = pefs_keychain_get(argv[0], PEFS_KEYCHAIN_USE, &k);
+	if (kc == NULL) {
+		bzero(&k, sizeof(k));
+		return (EX_DATAERR);
+	}
+
+	printf("Key chain:\n");
+	bzero(&k, sizeof(k));
+	for (i = 1, kci = kc; kci != NULL; i++, kci = kci->kc_next) {
+		pefs_key_show(&kci->kc_key, i);
+	}
+	pefs_keychain_free(kc);
+
+	return (0);
+}
+
+static int
+pefs_randomchain(int argc __unused, char *argv[] __unused)
+{
+	return (0);
+}
+
+
 void
 pefs_usage(void)
 {
 	fprintf(stderr, "usage:	pefs mount [-o options] target filesystem\n"
 			"	pefs unmount [-fv] filesystem\n"
-			"	pefs addkey [-p] [-a alg] [-i iterations] [-k keyfile] filesystem\n"
-			"	pefs setkey [-cp] [-a alg] [-i iterations] [-k keyfile] directory\n"
-			"	pefs delkey [-p] [-a alg] [-i iterations] [-k keyfile] filesystem\n"
+			"	pefs addkey [-cCp] [-a alg] [-i iterations] [-k keyfile] filesystem\n"
+			"	pefs setkey [-xcCp] [-a alg] [-i iterations] [-k keyfile] directory\n"
+			"	pefs delkey [-cCp] [-a alg] [-i iterations] [-k keyfile] filesystem\n"
 			"	pefs flushkeys filesystem\n"
-			"	pefs status filesystem\n");
+			"	pefs setchain [-pP] [-a alg] [-i iterations] [-k keyfile]\n"
+			"		[-A alg] [-I iterations] [-K keyfile] filesystem\n"
+			"	pefs delchain [-pP] [-a alg] [-i iterations] [-k keyfile]\n"
+			"		[-A alg] [-I iterations] [-K keyfile] filesystem\n"
+			"	pefs showchain [-a alg] [-n min] [-N max] filesystem\n"
+			"	pefs randomchain [-a alg] [-n min] [-N max] filesystem\n"
+			"	pefs showkeys filesystem\n");
 	exit(EX_USAGE);
 }
 

==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#2 (text+ko) ====

@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2009 Gleb Kurtsou. All rights reserved.
+ * Copyright (c) 2009 Gleb Kurtsou <gk at FreeBSD.org>
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -24,16 +25,33 @@
  *
  * $FreeBSD$
  */
-
 #define PEFS_ALG_DEFAULT		PEFS_ALG_SALSA20
 
 #define PEFS_KDF_ITERATIONS		50000
 
 struct pefs_xkey;
 
+struct pefs_keyparam {
+	int kp_nopassphrase;
+	int kp_iterations;
+	char *kp_keyfile;
+	char *kp_alg;
+};
+
+static inline void
+pefs_keyparam_init(struct pefs_keyparam *kp)
+{
+	kp->kp_nopassphrase = 0;
+	kp->kp_iterations = PEFS_KDF_ITERATIONS;
+	kp->kp_keyfile = NULL;
+	kp->kp_alg = NULL;
+}
+
 void	pefs_usage(void);
-int	pefs_get_key(struct pefs_xkey *xk, int *pargc, char *argv[]);
+int	pefs_key_get(struct pefs_xkey *xk, const char *prompt, int verify,
+    struct pefs_keyparam *kp);
 int	pefs_mount(int argc, char *argv[]);
 int	pefs_mount_prog(int argc, char *argv[]);
+uintmax_t	pefs_keyid_as_int(char *keyid);
 const char *	pefs_alg_name(int alg_id);
 

==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#2 (text+ko) ====

@@ -44,6 +44,8 @@
 
 #include "pefs_ctl.h"
 
+#define PEFS_KEY_PROMPT_DEFAULT			"passphrase"
+
 struct algorithm {
 	const char *name;
 	int id;
@@ -68,95 +70,76 @@
 }
 
 int
-pefs_get_key(struct pefs_xkey *xk, int *pargc, char *argv[])
+pefs_key_get(struct pefs_xkey *xk, const char *prompt, int verify, struct pefs_keyparam *kp)
 {
 	struct hmac_ctx ctx;
 	struct algorithm *alg;
-	char buf[BUFSIZ], *p;
-	char *keyfile = NULL;
+	char promptbuf[64], buf[BUFSIZ], buf2[BUFSIZ], *p;
 	ssize_t done;
-	int nopassphrase = 0;
-	int iterations = PEFS_KDF_ITERATIONS;
-	int i, fd, xargc = 0, orig_opterr;
+	int fd, i;
 
 	xk->pxk_index = -1;
 	xk->pxk_alg = PEFS_ALG_DEFAULT;
 
-	orig_opterr = opterr;
-	opterr = 0;
-	while ((i = getopt(*pargc, argv, "pi:k:")) != -1)
-		switch(i) {
-		case 'a':
-			for (alg = algs; alg->name != NULL; alg++) {
-				if (strcmp(optarg, alg->name) == 0)
-					xk->pxk_alg = alg->id;
-			}
-			errx(EX_USAGE, "invalid algorithm %s", optarg);
-			break;
-		case 'p':
-			nopassphrase = 1;
-			break;
-		case 'i':
-			iterations = atoi(optarg);
-			if (iterations <= 0) {
-				warnx("invalid iterations argument: %s", optarg);
-				pefs_usage();
-			}
-			break;
-		case 'k':
-			keyfile = optarg;
-			break;
-		default:
-			argv[xargc++] = argv[optind - 1];
+	if (kp->kp_alg != NULL) {
+		for (alg = algs; alg->name != NULL; alg++) {
+			if (strcmp(kp->kp_alg, alg->name) == 0)
+				xk->pxk_alg = alg->id;
 		}
-	if (optind != *pargc) {
-		if (strcmp(argv[optind - 1], "--") == 0)
-			optind--;
-		for (i = optind; i < *pargc; i++) {
-			argv[xargc++] = argv[i];
-		}
+		errx(EX_USAGE, "invalid algorithm %s", optarg);
 	}
-	*pargc = xargc;
-	opterr = orig_opterr;
-	optind = 0;
-	optreset = 1;
 
 	g_eli_crypto_hmac_init(&ctx, NULL, 0);
 
-	if (keyfile != NULL && keyfile[0] == '\0')
-		keyfile = NULL;
-	if (keyfile == NULL && nopassphrase) {
+	if (kp->kp_keyfile != NULL && kp->kp_keyfile[0] == '\0')
+		kp->kp_keyfile = NULL;
+	if (kp->kp_keyfile == NULL && kp->kp_nopassphrase) {
 		warnx("no key components given");
 		pefs_usage();
 	}
-	if (keyfile != NULL) {
-		if (strcmp(keyfile, "-") == 0)
+	if (kp->kp_keyfile != NULL) {
+		if (strcmp(kp->kp_keyfile, "-") == 0)
 			fd = STDIN_FILENO;
 		else {
-			fd = open(keyfile, O_RDONLY);
+			fd = open(kp->kp_keyfile, O_RDONLY);
 			if (fd == -1)
-				err(EX_IOERR, "cannot open keyfile %s", keyfile);
+				err(EX_IOERR, "cannot open keyfile %s", kp->kp_keyfile);
 		}
 		while ((done = read(fd, buf, sizeof(buf))) > 0)
 			g_eli_crypto_hmac_update(&ctx, buf, done);
 		bzero(buf, sizeof(buf));
 		if (done == -1)
-			err(EX_IOERR, "cannot read keyfile %s", keyfile);
+			err(EX_IOERR, "cannot read keyfile %s", kp->kp_keyfile);
 		if (fd != STDIN_FILENO)
 			close(fd);
 	}
 
-	if (!nopassphrase) {
-		p = readpassphrase("Enter passphrase:", buf, sizeof(buf),
-		    RPP_ECHO_OFF | RPP_REQUIRE_TTY);
-		if (p == NULL) {
+	if (!kp->kp_nopassphrase) {
+		if (verify)
+			verify = 1;
+		if (prompt == NULL)
+			prompt = PEFS_KEY_PROMPT_DEFAULT;
+		for (i = 0; i <= verify; i++) {
+			snprintf(promptbuf, sizeof(promptbuf), "%s %s:",
+			    !i ? "Enter" : "Reenter", prompt);
+			p = readpassphrase(promptbuf, !i ? buf : buf2, BUFSIZ,
+			    RPP_ECHO_OFF | RPP_REQUIRE_TTY);
+			if (p == NULL) {
+				bzero(buf, sizeof(buf));
+				bzero(buf2, sizeof(buf2));
+				errx(EX_DATAERR, "unable to read passphrase");
+			}
+		}
+		if (verify && strcmp(buf, buf2) != 0) {
 			bzero(buf, sizeof(buf));
-			errx(EX_DATAERR, "unable to read passphrase");
+			bzero(buf2, sizeof(buf2));
+			errx(EX_DATAERR, "passphrases didn't match");
 		}
-		if (iterations == 0) {
+		bzero(buf2, sizeof(buf2));
+		if (kp->kp_iterations == 0) {
 			g_eli_crypto_hmac_update(&ctx, buf, strlen(buf));
 		} else {
-			pkcs5v2_genkey(xk->pxk_key, PEFS_KEY_SIZE, buf, 0, buf, iterations);
+			pkcs5v2_genkey(xk->pxk_key, PEFS_KEY_SIZE, buf, 0, buf, kp->kp_iterations);
 			g_eli_crypto_hmac_update(&ctx, xk->pxk_key, PEFS_KEY_SIZE);
 		}
 		bzero(buf, sizeof(buf));

==== //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_mount.c#2 (text+ko) ====

@@ -30,28 +30,18 @@
  * SUCH DAMAGE.
  */
 
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
-	The Regents of the University of California.  All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mount_null.c	8.6 (Berkeley) 4/26/95";
-#endif
 /*
  * Ancestors:
  *	FreeBSD: head/sbin/mount_nullfs/mount_nullfs.c 152670 2005-11-21 22:51:16Z rodrigc
  */
-static const char rcsid[] =
-  "$FreeBSD$";
-#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/uio.h>
 
+#include <inttypes.h>
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#5 (text+ko) ====

@@ -119,6 +119,7 @@
 	case PEFS_ALG_SALSA20:
 		break;
 	default:
+		printf("pefs: unknown algorithm %d\n", alg);
 		return (NULL);
 	}
 

==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#8 (text+ko) ====

@@ -43,6 +43,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
+#include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -104,7 +105,7 @@
 }
 
 static int
-pefs_enccn_create(struct pefs_enccn *pec, struct pefs_key *pk, struct componentname *cnp)
+pefs_enccn_create(struct pefs_enccn *pec, struct pefs_key *pk, char *tweak, struct componentname *cnp)
 {
 	int r;
 
@@ -115,7 +116,10 @@
 		pefs_enccn_init(pec, NULL, cnp->cn_nameptr, cnp->cn_namelen, cnp);
 		return (0);
 	}
-	arc4rand(pec->pec_tkey.ptk_tweak, PEFS_TWEAK_SIZE, 0);
+	if (tweak == NULL)
+		arc4rand(pec->pec_tkey.ptk_tweak, PEFS_TWEAK_SIZE, 0);
+	else
+		memcpy(pec->pec_tkey.ptk_tweak, tweak, PEFS_TWEAK_SIZE);
 	pec->pec_tkey.ptk_key = pk;
 	PEFSDEBUG("%s: pk=%p\n", __func__, pk);
 	pec->pec_buf = uma_zalloc(namei_zone, M_WAITOK);
@@ -251,7 +255,7 @@
 	if (error == ENOENT) {
 		struct pefs_key *dpk = pefs_node_key(VP_TO_PN(dvp));
 
-		error = pefs_enccn_create(pec, dpk, cnp);
+		error = pefs_enccn_create(pec, dpk, NULL, cnp);
 		pefs_key_release(dpk);
 	}
 	PEFSDEBUG("%s: returning = %d\n", __func__, error);
@@ -259,6 +263,22 @@
 	return (error);
 }
 
+static inline int
+pefs_enccn_lookup_createcopy(struct pefs_enccn *pec, struct pefs_tkey *ptk, struct vnode *dvp, struct componentname *cnp)
+{
+	int error;
+
+	MPASS(ptk->ptk_key != NULL);
+	error = pefs_enccn_lookup(pec, dvp, cnp);
+	PEFSDEBUG("%s: lookup error = %d\n", __func__, error);
+	if (error == ENOENT) {
+		error = pefs_enccn_create(pec, ptk->ptk_key, ptk->ptk_tweak, cnp);
+	}
+	PEFSDEBUG("%s: returning = %d\n", __func__, error);
+
+	return (error);
+}
+
 static int
 pefs_enccn_get(struct pefs_enccn *pec, struct vnode *vp, struct vnode *dvp, struct componentname *cnp)
 {
@@ -297,14 +317,20 @@
  * Recycle vnodes using key pk.
  * If pk is NULL recycle all vnodes with PN_HASKEY flag set.
  */
+#define PEFS_FLUSHKEY_ALL		1
+
 static int
-pefs_flushkey(struct mount *mp, struct pefs_key *pk)
+pefs_flushkey(struct mount *mp, struct thread *td, int flags, struct pefs_key *pk)
 {
 	struct vnode *vp, *mvp;
 	struct pefs_node *pn;
 	int error;
 
 	PEFSDEBUG("pefs_flushkey: pk=%p\n", pk);
+
+	vflush(mp, 0, 0, td);
+	if ((flags & PEFS_FLUSHKEY_ALL) == 0 && pk == NULL)
+		goto loop_end;
 	MNT_ILOCK(mp);
 loop:
 	MNT_VNODE_FOREACH(vp, mp, mvp) {
@@ -313,7 +339,7 @@
 		VI_LOCK(vp);
 		pn = VP_TO_PN(vp);
 		if ((pn->pn_flags & PN_HASKEY) && 
-		    (pk == NULL || pn->pn_tkey.ptk_key == pk)) {
+		    ((flags & PEFS_FLUSHKEY_ALL) || pn->pn_tkey.ptk_key == pk)) {

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list