PERFORCE change 168707 for review

Gleb Kurtsou gk at FreeBSD.org
Sun Sep 20 13:20:25 UTC 2009


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

Change 168707 by gk at gk_h1 on 2009/09/20 13:19:49

	* use aes-128 in cbc mode to encrypt file names
	* don't use algorithm id and keysize during key generation, because file
	names are always encrypted with the same algorithm
	* load pefs kld if needed

Affected files ...

.. //depot/projects/soc2009/gk_pefs/sbin/pefs/Makefile#3 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.c#7 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_ctl.h#7 edit
.. //depot/projects/soc2009/gk_pefs/sbin/pefs/pefs_key.c#6 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#11 edit

Differences ...

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

@@ -16,7 +16,7 @@
 WARNS?=	6
 DEBUG_FLAGS+= -g
 
-DPADD=  ${LIBCRYPTO}
-LDADD=  -lcrypto
+DPADD=  ${LIBCRYPTO} ${LIBUTIL}
+LDADD=  -lcrypto -lutil
 
 .include <bsd.prog.mk>

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

@@ -29,6 +29,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/module.h>
 #include <sys/mount.h>
 
 #include <assert.h>
@@ -42,6 +43,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <libutil.h>
 
 #include <fs/pefs/pefs.h>
 
@@ -776,6 +778,15 @@
 	exit(EX_USAGE);
 }
 
+static void
+pefs_kld_load(void)
+{
+	if (modfind(PEFS_KLD) < 0)
+		if (kld_load(PEFS_KLD) < 0 || modfind(PEFS_KLD) < 0)
+			errx(EX_OSERR, "cannot find or load \"%s\" kernel module",
+			    PEFS_KLD);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -787,6 +798,7 @@
 		prog = argv[0];
 
 	if (strstr(prog, "mount_pefs")) {
+		pefs_kld_load();
 		return (pefs_mount_prog(argc, argv));
 	}
 
@@ -799,6 +811,7 @@
 			argv += 2;
 			optind = 0;
 			optreset = 1;
+			pefs_kld_load();
 			return (cmd->func(argc, argv));
 		}
 	}

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

@@ -27,6 +27,7 @@
  */
 
 #define PEFS_FSTYPE			"pefs"
+#define PEFS_KLD			PEFS_FSTYPE
 
 #define PEFS_ALG_DEFAULT		PEFS_ALG_AES_CTR
 #define PEFS_ALG_DEFAULT_KEYBITS	256

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

@@ -122,11 +122,6 @@
 
 	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/sys/fs/pefs/pefs_crypto.c#11 (text+ko) ====

@@ -47,7 +47,7 @@
 #include <fs/pefs/vmac.h>
 
 #define PEFS_CTR_BLOCK_SIZE		16
-#define PEFS_CSUM_BLOCK_SIZE		16
+#define PEFS_NAME_BLOCK_SIZE		16
 #define PEFS_BLOCK_ROUND(block, a)	(((a) + (block) - 1) & ~((block) - 1)) 
 
 CTASSERT(PEFS_KEY_SIZE <= SHA512_DIGEST_LENGTH);
@@ -114,10 +114,6 @@
 	pefs_camellia_crypt
 };
 
-static const char magic_tweak_name[PEFS_TWEAK_SIZE] = {
-	0x5c, 0x83, 0xcb, 0x96, 0x2f, 0xaf, 0x3b, 0xb5,
-};
-
 /* vmac requirement: first bit of the nonce buffer n must be 0 */
 static const char magic_name_csum_nonce[VMAC_NHBYTES] = {
 	0x00, 0xb1, 0xad, 0xd5, 0x5b, 0xf9, 0x10, 0xe1,
@@ -209,7 +205,7 @@
 	pefs_hmac_update(&ctx->o.pctx_hmac, magic_ctxinfo_name_key, PEFS_TWEAK_SIZE);
 	pefs_hmac_update(&ctx->o.pctx_hmac, &idx, sizeof(idx));
 	pefs_hmac_final(&ctx->o.pctx_hmac, key, PEFS_KEY_SIZE);
-	pk->pk_alg->pa_keysetup(pk->pk_name_ctx, key, pk->pk_keybits);
+	pefs_aes_keysetup(pk->pk_name_ctx, key, 128);
 
 	idx = 3;
 	pefs_hmac_init(&ctx->o.pctx_hmac, masterkey, PEFS_KEY_SIZE);
@@ -432,36 +428,49 @@
 	pefs_data_encrypt(ctx, ptk, offset, pc);
 }
 
