PERFORCE change 167256 for review
Gleb Kurtsou
gk at FreeBSD.org
Wed Aug 12 19:09:47 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167256
Change 167256 by gk at 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>
More information about the p4-projects
mailing list