Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Aug 2009 19:09:45 GMT
From:      Gleb Kurtsou <gk@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 167256 for review
Message-ID:  <200908121909.n7CJ9j3Q037433@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167256

Change 167256 by gk@gk_h1 on 2009/08/12 19:08:58

	* Add hmac-sha256 implementation
	* Use hmac for file name checksum:
		hmac(name key, encrypted file name)
		reduce hmac to 64 bits
		it should be replaced with something faster 
		previous checksum implementation was completely insecure
	* Additional algorithms support: 
		AES and Camellia
		128, 192, 256 bit key sizes
		used only in CTR mode (64 bit tweak + 64 bit offset)
	* Use algorithm id and key size during key generation . It allows use of same
	  passpharase with different algorithms/key sizes
	* Series of setkey fixes:
		recycle vnodes without key after adding a new one 
		recycle vnode after renamig it during setkey
		smaller userspace fixes
	* Key chain fixes: save int values in littlie endian db
	* Sepparate salsa20 implementation into 2 files so it can be compilled in
	  userspace easely

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#4 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#4 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#4 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_keychain.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20-kld.c#1 add
.. //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#9 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#7 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#8 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#10 edit
.. //depot/projects/soc2009/gk_pefs/sys/modules/pefs/Makefile#5 edit

Differences ...

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

@@ -118,7 +118,7 @@
 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));
+	printf("\t%-4d %016jx %s\n", ind, pefs_keyid_as_int(xk->pxk_keyid), pefs_alg_name(xk));
 }
 
 static int
@@ -236,12 +236,16 @@
 	struct pefs_keychain_head kch;
 	struct pefs_keyparam kp;
 	int error, fd, i;
+	int verbose = 0;
 	int addkey = 0;
 	int chain = PEFS_KEYCHAIN_IGNORE_MISSING;
 
 	pefs_keyparam_init(&kp);