+/*
+ * File name layout: [checksum] [tweak] [name]
+ * File name is padded with zeros to 16 byte boundary
+ */
 static inline size_t
-pefs_name_checksum_psize(size_t namelen)
+pefs_name_padsize(size_t size)
 {
 	size_t psize;
 
-	MPASS(namelen > PEFS_NAME_CSUM_SIZE && namelen < MAXNAMLEN + 1);
-	psize = namelen - PEFS_NAME_CSUM_SIZE;
+	MPASS(size > PEFS_NAME_CSUM_SIZE && size <= MAXNAMLEN);
+	psize = size - PEFS_NAME_CSUM_SIZE;
 	psize = PEFS_NAME_CSUM_SIZE + 
-	    PEFS_BLOCK_ROUND(PEFS_CSUM_BLOCK_SIZE, psize);
+	    PEFS_BLOCK_ROUND(PEFS_NAME_BLOCK_SIZE, psize);
 
 	return (psize);
 }
 
-/*
- * File name layout: [checksum] [tweak] [name]
- */
-static inline void
-pefs_name_checksum(struct pefs_ctx *ctx, struct pefs_key *pk, char *csum,
-    char *name, size_t size, size_t maxsize)
+static inline size_t
+pefs_name_pad(char *name, size_t size, size_t maxsize)
 {
-	CTASSERT(PEFS_NAME_CSUM_SIZE <= sizeof(uint64_t));
-	uint64_t csum_int;
 	size_t psize;
 
-	psize = pefs_name_checksum_psize(size);
+	psize = pefs_name_padsize(size);
+	MPASS(psize <= MAXNAMLEN);
 	if (psize != size) {
 		if (maxsize < psize)
-			panic("pefs_name_checksum: buffer is too small");
+			panic("pefs_name_pad: buffer is too small");
 		bzero(name + size, psize - size);
 	}
+
+	return (psize);
+}
+
+static inline void
+pefs_name_checksum(struct pefs_ctx *ctx, struct pefs_key *pk, char *csum,
+    char *name, size_t size)
+{
+	CTASSERT(PEFS_NAME_CSUM_SIZE <= sizeof(uint64_t));
+	uint64_t csum_int;
+
+	MPASS(size > PEFS_NAME_CSUM_SIZE &&
+	    size <= MAXNAMLEN &&
+	    (size - PEFS_NAME_CSUM_SIZE) % PEFS_NAME_BLOCK_SIZE == 0);
 	
 	pefs_ctx_cpy(ctx, pk->pk_name_csum_ctx);
 	csum_int = vmac(name + PEFS_NAME_CSUM_SIZE,
@@ -471,13 +480,64 @@
 	memcpy(csum, &csum_int, PEFS_NAME_CSUM_SIZE);
 }
 
+static inline void
+pefs_name_enccbc(struct pefs_ctx *ctx, struct pefs_key *pk,
+    u_char *data, ssize_t size)
+{
+	u_char *prev;
+	int i;
+
+	size -= PEFS_NAME_CSUM_SIZE;
+	data += PEFS_NAME_CSUM_SIZE;
+	MPASS(size > 0 && size % PEFS_NAME_BLOCK_SIZE == 0);
+
+	pefs_ctx_cpy(ctx, pk->pk_name_ctx);
+
+	/* Start with zero iv */
+	while (1) {
+		rijndael_encrypt(&ctx->o.pctx_aes, data, data);
+		prev = data;
+		data += PEFS_NAME_BLOCK_SIZE;
+		size -= PEFS_NAME_BLOCK_SIZE;
+		if (size == 0)
+			break;
+		for (i = 0; i < PEFS_NAME_BLOCK_SIZE; i++)
+			data[i] ^= prev[i];
+	}
+}
+
+static inline void
+pefs_name_deccbc(struct pefs_ctx *ctx, struct pefs_key *pk,
+    u_char *data, ssize_t size)
+{
+	u_char tmp[PEFS_NAME_BLOCK_SIZE], iv[PEFS_NAME_BLOCK_SIZE];
+	int i;
+
+	size -= PEFS_NAME_CSUM_SIZE;
+	data += PEFS_NAME_CSUM_SIZE;
+	MPASS(size > 0 && size % PEFS_NAME_BLOCK_SIZE == 0);
+
+	pefs_ctx_cpy(ctx, pk->pk_name_ctx);
+
+	bzero(iv, PEFS_NAME_BLOCK_SIZE);
+	while (size > 0) {
+		memcpy(tmp, data, PEFS_NAME_BLOCK_SIZE);
+		rijndael_decrypt(&ctx->o.pctx_aes, data, data);
+		for (i = 0; i < PEFS_NAME_BLOCK_SIZE; i++)
+			data[i] ^= iv[i];
+		memcpy(iv, tmp, PEFS_NAME_BLOCK_SIZE);
+		data += PEFS_NAME_BLOCK_SIZE;
+		size -= PEFS_NAME_BLOCK_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)
+pefs_name_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk,
+    const char *plain, size_t plain_len, char *enc, size_t enc_size)
 {
-	CTASSERT(MAXNAMLEN >= PEFS_NAME_PTON_SIZE(MAXNAMLEN) + PEFS_CSUM_BLOCK_SIZE);
-	const struct pefs_alg *alg;
+	CTASSERT(MAXNAMLEN >=
+	    PEFS_NAME_PTON_SIZE(MAXNAMLEN) + PEFS_NAME_BLOCK_SIZE);
 	char buf[MAXNAMLEN + 1];
-	char *buf_name, *buf_tweak;
 	size_t size;
 	int free_ctx = 0;
 	int r;
@@ -485,15 +545,15 @@
 	KASSERT(ptk != NULL && ptk->ptk_key != NULL,
 	    ("pefs_name_encrypt: key is null"));
 
-	alg = ptk->ptk_key->pk_alg;
-
-	size = PEFS_TWEAK_SIZE + plain_len + PEFS_NAME_CSUM_SIZE;
-	if (PEFS_NAME_NTOP_SIZE(size) + 1 > MAXNAMLEN) {
+	size = PEFS_NAME_CSUM_SIZE + PEFS_TWEAK_SIZE + plain_len;
+	/* Resulting name size, count '.' prepended to name */
+	r = PEFS_NAME_NTOP_SIZE(pefs_name_padsize(size)) + 1;
+	if (r > MAXNAMLEN) {
 		return (-ENAMETOOLONG);
 	}
-	if (enc_size < PEFS_NAME_NTOP_SIZE(size) + 1) {
-		printf("pefs: name encryption buffer is too small: length %ld, required %ld\n",
-				enc_size, PEFS_NAME_NTOP_SIZE(size));
+	if (enc_size < r) {
+		printf("pefs: name encryption buffer is too small: length %ld, required %d\n",
+		    enc_size, r);
 		return (-EOVERFLOW);
 	}
 
@@ -502,17 +562,13 @@
 		free_ctx = 1;
 	}
 
-	buf_tweak = buf + PEFS_NAME_CSUM_SIZE;
-	buf_name = buf + PEFS_NAME_CSUM_SIZE + PEFS_TWEAK_SIZE;
-	memcpy(buf_tweak, ptk->ptk_tweak, PEFS_TWEAK_SIZE);
-	memcpy(buf_name, plain, plain_len);
+	memcpy(buf + PEFS_NAME_CSUM_SIZE, ptk->ptk_tweak, PEFS_TWEAK_SIZE);
+	memcpy(buf + PEFS_NAME_CSUM_SIZE + PEFS_TWEAK_SIZE, plain, plain_len);
 
-	pefs_ctx_cpy(ctx, ptk->ptk_key->pk_name_ctx);
-	alg->pa_ivsetup(ctx, magic_tweak_name, 0);
-	alg->pa_crypt(ctx, buf_tweak, buf_tweak, size - PEFS_NAME_CSUM_SIZE);
+	size = pefs_name_pad(buf, size, sizeof(buf));
+	pefs_name_enccbc(ctx, ptk->ptk_key, buf, size);
+	pefs_name_checksum(ctx, ptk->ptk_key, buf, buf, size);
 
-	pefs_name_checksum(ctx, ptk->ptk_key, buf, buf, size, sizeof(buf));
-
 	if (free_ctx)
 		pefs_ctx_free(ctx);
 
@@ -526,36 +582,38 @@
 }
 
 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)
+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 csum[PEFS_NAME_CSUM_SIZE];
-	char *plain_tweak;
 	int free_ctx = 0;
 	int r, ki_rev;
 
 	KASSERT(enc != plain, ("pefs_name_decrypt: ciphertext and plaintext buffers should differ"));
+	MPASS(enc_len > 0 && enc_len <= MAXNAMLEN);
 
-	alg = pk->pk_alg;
-
-	if (enc[0] != '.')
+	if (enc[0] != '.' || enc_len <= 1)
 		return (-EINVAL);
 	enc++;
 	enc_len--;
-	if (PEFS_NAME_PTON_SIZE(enc_len) <= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE)
+
+	r = PEFS_NAME_PTON_SIZE(enc_len);
+	if (r <= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE ||
+	    (r - PEFS_NAME_CSUM_SIZE) % PEFS_NAME_BLOCK_SIZE != 0)
 		return (-EINVAL);
+	if (plain_size < r) {
+		printf("pefs: name decryption buffer is too small: length %ld, required %d\n",
+		    plain_size, r);
+		return (-EOVERFLOW);
+	}
+
 	r = pefs_name_pton(enc, enc_len, plain, plain_size);
 	if (r <= 0) {
 		PEFSDEBUG("pefs_name_decrypt: error: r=%d\n", r);
 		return (-EINVAL);
 	}
-	if (plain_size < pefs_name_checksum_psize(r)) {
-		printf("pefs: name decryption buffer is too small: length %ld, required %ld\n",
-				plain_size, pefs_name_checksum_psize(r));
-		return (-EOVERFLOW);
-	}
-	plain_tweak = plain + PEFS_NAME_CSUM_SIZE;
 
 	if (ctx == NULL) {
 		ctx = pefs_ctx_get();
@@ -565,7 +623,7 @@
 	ki = pk;
 	ki_rev = 0;
 	do {
-		pefs_name_checksum(ctx, ki, csum, plain, r, plain_size);
+		pefs_name_checksum(ctx, ki, csum, plain, r);
 		if (memcmp(csum, plain, PEFS_NAME_CSUM_SIZE) == 0)
 			break;
 
@@ -585,20 +643,23 @@
 		pefs_ctx_free(ctx);
 
 	if (ki == NULL)
-		return (-1);
+		return (-EINVAL);
 
-	pefs_ctx_cpy(ctx, ki->pk_name_ctx);
-	alg->pa_ivsetup(ctx, magic_tweak_name, 0);
-	alg->pa_crypt(ctx, plain_tweak, plain_tweak, r - PEFS_NAME_CSUM_SIZE);
+	pefs_name_deccbc(ctx, ki, plain, r);
 
 	if (ptk) {
 		ptk->ptk_key = ki;
-		memcpy(ptk->ptk_tweak, plain_tweak, PEFS_TWEAK_SIZE);
+		memcpy(ptk->ptk_tweak, plain + PEFS_NAME_CSUM_SIZE,
+		    PEFS_TWEAK_SIZE);
 	}
 
 	r -= PEFS_TWEAK_SIZE + PEFS_NAME_CSUM_SIZE;
 	memcpy(plain, plain + PEFS_NAME_CSUM_SIZE + PEFS_TWEAK_SIZE, r);
 	plain[r] = '\0';
+	/* Remove encryption zero padding */
+	while (r > 0 && plain[r - 1] == '\0')
+		r--;
+	MPASS(r > 0 && strlen(plain) == r);
 
 	return (r);
 }


More information about the p4-projects mailing list