PERFORCE change 167106 for review

Gleb Kurtsou gk at FreeBSD.org
Sat Aug 8 15:52:41 UTC 2009


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

Change 167106 by gk at gk_h1 on 2009/08/08 15:52:18

	       readdir improvements: skip unknown entries in encrypted directories, merge cookies
	       encrypt key chains
	       use tailq for keychains
	       implement randomchain
	       do not call pefs_node_lookup_name from pefs_enccn_get (it's not needed)
	       simplify readdir and pefs_enccn_lookup_dirent: use continious buffer (maximum size is page size)
	       remove unused pefs_chunk_get (direct access to iovec is preferred)
	       increase max key size to 512 bits. userspace always generates 512 bits of key material. particular algorithm is to use as much of it as it needs
	       minor style improvements

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#3 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.h#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#8 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#6 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#8 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#7 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#9 edit

Differences ...

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

@@ -47,6 +47,7 @@
 #include "pefs_keychain.h"
 
 #define PATH_UMOUNT		"/sbin/umount"
+#define PATH_DEVRANDOM		"/dev/random"
 
 static int	pefs_unmount(int argc, char *argv[]);
 static int	pefs_addkey(int argc, char *argv[]);
@@ -60,7 +61,7 @@
 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);
+typedef int (*keyop_func_t)(struct pefs_keychain_head *kch, int fd);
 
 struct command {
 	const char *name;
@@ -124,7 +125,7 @@
 pefs_keyop(keyop_func_t func, int argc, char *argv[])
 {
 	struct pefs_xkey k;
-	struct pefs_keychain *kc;
+	struct pefs_keychain_head kch;
 	struct pefs_keyparam kp;
 	int error, fd, i;
 	int chain = PEFS_KEYCHAIN_IGNORE_MISSING;
@@ -169,19 +170,18 @@
 	if (error != 0)
 		return (error);
 
-	kc = pefs_keychain_get(argv[0], chain, &k);
+	error = pefs_keychain_get(&kch, argv[0], chain, &k);
 	bzero(&k, sizeof(k));
-	if (kc == NULL) {
+	if (error)
 		return (EX_DATAERR);
-	}
 	fd = open(argv[0], O_RDONLY);
 	if (fd == -1) {
 		err(EX_IOERR, "cannot open %s", argv[0]);
 	}
 	
-	error = func(kc, fd);
+	error = func(&kch, fd);
 
-	pefs_keychain_free(kc);
+	pefs_keychain_free(&kch);
 
 	close(fd);
 
@@ -189,9 +189,11 @@
 }
 
 static int
-pefs_addkey_op(struct pefs_keychain *kc, int fd)
+pefs_addkey_op(struct pefs_keychain_head *kch, int fd)
 {
-	for (; kc; kc = kc->kc_next) {
+	struct pefs_keychain *kc;
+
+	TAILQ_FOREACH(kc, kch, kc_entry) {
 		if (ioctl(fd, PEFS_ADDKEY, &kc->kc_key) == -1) {
 			warn("cannot add key");
 			return (-1);
@@ -202,9 +204,11 @@
 }
 
 static int
-pefs_delkey_op(struct pefs_keychain *kc, int fd)
+pefs_delkey_op(struct pefs_keychain_head *kch, int fd)
 {
-	for (; kc; kc = kc->kc_next) {
+	struct pefs_keychain *kc;
+
+	TAILQ_FOREACH(kc, kch, kc_entry) {
 		if (ioctl(fd, PEFS_DELKEY, &kc->kc_key) == -1) {
 			warn("cannot delete key");
 		}
@@ -229,7 +233,7 @@
 pefs_setkey(int argc, char *argv[])
 {
 	struct pefs_xkey k;
-	struct pefs_keychain *kc;
+	struct pefs_keychain_head kch;
 	struct pefs_keyparam kp;
 	int error, fd, i;
 	int addkey = 0;
@@ -285,11 +289,11 @@
 	if (error != 0)
 		return (error);
 
-	kc = pefs_keychain_get(argv[0], chain, &k);
-	if (kc == NULL) {
+	error = pefs_keychain_get(&kch, argv[0], chain, &k);
+	bzero(&k, sizeof(k));
+	if (error)
 		return (EX_DATAERR);
-	}
-	pefs_keychain_free(kc);
+	pefs_keychain_free(&kch);
 
 	bzero(k.pxk_key, PEFS_KEY_SIZE);
 
@@ -414,18 +418,23 @@
 static int
 pefs_setchain(int argc, char *argv[])
 {
-	struct pefs_keychain *kc, *kci;
+	struct pefs_keychain *kc;
+	struct pefs_keychain_head kch;
 	struct {
 		struct pefs_xkey k;
 		struct pefs_keyparam kp;
 	} p[2];
 	struct pefs_xkey *k1 = &p[0].k, *k2 = &p[1].k;
+	int verbose = 0;
 	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)
+	while ((i = getopt(argc, argv, "vpPa:A:i:I:k:K:")) != -1)
 		switch(i) {
+		case 'v':
+			verbose = 1;
+			break;
 		case 'a':
 		case 'A':
 			p[isupper(i) ? 1 : 0].kp.kp_alg = optarg;
@@ -468,10 +477,10 @@
 		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);
+	pefs_keychain_get(&kch, argv[0], PEFS_KEYCHAIN_IGNORE_MISSING, k1);
+	TAILQ_FOREACH(kc, &kch, kc_entry) {
+		if (memcmp(k2->pxk_keyid, kc->kc_key.pxk_keyid, PEFS_KEYID_SIZE) == 0) {
+			pefs_keychain_free(&kch);
 			bzero(k1->pxk_key, PEFS_KEY_SIZE);
 			bzero(k2->pxk_key, PEFS_KEY_SIZE);
 			errx(EX_DATAERR, "key chain is already set: %016jx -> %016jx",
@@ -479,19 +488,25 @@
 			    pefs_keyid_as_int(k2->pxk_keyid));
 		}
 	}
-	if (kc->kc_next != NULL) {
+	kc = TAILQ_FIRST(&kch);
+	if (TAILQ_NEXT(kc, kc_entry) != 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);
+		    pefs_keyid_as_int(TAILQ_NEXT(kc, kc_entry)->kc_key.pxk_keyid));
+		pefs_keychain_free(&kch);
 		exit(EX_DATAERR);
 	}
 
 	error = pefs_keychain_set(argv[0], k1, k2);
 	if (error)
 		return (EX_DATAERR);
+	if (verbose) {
+		printf("Key chain set: %016jx -> %016jx\n",
+		    pefs_keyid_as_int(k1->pxk_keyid),
+		    pefs_keyid_as_int(k2->pxk_keyid));
+	}
 
 	return (0);
 }
@@ -501,16 +516,20 @@
 {
 	struct pefs_xkey k;
 	struct pefs_keyparam kp;
-	struct pefs_keychain *kc, *kci;
+	struct pefs_keychain *kc;
+	struct pefs_keychain_head kch;
+	int force = 0, verbose = 0;;
 	int error, i;
-	int force = 0;
 
 	pefs_keyparam_init(&kp);
-	while ((i = getopt(argc, argv, "fpa:i:k:")) != -1)
+	while ((i = getopt(argc, argv, "fvpa:i:k:")) != -1)
 		switch(i) {
 		case 'f':
 			force = 1;
 			break;
+		case 'v':
+			verbose = 1;
+			break;
 		case 'a':
 			kp.kp_alg = optarg;
 			break;
@@ -541,18 +560,25 @@
 	if (error != 0)
 		return (error);
 
-	kc = pefs_keychain_get(argv[0], PEFS_KEYCHAIN_USE, &k);
-	if (kc == NULL) {
+	error = pefs_keychain_get(&kch, argv[0], PEFS_KEYCHAIN_USE, &k);
+	if (error) {
 		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);
+	TAILQ_FOREACH(kc, &kch, kc_entry) {
+		if (!TAILQ_NEXT(kc, kc_entry))
+			break;
+		pefs_keychain_del(argv[0], &kc->kc_key);
+		if (verbose) {
+			printf("Key chain deleted: %016jx -> %016jx\n",
+			    pefs_keyid_as_int(kc->kc_key.pxk_keyid),
+			    pefs_keyid_as_int(TAILQ_NEXT(kc, kc_entry)->kc_key.pxk_keyid));
+		}
 		if (!force)
 			break;
 	}
-	pefs_keychain_free(kc);
+	pefs_keychain_free(&kch);
 
 	return (0);
 }
@@ -562,7 +588,8 @@
 {
 	struct pefs_xkey k;
 	struct pefs_keyparam kp;
-	struct pefs_keychain *kc, *kci;
+	struct pefs_keychain *kc;
+	struct pefs_keychain_head kch;
 	int error, i;
 
 	pefs_keyparam_init(&kp);
@@ -598,25 +625,87 @@
 	if (error != 0)
 		return (error);
 
-	kc = pefs_keychain_get(argv[0], PEFS_KEYCHAIN_USE, &k);
-	if (kc == NULL) {
-		bzero(&k, sizeof(k));
+	error = pefs_keychain_get(&kch, argv[0], PEFS_KEYCHAIN_USE, &k);
+	bzero(&k, sizeof(k));
+	if (error) {
 		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);
+	i = 1;
+	TAILQ_FOREACH(kc, &kch, kc_entry) {
+		pefs_key_show(&kc->kc_key, i++);
 	}
-	pefs_keychain_free(kc);
+	pefs_keychain_free(&kch);
 
 	return (0);
 }
 
 static int
-pefs_randomchain(int argc __unused, char *argv[] __unused)
+pefs_randomchain(int argc, char *argv[])
 {
+	struct pefs_xkey k[2];
+	int nmin = PEFS_RANDOMCHAIN_MIN, nmax = PEFS_RANDOMCHAIN_MAX;
+	int verbose = 0;
+	int i, n, fd;
+
+	k[0].pxk_index = k[1].pxk_index = -1;
+	while ((i = getopt(argc, argv, "va:n:N:")) != -1)
+		switch(i) {
+		case 'v':
+			verbose = 1;
+			break;
+		case 'a':
+			k[0].pxk_alg = k[1].pxk_alg = pefs_alg_id(optarg);
+			if (k[0].pxk_alg < 0)
+				errx(EX_USAGE, "invalid algorithm %s", optarg);
+			break;
+		case 'n':
+			if ((nmin = atoi(optarg)) <= 0) {
+				warnx("invalid lower bound argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		case 'N':
+			if ((nmax = atoi(optarg)) <= 0) {
+				warnx("invalid lower bound argument: %s", optarg);
+				pefs_usage();
+			}
+			break;
+		default:
+			pefs_usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (nmin >= nmax) {
+		errx(EX_USAGE, "invalid arguments: lower bound (%d) >= upper bound (%d)", nmin, nmax);
+	}
+
+	if (!checkargs_fs(argc, argv)) {
+		pefs_usage();
+	}
+
+	n = arc4random_uniform(nmax - nmin) + nmin;
+
+	fd = open(PATH_DEVRANDOM, O_RDONLY);
+	if (fd == -1)
+		err(EX_IOERR, "%s", PATH_DEVRANDOM);
+
+	for (i = 1; i <= n; i++) {
+		read(fd, k, 2 * sizeof(struct pefs_keychain));
+		if (i % 2 == 0) {
+			pefs_keychain_set(argv[0], &k[0], &k[1]);
+			if (verbose) {
+				printf("Key chain set: %016jx -> %016jx\n",
+				    pefs_keyid_as_int(k[0].pxk_keyid),
+				    pefs_keyid_as_int(k[1].pxk_keyid));
+			}
+		}
+	}
+	
+	close(fd);
+
 	return (0);
 }
 
@@ -627,15 +716,15 @@
 	fprintf(stderr, "usage:	pefs mount [-o options] target filesystem\n"
 			"	pefs unmount [-fv] 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 setkey [-cCpx] [-a alg] [-i iterations] [-k keyfile] directory\n"
 			"	pefs delkey [-cCp] [-a alg] [-i iterations] [-k keyfile] filesystem\n"
 			"	pefs flushkeys filesystem\n"
-			"	pefs setchain [-pP] [-a alg] [-i iterations] [-k keyfile]\n"
+			"	pefs setchain [-pPv] [-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"
+			"	pefs delchain [-pPv] [-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 randomchain [-v] [-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#3 (text+ko) ====

@@ -25,10 +25,14 @@
  *
  * $FreeBSD$
  */
+
 #define PEFS_ALG_DEFAULT		PEFS_ALG_SALSA20
 
 #define PEFS_KDF_ITERATIONS		50000
 
+#define PEFS_RANDOMCHAIN_MIN		16
+#define PEFS_RANDOMCHAIN_MAX		64
+
 struct pefs_xkey;
 
 struct pefs_keyparam {
@@ -48,10 +52,12 @@
 }
 
 void	pefs_usage(void);
-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[]);
+int	pefs_key_get(struct pefs_xkey *xk, const char *prompt, int verify, struct pefs_keyparam *kp);
+int	pefs_key_encrypt(struct pefs_xkey *xk, const struct pefs_xkey *xk_parent);
+int	pefs_key_decrypt(struct pefs_xkey *xk, const struct pefs_xkey *xk_parent);
 uintmax_t	pefs_keyid_as_int(char *keyid);
 const char *	pefs_alg_name(int alg_id);
+int		pefs_alg_id(const char *name);
 

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

@@ -28,6 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <assert.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,10 +43,14 @@
 #include <geom/eli/pkcs5v2.h>
 #include <fs/pefs/pefs.h>
 
+#include <openssl/evp.h>
+
 #include "pefs_ctl.h"
 
 #define PEFS_KEY_PROMPT_DEFAULT			"passphrase"
 
+#define PEFS_CIPHERKEY_ITERATIONS		1000
+
 struct algorithm {
 	const char *name;
 	int id;
@@ -70,10 +75,22 @@
 }
 
 int
+pefs_alg_id(const char *algname)
+{
+	struct algorithm *alg;
+
+	for (alg = algs; alg->name != NULL; alg++) {
+		if (strcmp(algname, alg->name) == 0)
+			return (alg->id);
+	}
+
+	return (-1);
+}
+
+int
 pefs_key_get(struct pefs_xkey *xk, const char *prompt, int verify, struct pefs_keyparam *kp)
 {
 	struct hmac_ctx ctx;
-	struct algorithm *alg;
 	char promptbuf[64], buf[BUFSIZ], buf2[BUFSIZ], *p;
 	ssize_t done;
 	int fd, i;
@@ -82,11 +99,9 @@
 	xk->pxk_alg = PEFS_ALG_DEFAULT;
 
 	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;
-		}
-		errx(EX_USAGE, "invalid algorithm %s", optarg);
+		xk->pxk_alg = pefs_alg_id(kp->kp_alg);
+		if (xk->pxk_alg < 0)
+			errx(EX_USAGE, "invalid algorithm %s", kp->kp_alg);
 	}
 
 	g_eli_crypto_hmac_init(&ctx, NULL, 0);
@@ -153,3 +168,53 @@
 	return (0);
 }
 
+static int
+pefs_key_cipher(struct pefs_xkey *xk, int enc, const struct pefs_xkey *xk_parent)
+{
+	const int keysize = 128 / 8;
+	const int datasize = sizeof(struct pefs_xkey);
+	u_char *data = (u_char *) xk;
+	EVP_CIPHER_CTX ctx;
+	u_char iv[keysize];
+	u_char key[keysize];
+	int outsize;
+
+	pkcs5v2_genkey(key, keysize, NULL, 0, xk_parent->pxk_key, PEFS_CIPHERKEY_ITERATIONS);
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	EVP_CipherInit_ex(&ctx, EVP_aes_128_cfb(), NULL, NULL, NULL, enc);
+	EVP_CIPHER_CTX_set_key_length(&ctx, keysize);
+	EVP_CIPHER_CTX_set_padding(&ctx, 0);
+	bzero(iv, sizeof(iv));
+	EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
+	bzero(key, sizeof(key));
+
+	if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return (EINVAL);
+	}
+	assert(outsize == (int)datasize);
+
+	if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		return (EINVAL);
+	}
+	assert(outsize == 0);
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return (0);
+}
+
+int
+pefs_key_encrypt(struct pefs_xkey *xk, const struct pefs_xkey *xk_parent)
+{
+	return (pefs_key_cipher(xk, 1, xk_parent));
+}
+
+int
+pefs_key_decrypt(struct pefs_xkey *xk, const struct pefs_xkey *xk_parent)
+{
+	return (pefs_key_cipher(xk, 0, xk_parent));
+}
+

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

@@ -62,120 +62,129 @@
 	return (db);
 }
 
-void pefs_keychain_free(struct pefs_keychain *kc)
+void
+pefs_keychain_free(struct pefs_keychain_head *kch)
 {
-	struct pefs_keychain *prev;
+	struct pefs_keychain *kc;
 
-	while (kc) {
-		if (kc == NULL)
-			break;
-
+	if (kch == NULL)
+		return;
+	while ((kc = TAILQ_FIRST(kch)) != NULL) {
+		TAILQ_REMOVE(kch, kc, kc_entry);
 		bzero(kc, sizeof(struct pefs_keychain));
-		prev = kc;
-		kc = kc->kc_next;
-		free(prev);
+		free(kc);
 	}
 }
 
-static struct pefs_keychain *
-pefs_keychain_get_db(DB *db, struct pefs_xkey *xk)
+static int
+pefs_keychain_get_db(DB *db, struct pefs_keychain_head *kch)
 {
-	struct pefs_keychain *kc_head = NULL, **kc_prev = NULL, *kc;
+	struct pefs_keychain *kc_parent = NULL, *kc;
 	DBT db_key, db_data;
 	int error;
 
 	while (1) {
-		for (kc = kc_head; kc != NULL; kc = kc->kc_next) {
-			if (memcmp(xk->pxk_keyid, kc->kc_key.pxk_keyid, PEFS_KEYID_SIZE) == 0) {
-				pefs_keychain_free(kc_head);
+		kc_parent = TAILQ_LAST(kch, pefs_keychain_head);
+		TAILQ_FOREACH(kc, kch, kc_entry) {
+			if (kc != kc_parent && memcmp(kc->kc_key.pxk_keyid,
+			    kc_parent->kc_key.pxk_keyid, PEFS_KEYID_SIZE) == 0) {
+				pefs_keychain_free(kch);
 				errx(EX_DATAERR, "keychain: loop detected: %016jx",
-				    pefs_keyid_as_int(xk->pxk_keyid));
+				    pefs_keyid_as_int(kc->kc_key.pxk_keyid));
 			}
 		}
-
-		kc = calloc(1, sizeof(struct pefs_keychain));
-		if (kc == NULL)
-			err(EX_OSERR, "calloc");
-		if (kc_head == NULL)
-			kc_head = kc;
-		if (kc_prev != NULL)
-			*kc_prev = kc;
-		kc_prev = &kc->kc_next;
-		kc->kc_key = *xk;
-
-		db_key.data = kc->kc_key.pxk_keyid;
+		db_key.data = kc_parent->kc_key.pxk_keyid;
 		db_key.size = PEFS_KEYID_SIZE;
 		error = db->get(db, &db_key, &db_data, 0);
 		if (error != 0) {
 			if (error == -1)
 				warn("keychain");
-			if (kc == kc_head) {
-				pefs_keychain_free(kc);
-				kc_head = NULL;
-			}
+			if (TAILQ_FIRST(kch) != kc_parent)
+				error = 0;
 			break;
 		}
 		if (db_data.size != sizeof(struct pefs_xkey))
 			errx(EX_DATAERR, "keychain: db damaged");
-		xk = db_data.data;
+		
+		kc = calloc(1, sizeof(struct pefs_keychain));
+		if (kc == NULL)
+			err(EX_OSERR, "calloc");
+		
+		memcpy(&kc->kc_key, db_data.data, sizeof(struct pefs_xkey));
+		error = pefs_key_decrypt(&kc->kc_key, &kc_parent->kc_key);
+		if (error)
+			break;
+		if (pefs_alg_name(kc->kc_key.pxk_alg) == NULL) {
+			bzero(&kc->kc_key, sizeof(struct pefs_xkey));
+			warn("keychain %016jx -> %016jx: invalid algorithm (decyption failed)",
+			    pefs_keyid_as_int(kc_parent->kc_key.pxk_keyid),
+			    pefs_keyid_as_int(kc->kc_key.pxk_keyid));
+		}
+		TAILQ_INSERT_TAIL(kch, kc, kc_entry);
 	}
 
-	return (kc_head);
+	return (error);
 }
 
-struct pefs_keychain *
-pefs_keychain_get(const char *filesystem, int flags, struct pefs_xkey *xk)
+int
+pefs_keychain_get(struct pefs_keychain_head *kch, const char *filesystem,
+    int flags, struct pefs_xkey *xk)
 {
 	struct pefs_keychain *kc;
 	DB *db;
+	int error;
 
-	assert(filesystem != NULL && xk != NULL);
+	assert(filesystem != NULL && kch != NULL && xk != NULL);
 
-	if (flags == 0) {
-		kc = calloc(1, sizeof(struct pefs_keychain));
-		if (kc == NULL)
-			err(EX_OSERR, "calloc");
-		kc->kc_key = *xk;
+	TAILQ_INIT(kch);
 
-		return (kc);
-	}
+	kc = calloc(1, sizeof(struct pefs_keychain));
+	if (kc == NULL)
+		err(EX_OSERR, "calloc");
+	kc->kc_key = *xk;
+	TAILQ_INSERT_HEAD(kch, kc, kc_entry);
 	
 	db = keychain_dbopen(filesystem, flags, O_RDONLY);
 	if (db == NULL) {
 		if (flags & PEFS_KEYCHAIN_IGNORE_MISSING)
-			return (pefs_keychain_get(filesystem, 0, xk));
-		return (NULL);
+			return (0);
+		return (ENOENT);
 	}
 
-	kc = pefs_keychain_get_db(db, xk);
+	error = pefs_keychain_get_db(db, kch);
 
 	db->close(db);
 
-	if (kc == NULL) {
+	if (error) {
 		if (flags & PEFS_KEYCHAIN_USE)
 			errx(EX_DATAERR, "keychain: Key not found %016jx", pefs_keyid_as_int(xk->pxk_keyid));
-		else if (flags & PEFS_KEYCHAIN_IGNORE_MISSING)
-			return (pefs_keychain_get(filesystem, 0, xk));
 	}
 
-	return (kc);
+	return (0);
 }
 
 int
 pefs_keychain_set(const char *filesystem, struct pefs_xkey *xk, struct pefs_xkey *xknext)
 {
+	struct pefs_xkey k;
 	DBT db_key, db_data;
 	DB *db;
 	int error;
 
+	k = *xknext;
+	if (pefs_key_encrypt(&k, xk) != 0)
+		return (-1);
+	
 	db = keychain_dbopen(filesystem, PEFS_KEYCHAIN_USE, O_RDWR | O_CREAT);
 	if (db == NULL)
 		return (-1);
+
+	db_data.data = &k;
+	db_data.size = sizeof(struct pefs_xkey);
 	db_key.data = xk->pxk_keyid;
 	db_key.size = PEFS_KEYID_SIZE;
-	db_data.data = xknext;
-	db_data.size = sizeof(struct pefs_xkey);
 	error = db->put(db, &db_key, &db_data, R_NOOVERWRITE);
+	bzero(&k, sizeof(struct pefs_xkey));
 	if (error != 0) {
 		if (error == -1)
 			warn("keychain");

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

@@ -26,17 +26,23 @@
  * $FreeBSD$
  */
 
+#include <sys/queue.h>
+
 #define PEFS_KEYCHAIN_USE		0x0001
 #define PEFS_KEYCHAIN_IGNORE_MISSING	0x0002
 
 struct pefs_keychain
 {
+	TAILQ_ENTRY(pefs_keychain) kc_entry;
 	struct pefs_xkey kc_key;
-	struct pefs_keychain *kc_next;
 };
 
-struct pefs_keychain * pefs_keychain_get(const char *filesystem, int flags, struct pefs_xkey *xk);
-int pefs_keychain_set(const char *filesystem, struct pefs_xkey *xk, struct pefs_xkey *xknext);
-int pefs_keychain_del(const char *filesystem, struct pefs_xkey *xk);
-void pefs_keychain_free(struct pefs_keychain *kc);
+TAILQ_HEAD(pefs_keychain_head, pefs_keychain);
+
+int	pefs_keychain_get(struct pefs_keychain_head *kch,
+    const char *filesystem, int flags, struct pefs_xkey *xk);
+int	pefs_keychain_set(const char *filesystem, struct pefs_xkey *xk,
+    struct pefs_xkey *xknext);
+int	pefs_keychain_del(const char *filesystem, struct pefs_xkey *xk);
+void	pefs_keychain_free(struct pefs_keychain_head *kch);
 

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

@@ -47,7 +47,7 @@
 #define PEFS_ALG_SALSA20		1
 
 #define PEFS_TWEAK_SIZE			8
-#define PEFS_KEY_BITS			256
+#define PEFS_KEY_BITS			512
 #define PEFS_KEY_SIZE			(PEFS_KEY_BITS / 8)
 #define PEFS_KEYID_SIZE			8
 #define PEFS_NAME_CSUM_SIZE		2
@@ -164,7 +164,6 @@
 
 int pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode *ldvp, struct vnode **vpp, struct ucred *cred, struct pefs_tkey *ptk);
 void pefs_node_free(struct pefs_node *xp);
-int pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len);
 struct pefs_key * pefs_node_key(struct pefs_node *pn);
 
 struct pefs_ctx * pefs_ctx_get(void);
@@ -194,7 +193,6 @@
 void* pefs_chunk_pullup(struct pefs_chunk *pc, size_t size);
 struct uio * pefs_chunk_uio(struct pefs_chunk *pc, off_t uio_offset, enum uio_rw uio_rw);
 struct uio * pefs_chunk_uio_range(struct pefs_chunk *pc, size_t skip, size_t size, off_t uio_offset, enum uio_rw uio_rw);
-void* pefs_chunk_get(struct pefs_chunk *pc, size_t *size, long *_state);
 void pefs_chunk_zero(struct pefs_chunk *pc);
 int pefs_chunk_copy(struct pefs_chunk *pc, size_t skip, struct uio *uio);
 void pefs_chunk_crop(struct pefs_chunk *pc, size_t skip_begin, size_t skip_end);
@@ -228,7 +226,7 @@
 #ifdef PEFS_DEBUG
 #define PEFSDEBUG(format, args...) printf(format ,## args)
 #else
-#define PEFSDEBUG(format, args...)
+#define PEFSDEBUG(format, args...) do { } while (0)
 #endif /* PEFS_DEBUG */
 
 #endif /* _KERNEL */

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

@@ -79,7 +79,7 @@
 struct pefs_ctx *
 pefs_ctx_get(void)
 {
-	return uma_zalloc(pefs_ctx_zone, M_WAITOK);
+	return (uma_zalloc(pefs_ctx_zone, M_WAITOK));
 }
 
 void
@@ -244,9 +244,7 @@
 void
 pefs_data_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
 {
-	long arg = 0;
-	char *mem;
-	size_t size;
+	struct iovec *iov;
 	int free_ctx = 0;
 
 	if (ptk->ptk_key == NULL) {
@@ -260,11 +258,9 @@
 
 	salsa20_keysetup(&ctx->pctx_salsa, ptk->ptk_key->pk_data, PEFS_KEY_BITS);
 	salsa20_ivsetup(&ctx->pctx_salsa, ptk->ptk_tweak, offset);
-	while (1) {
-		mem = pefs_chunk_get(pc, &size, &arg);
-		if (mem == NULL)
-			break;
-		salsa20_crypt(&ctx->pctx_salsa, mem, mem, size);
+	for (iov = pc->pc_iov; iov < pc->pc_iov + pc->pc_iovcnt; iov++) {
+		salsa20_crypt(&ctx->pctx_salsa, iov->iov_base, iov->iov_base,
+		    iov->iov_len);
 	}
 
 	if (free_ctx)
@@ -356,7 +352,7 @@
 
 	free(buf, M_PEFSBUF);
 
-	return r;
+	return (r);
 }
 
 int
@@ -395,7 +391,6 @@
 	else
 		dec = plain;
 	do {
-		PEFSDEBUG("pefs_name_decrypt: check key %p\n", ki);
 		salsa20_keysetup(&ctx->pctx_salsa, ki->pk_name, PEFS_KEY_BITS);
 		salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
 		salsa20_crypt(&ctx->pctx_salsa, plain, dec, r);
@@ -411,7 +406,6 @@
 
 		if (!ki_rev) {
 			ki = TAILQ_NEXT(ki, pk_entry);
-			PEFSDEBUG("pefs_name_decrypt: next key %p\n", ki);
 			if (ki == NULL) {
 				ki_rev = 1;
 				ki = pk;
@@ -419,7 +413,6 @@
 		}
 		if (ki_rev) {
 			ki = TAILQ_PREV(ki, pefs_key_head, pk_entry);
-			PEFSDEBUG("pefs_name_decrypt: prev key %p\n", ki);
 		}
 	} while (ki != NULL);
 
@@ -438,8 +431,8 @@
 	memcpy(plain, dec + PEFS_TWEAK_SIZE, r);
 	plain[r] = '\0';
 
-	PEFSDEBUG("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
+	// PEFSDEBUG("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
 
-	return r;
+	return (r);
 }
 

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

@@ -191,7 +191,7 @@
 	vput(vp);
 }
 
-int
+static int
 pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len)
 {
 	struct vnode *nldvp;
@@ -229,7 +229,7 @@
 		encname[*encname_len] = '\0';
 	PEFSDEBUG("%s: len=%d %s\n", __func__, *encname_len, encname);
 
-	return 0;
+	return (0);
 }
 
 static int
@@ -463,7 +463,7 @@
 struct uio*
 pefs_chunk_uio(struct pefs_chunk *pc, off_t uio_offset, enum uio_rw uio_rw)
 {
-	return pefs_chunk_uio_range(pc, 0, pc->pc_size, uio_offset, uio_rw);
+	return (pefs_chunk_uio_range(pc, 0, pc->pc_size, uio_offset, uio_rw));
 }
 
 struct uio*
@@ -497,23 +497,6 @@
 	return (&pc->pc_uio);
 }
 
-void*
-pefs_chunk_get(struct pefs_chunk *pc, size_t *size, long *state)
-{
-	void *mem;
-
-	if (!size || !state || *state < 0)
-		panic("pefs_chunk_get: invalid args");
-	if (*state >= pc->pc_iovcnt) {
-		*size = 0;
-		return (NULL);
-	}
-	mem = pc->pc_iov[*state].iov_base;
-	*size = pc->pc_iov[*state].iov_len;
-	(*state)++;
-	return (mem);
-}
-
 void
 pefs_chunk_zero(struct pefs_chunk *pc)
 {
@@ -653,6 +636,6 @@
 		a->pn_lowervp, vrefcnt(a->pn_lowervp),
 		fil, lno);
 #endif
-	return a->pn_lowervp;
+	return (a->pn_lowervp);
 }
 #endif

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

@@ -62,7 +62,7 @@
 	int error = 0;
 	struct vnode *lowerrootvp, *vp;
 	struct vnode *pm_rootvp;
-	struct pefs_mount *xmp;
+	struct pefs_mount *pm;
 	char *target;
 	int isvnunlocked = 0, len;
 	struct nameidata nd, *ndp = &nd;
@@ -129,16 +129,16 @@
 		return (EDEADLK);
 	}
 
-	xmp = (struct pefs_mount *) malloc(sizeof(struct pefs_mount),
-				M_PEFSMNT, M_WAITOK | M_ZERO);	/* XXX */
+	pm = (struct pefs_mount *)malloc(sizeof(struct pefs_mount), M_PEFSMNT,
+	    M_WAITOK | M_ZERO);
 
-	mtx_init(&xmp->pm_keys_lock, "pefs_mount lock", NULL, MTX_DEF);
-	TAILQ_INIT(&xmp->pm_keys);
+	mtx_init(&pm->pm_keys_lock, "pefs_mount lock", NULL, MTX_DEF);
+	TAILQ_INIT(&pm->pm_keys);
 
 	/*
 	 * Save reference to underlying FS
 	 */
-	xmp->pm_lowervfs = lowerrootvp->v_mount;
+	pm->pm_lowervfs = lowerrootvp->v_mount;
 
 	/*
 	 * Save reference.  Each mount also holds
@@ -151,7 +151,7 @@
 	if (error) {
 		VOP_UNLOCK(vp, 0);
 		vrele(lowerrootvp);
-		free(xmp, M_PEFSMNT);	/* XXX */
+		free(pm, M_PEFSMNT);
 		return (error);
 	}
 
@@ -161,7 +161,7 @@
 	 */
 	pm_rootvp = vp;
 	pm_rootvp->v_vflag |= VV_ROOT;
-	xmp->pm_rootvp = pm_rootvp;
+	pm->pm_rootvp = pm_rootvp;
 
 	/*
 	 * Unlock the node (either the lower or the alias)
@@ -176,7 +176,7 @@
 	MNT_ILOCK(mp);
 	mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE;
 	MNT_IUNLOCK(mp);
-	mp->mnt_data =  xmp;
+	mp->mnt_data =  pm;
 	vfs_getnewfsid(mp);
 
 	vfs_mountedfrom(mp, target);
@@ -214,7 +214,7 @@
 	pefs_key_remove_all(pm);
 	mtx_destroy(&pm->pm_keys_lock);
 	free(pm, M_PEFSMNT);
-	return 0;

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


More information about the p4-projects mailing list