-	while ((i = getopt(argc, argv, "xpcCa:i:k:")) != -1)
+	while ((i = getopt(argc, argv, "vxpcCa:i:k:")) != -1)
 		switch(i) {
+		case 'v':
+			verbose = 1;
+			break;
 		case 'x':
 			addkey = 1;
 			break;
@@ -290,13 +294,11 @@
 		return (error);
 
 	error = pefs_keychain_get(&kch, argv[0], chain, &k);
-	bzero(&k, sizeof(k));
+	bzero(k.pxk_key, PEFS_KEY_SIZE);
 	if (error)
 		return (EX_DATAERR);
 	pefs_keychain_free(&kch);
 
-	bzero(k.pxk_key, PEFS_KEY_SIZE);
-
 	fd = open(argv[0], O_RDONLY);
 	if (fd == -1) {
 		err(EX_IOERR, "cannot open %s", argv[0]);
@@ -305,6 +307,8 @@
 	if (ioctl(fd, PEFS_SETKEY, &k) == -1) {
 		warn("cannot set key");
 		error = EX_OSERR;
+	} else if (verbose) {
+		printf("New key: %016jx\n", pefs_keyid_as_int(k.pxk_keyid));
 	}
 
 	close(fd);
@@ -656,9 +660,9 @@
 			verbose = 1;
 			break;
 		case 'a':
-			k[0].pxk_alg = k[1].pxk_alg = pefs_alg_id(optarg);
-			if (k[0].pxk_alg < 0)
+			if (pefs_alg_lookup(&k[0], optarg) < 0)
 				errx(EX_USAGE, "invalid algorithm %s", optarg);
+			k[1] = k[0];
 			break;
 		case 'n':
 			if ((nmin = atoi(optarg)) <= 0) {
@@ -716,7 +720,7 @@
 	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 [-cCpx] [-a alg] [-i iterations] [-k keyfile] directory\n"
+			"	pefs setkey [-cCpvx] [-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 [-pPv] [-a alg] [-i iterations] [-k keyfile]\n"

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

@@ -27,6 +27,7 @@
  */
 
 #define PEFS_ALG_DEFAULT		PEFS_ALG_SALSA20
+#define PEFS_ALG_DEFAULT_KEYBITS	256
 
 #define PEFS_KDF_ITERATIONS		50000
 
@@ -58,6 +59,6 @@
 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);
+const char *	pefs_alg_name(struct pefs_xkey *xk);
+int	pefs_alg_lookup(struct pefs_xkey *xk, const char *algname);
 

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

@@ -53,21 +53,34 @@
 
 struct algorithm {
 	const char *name;
-	int id;
+	uint32_t id;
+	uint32_t keybits;
 };
 
 static struct algorithm algs[] = {
-	{ "salsa20-256", PEFS_ALG_SALSA20 },
-	{ NULL, 0 },
+	{ "salsa20-256", PEFS_ALG_SALSA20, 256 },
+	{ "aes128-ctr", PEFS_ALG_AES_CTR, 128 },
+	{ "aes128", PEFS_ALG_AES_CTR, 128 },
+	{ "aes192-ctr", PEFS_ALG_AES_CTR, 192 },
+	{ "aes192", PEFS_ALG_AES_CTR, 192 },
+	{ "aes256-ctr", PEFS_ALG_AES_CTR, 256 },
+	{ "aes256", PEFS_ALG_AES_CTR, 256 },
+	{ "camellia128-ctr", PEFS_ALG_CAMELLIA_CTR, 128 },
+	{ "camellia128", PEFS_ALG_CAMELLIA_CTR, 128 },
+	{ "camellia192-ctr", PEFS_ALG_CAMELLIA_CTR, 192 },
+	{ "camellia192", PEFS_ALG_CAMELLIA_CTR, 192 },
+	{ "camellia256-ctr", PEFS_ALG_CAMELLIA_CTR, 256 },
+	{ "camellia256", PEFS_ALG_CAMELLIA_CTR, 256 },
+	{ NULL, 0, 0 },
 };
 
 const char *
-pefs_alg_name(int alg_id)
+pefs_alg_name(struct pefs_xkey *xk)
 {
 	struct algorithm *alg;
 
 	for (alg = algs; alg->name != NULL; alg++) {
-		if (alg->id == alg_id)
+		if (alg->id == xk->pxk_alg && alg->keybits == xk->pxk_keybits)
 			return (alg->name);
 	}
 
@@ -75,13 +88,16 @@
 }
 
 int
-pefs_alg_id(const char *algname)
+pefs_alg_lookup(struct pefs_xkey *xk, const char *algname)
 {
 	struct algorithm *alg;
 
 	for (alg = algs; alg->name != NULL; alg++) {
-		if (strcmp(algname, alg->name) == 0)
+		if (strcmp(algname, alg->name) == 0) {
+			xk->pxk_alg = alg->id;
+			xk->pxk_keybits = alg->keybits;
 			return (alg->id);
+		}
 	}
 
 	return (-1);
@@ -97,15 +113,20 @@
 
 	xk->pxk_index = -1;
 	xk->pxk_alg = PEFS_ALG_DEFAULT;
+	xk->pxk_keybits = PEFS_ALG_DEFAULT_KEYBITS;
 
 	if (kp->kp_alg != NULL) {
-		xk->pxk_alg = pefs_alg_id(kp->kp_alg);
-		if (xk->pxk_alg < 0)
+		if (pefs_alg_lookup(xk, kp->kp_alg) < 0)
 			errx(EX_USAGE, "invalid algorithm %s", kp->kp_alg);
 	}
 
 	g_eli_crypto_hmac_init(&ctx, NULL, 0);
 
+	i = htole32(xk->pxk_alg);
+	g_eli_crypto_hmac_update(&ctx, (void *)&i, sizeof(uint32_t));
+	i = htole32(xk->pxk_keybits);
+	g_eli_crypto_hmac_update(&ctx, (void *)&i, sizeof(uint32_t));
+
 	if (kp->kp_keyfile != NULL && kp->kp_keyfile[0] == '\0')
 		kp->kp_keyfile = NULL;
 	if (kp->kp_keyfile == NULL && kp->kp_nopassphrase) {

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

@@ -29,6 +29,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <sys/endian.h>
 #include <sys/stat.h>
 #include <assert.h>
 #include <inttypes.h>
@@ -114,7 +115,10 @@
 		error = pefs_key_decrypt(&kc->kc_key, &kc_parent->kc_key);
 		if (error)
 			break;
-		if (pefs_alg_name(kc->kc_key.pxk_alg) == NULL) {
+		kc->kc_key.pxk_index = -1;
+		kc->kc_key.pxk_alg = le32toh(kc->kc_key.pxk_alg);
+		kc->kc_key.pxk_keybits = le32toh(kc->kc_key.pxk_keybits);
+		if (pefs_alg_name(&kc->kc_key) == 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),
@@ -144,6 +148,9 @@
 	kc->kc_key = *xk;
 	TAILQ_INSERT_HEAD(kch, kc, kc_entry);
 	
+	if (flags == 0)
+		return (0);
+
 	db = keychain_dbopen(filesystem, flags, O_RDONLY);
 	if (db == NULL) {
 		if (flags & PEFS_KEYCHAIN_IGNORE_MISSING)
@@ -172,6 +179,9 @@
 	int error;
 
 	k = *xknext;
+	k.pxk_index = (uint32_t)random();
+	k.pxk_alg = htole32(k.pxk_alg);
+	k.pxk_keybits = htole32(k.pxk_keybits);
 	if (pefs_key_encrypt(&k, xk) != 0)
 		return (-1);
 	

==== //depot/projects/soc2009/gk_pefs/sys/crypto/salsa20/salsa20.c#2 (text+ko) ====

@@ -7,11 +7,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/endian.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
 
 #include <crypto/salsa20/salsa20.h>
 
@@ -254,23 +251,3 @@
 	}
 }
 
-static int
-salsa20_modevent(module_t mod, int type, void *unused)
-{
-	switch (type) {
-	case MOD_LOAD:
-	case MOD_UNLOAD:
-		return (0);
-	}
-	return (EOPNOTSUPP);
-}
-
-static moduledata_t salsa20_mod = {
-	"salsa20",
-	salsa20_modevent,
-	NULL
-};
-
-DECLARE_MODULE(salsa20, salsa20_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
-MODULE_VERSION(salsa20, 1);
-

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

@@ -45,16 +45,19 @@
 #include <sys/uio.h>
 
 #define PEFS_ALG_SALSA20		1
+#define PEFS_ALG_AES_CTR		2
+#define PEFS_ALG_CAMELLIA_CTR		3
 
 #define PEFS_TWEAK_SIZE			8
 #define PEFS_KEY_BITS			512
 #define PEFS_KEY_SIZE			(PEFS_KEY_BITS / 8)
 #define PEFS_KEYID_SIZE			8
-#define PEFS_NAME_CSUM_SIZE		2
+#define PEFS_NAME_CSUM_SIZE		8
 
 struct pefs_xkey {
-	int pxk_index;
-	int pxk_alg;
+	uint32_t pxk_index;
+	uint32_t pxk_alg;
+	uint32_t pxk_keybits;
 	char pxk_keyid[PEFS_KEYID_SIZE];
 	char pxk_key[PEFS_KEY_SIZE];
 };
@@ -70,12 +73,16 @@
 #define PEFS_NAME_NTOP_SIZE(a)		(((a) * 4 + 2)/3)
 #define PEFS_NAME_PTON_SIZE(a)		(((a) * 3)/4)
 
+struct pefs_alg;
+
 TAILQ_HEAD(pefs_key_head, pefs_key);
 
 struct pefs_key {
+	TAILQ_ENTRY(pefs_key) pk_entry;
 	volatile u_int pk_refcnt;
-	int pk_alg;
-	TAILQ_ENTRY(pefs_key) pk_entry;
+	int pk_algid;
+	int pk_keybits;
+	const struct pefs_alg *pk_alg;
 	struct mtx *pk_entry_lock;
 	char pk_name[PEFS_KEY_SIZE];
 	char pk_data[PEFS_KEY_SIZE];
@@ -169,7 +176,7 @@
 struct pefs_ctx * pefs_ctx_get(void);
 void pefs_ctx_free(struct pefs_ctx *ctx);
 
-struct pefs_key * pefs_key_get(int alg, const char *key, const char *keyid);
+struct pefs_key * pefs_key_get(int alg, int keybits, const char *key, const char *keyid);
 struct pefs_key * pefs_key_ref(struct pefs_key *pk);
 void pefs_key_release(struct pefs_key *pk);
 

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

@@ -26,8 +26,8 @@
  * $FreeBSD$
  */
 
-#include <sys/types.h>
 #include <sys/param.h>
+#include <sys/endian.h>
 #include <sys/lock.h>
 #include <sys/libkern.h>
 #include <sys/malloc.h>
@@ -37,10 +37,55 @@
 
 #include <vm/uma.h>
 
+#include <crypto/camellia/camellia.h>
+#include <crypto/rijndael/rijndael.h>
 #include <crypto/salsa20/salsa20.h>
 
 #include <fs/pefs/pefs.h>
+#include <fs/pefs/pefs_hmac.h>
+
+typedef void algop_keysetup_t(struct pefs_ctx *ctx, const uint8_t *key, uint32_t keybits);
+typedef void algop_ivsetup_t(struct pefs_ctx *ctx, const uint8_t *iv, uint64_t offset);
+typedef void algop_crypt_t(struct pefs_ctx *ctx, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t len);
+typedef void algop_cryptblock_t(struct pefs_ctx *ctx, uint8_t *data);
+
+struct pefs_alg {
+	int pa_id;
+	algop_keysetup_t *pa_keysetup;
+	algop_ivsetup_t *pa_ivsetup;
+	algop_crypt_t *pa_crypt;
+};
+
+static algop_keysetup_t pefs_salsa20_keysetup;
+static algop_ivsetup_t pefs_salsa20_ivsetup;
+static algop_crypt_t pefs_salsa20_crypt;
+static algop_ivsetup_t pefs_ctr_ivsetup;
+static algop_keysetup_t pefs_aes_keysetup;
+static algop_crypt_t pefs_aes_crypt;
+static algop_keysetup_t pefs_camellia_keysetup;
+static algop_crypt_t pefs_camellia_crypt;
+
+static const struct pefs_alg pefs_alg_salsa20 = { 
+	PEFS_ALG_SALSA20,
+	pefs_salsa20_keysetup, 
+	pefs_salsa20_ivsetup,
+	pefs_salsa20_crypt
+};
 
+static const struct pefs_alg pefs_alg_aes = { 
+	PEFS_ALG_AES_CTR,
+	pefs_aes_keysetup, 
+	pefs_ctr_ivsetup,
+	pefs_aes_crypt
+};
+
+static const struct pefs_alg pefs_alg_camellia = { 
+	PEFS_ALG_CAMELLIA_CTR,
+	pefs_camellia_keysetup, 
+	pefs_ctr_ivsetup,
+	pefs_camellia_crypt
+};
+
 static const char magic_tweak_name[PEFS_TWEAK_SIZE] = {
 	0x5c, 0x83, 0xcb, 0x96, 0x2f, 0xaf, 0x3b, 0xb5,
 };
@@ -51,8 +96,26 @@
 	0xc8, 0x27, 0xa3, 0x7e, 0xcf, 0x86, 0x3d, 0x0d,
 };
 
+#define PEFS_CTR_BLOCK_SIZE		16
+
+CTASSERT(PEFS_TWEAK_SIZE == 64/8);
+CTASSERT(CAMELLIA_BLOCK_SIZE == PEFS_CTR_BLOCK_SIZE);
+
+struct pefs_ctr {
+	uint64_t pctr_offset;
+	uint32_t pctr_pos;
+	char pctr_tweak[PEFS_TWEAK_SIZE];
+	char pctr_block[PEFS_CTR_BLOCK_SIZE];
+} ;
+
 struct pefs_ctx {
-	salsa20_ctx pctx_salsa;
+	struct pefs_ctr pctx_ctr;
+	union {
+		camellia_ctx pctx_camellia;
+		rijndael_ctx pctx_aes;
+		salsa20_ctx pctx_salsa;
+		struct pefs_hmac_ctx pctx_hmac;
+	} o;
 };
 
 static uma_zone_t pefs_ctx_zone;
@@ -101,30 +164,50 @@
 	memcpy(tweak, magic_tweak_keygen, PEFS_TWEAK_SIZE);
 
 	for (i = 1; i < MAGIC_KEYGEN_ITERATIONS; i++) {
-		salsa20_keysetup(&ctx->pctx_salsa, key, PEFS_KEY_BITS);
-		salsa20_ivsetup(&ctx->pctx_salsa, tweak, i * 64);
-		salsa20_crypt(&ctx->pctx_salsa, key, key, PEFS_KEY_SIZE);
+		salsa20_keysetup(&ctx->o.pctx_salsa, key, 256);
+		salsa20_ivsetup(&ctx->o.pctx_salsa, tweak, i * 64);
+		salsa20_crypt(&ctx->o.pctx_salsa, key, key, PEFS_KEY_SIZE);
 		for (j = 0; j < PEFS_TWEAK_SIZE; j++)
 			tweak[j]++;
 	}
 }
 
 struct pefs_key *
-pefs_key_get(int alg, const char *key, const char *keyid)
+pefs_key_get(int alg, int keybits, const char *key, const char *keyid)
 {
 	struct pefs_ctx *ctx;
 	struct pefs_key *pk;
 
+	pk = uma_zalloc(pefs_key_zone, M_WAITOK | M_ZERO);
+
 	switch (alg) {
 	case PEFS_ALG_SALSA20:
+		pk->pk_alg = &pefs_alg_salsa20;
+		if (keybits == 256)
+			pk->pk_keybits = keybits;
+		break;
+	case PEFS_ALG_AES_CTR:
+		pk->pk_alg = &pefs_alg_aes;
+		if (keybits == 128 || keybits == 192 || keybits == 256)
+			pk->pk_keybits = keybits;
+		break;
+	case PEFS_ALG_CAMELLIA_CTR:
+		pk->pk_alg = &pefs_alg_camellia;
+		if (keybits == 128 || keybits == 192 || keybits == 256)
+			pk->pk_keybits = keybits;
 		break;
 	default:
+		uma_zfree(pefs_key_zone, pk);
 		printf("pefs: unknown algorithm %d\n", alg);
 		return (NULL);
 	}
+	if (pk->pk_keybits == 0) {
+		uma_zfree(pefs_key_zone, pk);
+		printf("pefs: invalid key size %d for algorithm %d\n", keybits, alg);
+		return (NULL);
+	}
+	pk->pk_algid = alg;
 
-	pk = uma_zalloc(pefs_key_zone, M_WAITOK | M_ZERO);
-	pk->pk_alg = alg;
 	refcount_init(&pk->pk_refcnt, 1);
 	memcpy(pk->pk_keyid, keyid, PEFS_KEYID_SIZE);
 
@@ -244,6 +327,7 @@
 void
 pefs_data_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
 {
+	const struct pefs_alg *alg;
 	struct iovec *iov;
 	int free_ctx = 0;
 
@@ -256,10 +340,11 @@
 		free_ctx = 1;
 	}
 
-	salsa20_keysetup(&ctx->pctx_salsa, ptk->ptk_key->pk_data, PEFS_KEY_BITS);
-	salsa20_ivsetup(&ctx->pctx_salsa, ptk->ptk_tweak, offset);
+	alg = ptk->ptk_key->pk_alg;
+	alg->pa_keysetup(ctx, ptk->ptk_key->pk_data, ptk->ptk_key->pk_keybits);
+	alg->pa_ivsetup(ctx, ptk->ptk_tweak, offset);
 	for (iov = pc->pc_iov; iov < pc->pc_iov + pc->pc_iovcnt; iov++) {
-		salsa20_crypt(&ctx->pctx_salsa, iov->iov_base, iov->iov_base,
+		alg->pa_crypt(ctx, iov->iov_base, iov->iov_base,
 		    iov->iov_len);
 	}
 
@@ -273,43 +358,19 @@
 	pefs_data_encrypt(ctx, ptk, offset, pc);
 }
 
-/*
- * Compute Internet Checksum
- */
-static u_short
-pefs_name_checksum(void *mem, size_t count)
+static inline void
+pefs_name_checksum(struct pefs_ctx *ctx, struct pefs_key *pk, u_char *csum, const void *mem, size_t count)
 {
-	u_short *buf = mem;
-	u_int sum = 0;
-
-	while (count > 1)  {
-		sum += *buf++;
-		count -= 2;
-	}
-
-	/*  Fold 32-bit sum to 16 bits */
-	while (sum >> 16)
-		sum = (sum & 0xffff) + (sum >> 16);
-
-	/*  Add left-over byte, if any */
-	if (count > 0) {
-		sum += * (unsigned char *) buf;
-		sum <<= 8;
-	}
-
-	/*  Fold 32-bit sum to 16 bits */
-	while (sum >> 16)
-		sum = (sum & 0xffff) + (sum >> 16);
-
-	return (~sum & 0xffff);
+	pefs_hmac(&ctx->o.pctx_hmac, pk->pk_name, pk->pk_keybits / 8,
+	    mem, count, csum, PEFS_NAME_CSUM_SIZE);
 }
 
 int
 pefs_name_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, const char *plain, size_t plain_len, char *enc, size_t enc_size)
 {
+	const struct pefs_alg *alg;
 	char *buf;
 	size_t size;
-	u_short csum;
 	int free_ctx = 0;
 	int r;
 
@@ -318,6 +379,7 @@
 		PEFSDEBUG("!!!! %s: NULL key\n", __func__);
 		return (-1);
 	}
+	alg = ptk->ptk_key->pk_alg;
 
 	size = PEFS_TWEAK_SIZE + plain_len + PEFS_NAME_CSUM_SIZE;
 	if (enc_size < PEFS_NAME_NTOP_SIZE(size)) {
@@ -326,22 +388,22 @@
 		return (-1);
 	}
 
+	if (ctx == NULL) {
+		ctx = pefs_ctx_get();
+		free_ctx = 1;
+	}
+
 	buf = malloc(size, M_PEFSBUF, M_WAITOK);
 
 	memcpy(buf, ptk->ptk_tweak, PEFS_TWEAK_SIZE);
 	memcpy(buf + PEFS_TWEAK_SIZE, plain, plain_len);
-	bzero(buf + size - PEFS_NAME_CSUM_SIZE, PEFS_NAME_CSUM_SIZE);
-	csum = pefs_name_checksum(buf, size);
-	memcpy(buf + size - PEFS_NAME_CSUM_SIZE, &csum, PEFS_NAME_CSUM_SIZE);
 
-	if (ctx == NULL) {
-		ctx = pefs_ctx_get();
-		free_ctx = 1;
-	}
+	alg->pa_keysetup(ctx, ptk->ptk_key->pk_name, ptk->ptk_key->pk_keybits);
+	alg->pa_ivsetup(ctx, magic_tweak_name, 0);
+	alg->pa_crypt(ctx, buf, buf, size - PEFS_NAME_CSUM_SIZE);
 
-	salsa20_keysetup(&ctx->pctx_salsa, ptk->ptk_key->pk_name, PEFS_KEY_BITS);
-	salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
-	salsa20_crypt(&ctx->pctx_salsa, buf, buf, size);
+	pefs_name_checksum(ctx, ptk->ptk_key, buf + size - PEFS_NAME_CSUM_SIZE,
+	    buf, size - PEFS_NAME_CSUM_SIZE);
 
 	if (free_ctx)
 		pefs_ctx_free(ctx);
@@ -358,8 +420,9 @@
 int
 pefs_name_decrypt(struct pefs_ctx *ctx, struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size)
 {
+	const struct pefs_alg *alg;
 	struct pefs_key *ki;
-	char *dec;
+	char csum[PEFS_NAME_CSUM_SIZE];
 	int free_ctx = 0;
 	int r, ki_rev;
 
@@ -367,6 +430,7 @@
 		PEFSDEBUG("!!!! %s: NULL pk\n", __func__);
 		return (-1);
 	}
+	alg = pk->pk_alg;
 	
 	if (enc == plain) {
 		PEFSDEBUG("pefs_name_decrypt: enc == plain\n");
@@ -386,24 +450,11 @@
 
 	ki = pk;
 	ki_rev = 0;
-	if (plain_size >= r * 2)
-		dec = plain + r;
-	else
-		dec = plain;
 	do {
-		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);
-
-		if (pefs_name_checksum(dec, r) == 0)
+		pefs_name_checksum(ctx, ki, csum, plain, r - PEFS_NAME_CSUM_SIZE);
+		if (memcmp(csum, plain + r - PEFS_NAME_CSUM_SIZE, PEFS_NAME_CSUM_SIZE) == 0)
 			break;
 
-		if (plain == dec) {
-			/* Restore previous value. */
-			salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
-			salsa20_crypt(&ctx->pctx_salsa, dec, plain, r);
-		}
-
 		if (!ki_rev) {
 			ki = TAILQ_NEXT(ki, pk_entry);
 			if (ki == NULL) {
@@ -422,13 +473,17 @@
 	if (ki == NULL)
 		return (-1);
 
+	alg->pa_keysetup(ctx, ki->pk_name, ki->pk_keybits);
+	alg->pa_ivsetup(ctx, magic_tweak_name, 0);
+	alg->pa_crypt(ctx, plain, plain, r - PEFS_NAME_CSUM_SIZE);
+
 	if (ptk) {
 		ptk->ptk_key = ki;
-		memcpy(ptk->ptk_tweak, dec, PEFS_TWEAK_SIZE);
+		memcpy(ptk->ptk_tweak, plain, PEFS_TWEAK_SIZE);
 	}
 
 	r -= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE;
-	memcpy(plain, dec + PEFS_TWEAK_SIZE, r);
+	memcpy(plain, plain + PEFS_TWEAK_SIZE, r);
 	plain[r] = '\0';
 
 	// PEFSDEBUG("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
@@ -436,3 +491,96 @@
 	return (r);
 }
 
+static void
+pefs_salsa20_keysetup(struct pefs_ctx *ctx, const uint8_t *key, uint32_t keybits)
+{
+	salsa20_keysetup(&ctx->o.pctx_salsa, key, keybits);
+}
+
+static void
+pefs_salsa20_ivsetup(struct pefs_ctx *ctx, const uint8_t *iv, uint64_t offset)
+{
+	salsa20_ivsetup(&ctx->o.pctx_salsa, iv, offset);
+}
+
+static void
+pefs_salsa20_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t len)
+{
+	salsa20_crypt(&ctx->o.pctx_salsa, plaintext, ciphertext, len);
+}
+
+static void
+pefs_ctr_ivsetup(struct pefs_ctx *ctx, const uint8_t *iv, uint64_t offset)
+{
+	ctx->pctx_ctr.pctr_offset = offset / PEFS_CTR_BLOCK_SIZE;
+	ctx->pctx_ctr.pctr_pos = offset % PEFS_CTR_BLOCK_SIZE;
+	memcpy(ctx->pctx_ctr.pctr_tweak, iv, PEFS_TWEAK_SIZE);
+}
+
+static inline void
+pefs_ctr_crypt(struct pefs_ctx *ctx, algop_cryptblock_t *cryptblock,
+    const uint8_t *plaintext, uint8_t *ciphertext, uint32_t len)
+{
+	struct pefs_ctr *c = &ctx->pctx_ctr;
+	uint64_t le_offset;
+	uint32_t pos, l, i;
+
+	pos = c->pctr_pos;
+	while (len) {
+		l = pos + len > PEFS_CTR_BLOCK_SIZE ? PEFS_CTR_BLOCK_SIZE - pos : len;
+		le_offset = htole64(c->pctr_offset);
+		memcpy(c->pctr_block + PEFS_TWEAK_SIZE, &le_offset, sizeof(uint64_t));
+		memcpy(c->pctr_block, c->pctr_tweak, PEFS_TWEAK_SIZE);
+		
+		cryptblock(ctx, c->pctr_block);
+		for (i = 0; i < l; i++) {
+			*(ciphertext++) = c->pctr_block[pos + i] ^ (*plaintext++);
+		}
+		pos = (pos + l) & (PEFS_CTR_BLOCK_SIZE - 1);
+		if (!pos)
+			c->pctr_offset++;
+		len -= l;
+	}
+	c->pctr_pos = pos;
+}
+
+static void
+pefs_camellia_keysetup(struct pefs_ctx *ctx, const uint8_t *key, uint32_t keybits)
+{
+	camellia_set_key(&ctx->o.pctx_camellia, key, keybits);
+}
+
+static void
+pefs_camellia_cryptblock(struct pefs_ctx *ctx, uint8_t *data)
+{
+	camellia_encrypt(&ctx->o.pctx_camellia, data, data);
+}
+
+static void
+pefs_camellia_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, 
+    uint8_t *ciphertext, uint32_t len)
+{
+	pefs_ctr_crypt(ctx, pefs_camellia_cryptblock, 
+	    plaintext, ciphertext, len);
+}
+
+static void
+pefs_aes_keysetup(struct pefs_ctx *ctx, const uint8_t *key, uint32_t keybits)
+{
+	rijndael_set_key(&ctx->o.pctx_aes, key, keybits);
+}
+
+static void
+pefs_aes_cryptblock(struct pefs_ctx *ctx, uint8_t *data)
+{
+	rijndael_encrypt(&ctx->o.pctx_aes, data, data);
+}
+
+static void
+pefs_aes_crypt(struct pefs_ctx *ctx, const uint8_t *plaintext, 
+    uint8_t *ciphertext, uint32_t len)
+{
+	pefs_ctr_crypt(ctx, pefs_aes_cryptblock, 
+	    plaintext, ciphertext, len);
+}
+

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

@@ -222,10 +222,6 @@
 {
 	struct vnode *vp;
 
-	PEFSDEBUG("pefs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
-	    (void *)VFS_TO_PEFS(mp)->pm_rootvp,
-	    (void *)PEFS_LOWERVP(VFS_TO_PEFS(mp)->pm_rootvp));
-
 	/*
 	 * Return locked reference to root.
 	 */

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

@@ -101,7 +101,7 @@
 	pec->pec_cn.cn_nameptr = pec->pec_buf;
 	pec->pec_cn.cn_namelen = encname_len;
 	pec->pec_cn.cn_consume = 0;
-	PEFSDEBUG("%s: name=%s len=%d\n", __func__, (char*)pec->pec_buf, encname_len);
+	PEFSDEBUG("%s: name=%s len=%d pk=%p\n", __func__, (char*)pec->pec_buf, encname_len, pec->pec_tkey.ptk_key);
 }
 
 static int
@@ -112,7 +112,7 @@
 	MPASS(pec != NULL && cnp != NULL);
 
 	pec->pec_cn = *cnp;
-	if (/* pk == NULL || */ (cnp->cn_flags & ISDOTDOT) || pefs_name_skip(cnp->cn_nameptr, cnp->cn_namelen)) {
+	if ((cnp->cn_flags & ISDOTDOT) || pefs_name_skip(cnp->cn_nameptr, cnp->cn_namelen)) {
 		pefs_enccn_init(pec, NULL, cnp->cn_nameptr, cnp->cn_namelen, cnp);
 		return (0);
 	}
@@ -290,33 +290,35 @@
 	return (error);
 }
 
+#define PEFS_FLUSHKEY_ALL		1
+
 /*
- * Recycle vnodes using key pk.
- * If pk is NULL recycle all vnodes with PN_HASKEY flag set.
+ * Recycle vnodes with key pk.
+ *
+ * pk == NULL => recycle vnodes without key
+ * flags & PEFS_FLUSHKEY_ALL => recycle all vnodes with key
  */
-#define PEFS_FLUSHKEY_ALL		1
-
 static int
 pefs_flushkey(struct mount *mp, struct thread *td, int flags, struct pefs_key *pk)
 {
-	struct vnode *vp, *mvp;
+	struct vnode *vp, *rootvp, *mvp;
 	struct pefs_node *pn;
 	int error;
 
-	PEFSDEBUG("pefs_flushkey: pk=%p\n", pk);
+	PEFSDEBUG("pefs_flushkey: pk=%p flags=%d\n", pk, flags);
 
 	vflush(mp, 0, 0, td);
-	if ((flags & PEFS_FLUSHKEY_ALL) == 0 && pk == NULL)
-		goto loop_end;
 	MNT_ILOCK(mp);
+	rootvp = VFS_TO_PEFS(mp)->pm_rootvp;
 loop:
 	MNT_VNODE_FOREACH(vp, mp, mvp) {
-		if (vp->v_type != VREG && vp->v_type != VDIR)
+		if ((vp->v_type != VREG && vp->v_type != VDIR) || vp == rootvp)
 			continue;
 		VI_LOCK(vp);
 		pn = VP_TO_PN(vp);
-		if ((pn->pn_flags & PN_HASKEY) && 
-		    ((flags & PEFS_FLUSHKEY_ALL) || pn->pn_tkey.ptk_key == pk)) {
+		if (((pn->pn_flags & PN_HASKEY) && 
+		    ((flags & PEFS_FLUSHKEY_ALL) || pn->pn_tkey.ptk_key == pk)) ||
+		    ((pn->pn_flags & PN_HASKEY) == 0 && pk == NULL)) {
 			vholdl(vp);
 			MNT_IUNLOCK(mp);
 			error = vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE);
@@ -336,7 +338,7 @@
 		}
 	}
 	MNT_IUNLOCK(mp);
-loop_end:
+
 	cache_purgevfs(mp);
 	return (0);
 }
@@ -1568,50 +1570,54 @@
 	PEFSDEBUG("pefs_setkey: name=%s; vp=%p; dvp=%p\n", cn.cn_nameptr, vp, dvp);
 
 	MPASS(dvp->v_mount == vp->v_mount);
+	lvp = PEFS_LOWERVP(vp);
+	ldvp = PEFS_LOWERVP(dvp);
 	vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	vdrop(dvp); /* vhold by vn_vptocnp */
 
 	error = pefs_enccn_get(&fenccn, vp, &cn);
 	if (error) {
+		VOP_UNLOCK(lvp, 0);
+		VOP_UNLOCK(ldvp, 0);
 		PEFSDEBUG("%s: pefs_enccn_get failed: %d\n", __func__, error);
 		goto out;
 	}
 	PEFSDEBUG("pefs_setkey: fromname=%s; key=%p\n", fenccn.pec_cn.cn_nameptr, fenccn.pec_tkey.ptk_key);
 	error = pefs_enccn_create(&tenccn, pk, NULL, &cn);
 	if (error) {
+		VOP_UNLOCK(lvp, 0);
+		VOP_UNLOCK(ldvp, 0);
 		pefs_enccn_free(&fenccn);
 		goto out;
 	}
 	PEFSDEBUG("pefs_setkey: toname=%s; key=%p\n", tenccn.pec_cn.cn_nameptr, tenccn.pec_tkey.ptk_key);
 
-	lvp = PEFS_LOWERVP(vp);
-	ldvp = PEFS_LOWERVP(dvp);
+	PEFSDEBUG("pefs_setkey: lvp usecount=%d, ldvp usecount=%d\n", lvp->v_usecount, ldvp->v_usecount); 
+	vref(lvp);
 	vref(lvp);
 	vref(ldvp);
+	vref(ldvp);
 	error = VOP_RENAME(ldvp, lvp, &fenccn.pec_cn, ldvp, lvp, &tenccn.pec_cn);
 	if (error) {
-		VOP_UNLOCK(dvp, 0);
-		VOP_UNLOCK(vp, 0);
+		vput(lvp);
+		vput(ldvp);
 		vrele(lvp);
 		vrele(ldvp);
+		PEFSDEBUG("pefs_setkey: error; lvp usecount=%d, ldvp usecount=%d\n", lvp->v_usecount, ldvp->v_usecount); 
 	} else {
-		pefs_key_release(pn->pn_tkey.ptk_key);
-		pn->pn_tkey = tenccn.pec_tkey;
-		pefs_key_ref(pn->pn_tkey.ptk_key);
+		PEFSDEBUG("pefs_setkey: ok; lvp usecount=%d, ldvp usecount=%d\n", lvp->v_usecount, ldvp->v_usecount); 
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+		vgone(vp);
+		VOP_UNLOCK(vp, 0);
 	}
 
 	pefs_enccn_free(&fenccn);
 	pefs_enccn_free(&tenccn);
 
 out:
-	vdrop(dvp);
 	free(namebuf, M_PEFSBUF);
 
-	if (!error) {
-		cache_purge(dvp);
-		cache_purge(vp);
-	}
-
 	return (error);
 }
 
@@ -1642,7 +1648,8 @@
 		TAILQ_FOREACH(pk, &pm->pm_keys, pk_entry) {
 			if (i++ == xk->pxk_index) {
 				memcpy(xk->pxk_keyid, pk->pk_keyid, PEFS_KEYID_SIZE);
-				xk->pxk_alg = pk->pk_alg;
+				xk->pxk_alg = pk->pk_algid;
+				xk->pxk_keybits = pk->pk_keybits;
 				break;
 			}
 		}
@@ -1667,7 +1674,7 @@
 		break;
 	case PEFS_ADDKEY:
 		PEFSDEBUG("pefs_ioctl: add key: %8D\n", xk->pxk_keyid, "");
-		pk = pefs_key_get(xk->pxk_alg, xk->pxk_key, xk->pxk_keyid);
+		pk = pefs_key_get(xk->pxk_alg, xk->pxk_keybits, xk->pxk_key, xk->pxk_keyid);
 		if (pk == NULL) {
 			PEFSDEBUG("pefs_key_get: error\n");
 			error = ENOENT;

==== //depot/projects/soc2009/gk_pefs/sys/modules/pefs/Makefile#5 (text+ko) ====

@@ -4,7 +4,7 @@
 
 KMOD=	pefs
 SRCS=	vnode_if.h \
-	pefs_subr.c pefs_vfsops.c pefs_vnops.c pefs_xbase64.c pefs_crypto.c
+	pefs_subr.c pefs_vfsops.c pefs_vnops.c pefs_xbase64.c pefs_crypto.c pefs_hmac.c
 DEBUG_FLAGS= -g -DPEFS_DEBUG
 
 .include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908121909.n7CJ9j3Q037433>