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