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>
