iAdd support for storing/retrieving an encrypted seed - dedup - deduplicating backup program Err bitreich.org 70 hgit clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ URL:git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ bitreich.org 70 1Log /scm/dedup/log.gph bitreich.org 70 1Files /scm/dedup/files.gph bitreich.org 70 1Refs /scm/dedup/refs.gph bitreich.org 70 1Tags /scm/dedup/tag bitreich.org 70 1README /scm/dedup/file/README.gph bitreich.org 70 1LICENSE /scm/dedup/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit eba08d1ff6618f1b3277dea6990a0afde7a0bc11 /scm/dedup/commit/eba08d1ff6618f1b3277dea6990a0afde7a0bc11.gph bitreich.org 70 1parent 042e687f46e7c334def143a387c332e6884cd078 /scm/dedup/commit/042e687f46e7c334def143a387c332e6884cd078.gph bitreich.org 70 hAuthor: sin URL:mailto:sin@2f30.org bitreich.org 70 iDate: Sun, 19 May 2019 19:26:12 +0300 Err bitreich.org 70 i Err bitreich.org 70 iAdd support for storing/retrieving an encrypted seed Err bitreich.org 70 i Err bitreich.org 70 iThe seed is XOR-ed with the initial state of the chunker to mitigate Err bitreich.org 70 iagainst fingerprinting attacks. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M dup-gc.c | 1 + Err bitreich.org 70 i M dup-init.c | 34 ++++++++++++++++++++----------- Err bitreich.org 70 i M dup-keygen.c | 1 + Err bitreich.org 70 i M dup-pack.c | 3 ++- Err bitreich.org 70 i M dup-rm.c | 1 + Err bitreich.org 70 i M dup-unpack.c | 1 + Err bitreich.org 70 i M state.c | 63 +++++++++++++++++++++++++++++-- Err bitreich.org 70 i M state.h | 9 +++++---- Err bitreich.org 70 i Err bitreich.org 70 i8 files changed, 93 insertions(+), 20 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/dup-gc.c b/dup-gc.c /scm/dedup/file/dup-gc.c.gph bitreich.org 70 i@@ -4,6 +4,7 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 1diff --git a/dup-init.c b/dup-init.c /scm/dedup/file/dup-init.c.gph bitreich.org 70 i@@ -4,11 +4,14 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i #include "arg.h" Err bitreich.org 70 i #include "block.h" Err bitreich.org 70 i #include "config.h" Err bitreich.org 70 i@@ -40,21 +43,21 @@ savestate(char *repo) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i static void Err bitreich.org 70 i-loadkey(char *keyfile) Err bitreich.org 70 i+loadkey(char *keyf) Err bitreich.org 70 i { Err bitreich.org 70 i int fd; Err bitreich.org 70 i Err bitreich.org 70 i- if (keyfile == NULL) Err bitreich.org 70 i+ if (keyf == NULL) Err bitreich.org 70 i return; Err bitreich.org 70 i Err bitreich.org 70 i- fd = open(keyfile, O_RDONLY); Err bitreich.org 70 i+ fd = open(keyf, O_RDONLY); Err bitreich.org 70 i if (fd < 0) Err bitreich.org 70 i- err(1, "open: %s", keyfile); Err bitreich.org 70 i+ err(1, "open: %s", keyf); Err bitreich.org 70 i if (readkey(fd, param.key, sizeof(param.key)) < 0) Err bitreich.org 70 i- printerr("readkey: %s", keyfile); Err bitreich.org 70 i+ printerr("readkey: %s", keyf); Err bitreich.org 70 i param.keyloaded = 1; Err bitreich.org 70 i if (close(fd) < 0) Err bitreich.org 70 i- err(1, "close: %s", keyfile); Err bitreich.org 70 i+ err(1, "close: %s", keyf); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i static void Err bitreich.org 70 i@@ -70,7 +73,7 @@ main(int argc, char *argv[]) Err bitreich.org 70 i char spath[PATH_MAX]; Err bitreich.org 70 i char bpath[PATH_MAX]; Err bitreich.org 70 i struct bctx *bctx; Err bitreich.org 70 i- char *keyfile = NULL; Err bitreich.org 70 i+ char *keyf = NULL; Err bitreich.org 70 i char *repo; Err bitreich.org 70 i int lfd; Err bitreich.org 70 i Err bitreich.org 70 i@@ -79,7 +82,7 @@ main(int argc, char *argv[]) Err bitreich.org 70 i Err bitreich.org 70 i ARGBEGIN { Err bitreich.org 70 i case 'k': Err bitreich.org 70 i- keyfile = EARGF(usage()); Err bitreich.org 70 i+ keyf = EARGF(usage()); Err bitreich.org 70 i break; Err bitreich.org 70 i case 'E': Err bitreich.org 70 i param.ealgo = EARGF(usage()); Err bitreich.org 70 i@@ -105,9 +108,16 @@ main(int argc, char *argv[]) Err bitreich.org 70 i usage(); Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i- if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0 && Err bitreich.org 70 i- keyfile == NULL) Err bitreich.org 70 i- errx(1, "expected encryption key"); Err bitreich.org 70 i+ if (strcasecmp(param.ealgo, "none") == 0) { Err bitreich.org 70 i+ param.seed = 0; Err bitreich.org 70 i+ } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i+ if (keyf == NULL) Err bitreich.org 70 i+ errx(1, "expected encryption key"); Err bitreich.org 70 i+ param.seed = randombytes_uniform(0xffffffff); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (sodium_init() < 0) Err bitreich.org 70 i+ errx(1, "sodium_init: failed"); Err bitreich.org 70 i Err bitreich.org 70 i if (snprintf(spath, sizeof(spath), "%s/%s", Err bitreich.org 70 i repo, ARCHIVEPATH) >= sizeof(spath)) Err bitreich.org 70 i@@ -125,7 +135,7 @@ main(int argc, char *argv[]) Err bitreich.org 70 i if (mkdir(spath, 0700) < 0) Err bitreich.org 70 i err(1, "mkdir: %s", spath); Err bitreich.org 70 i Err bitreich.org 70 i- loadkey(keyfile); Err bitreich.org 70 i+ loadkey(keyf); Err bitreich.org 70 i savestate(repo); Err bitreich.org 70 i Err bitreich.org 70 i if (bcreat(bpath, 0600, &bctx) < 0) Err bitreich.org 70 1diff --git a/dup-keygen.c b/dup-keygen.c /scm/dedup/file/dup-keygen.c.gph bitreich.org 70 i@@ -3,6 +3,7 @@ Err bitreich.org 70 i Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 1diff --git a/dup-pack.c b/dup-pack.c /scm/dedup/file/dup-pack.c.gph bitreich.org 70 i@@ -63,7 +63,8 @@ pack(struct sctx *sctx, struct bctx *bctx) Err bitreich.org 70 i { Err bitreich.org 70 i struct chunker *c; Err bitreich.org 70 i Err bitreich.org 70 i- if ((c = copen(0, BSIZEMIN, BSIZEMAX, HMASKBITS, WINSIZE, 0)) == NULL) Err bitreich.org 70 i+ if ((c = copen(0, BSIZEMIN, BSIZEMAX, HMASKBITS, WINSIZE, Err bitreich.org 70 i+ param.seed)) == NULL) Err bitreich.org 70 i printerr("copen"); Err bitreich.org 70 i Err bitreich.org 70 i while (cfill(c) > 0) { Err bitreich.org 70 1diff --git a/dup-rm.c b/dup-rm.c /scm/dedup/file/dup-rm.c.gph bitreich.org 70 i@@ -4,6 +4,7 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 1diff --git a/dup-unpack.c b/dup-unpack.c /scm/dedup/file/dup-unpack.c.gph bitreich.org 70 i@@ -4,6 +4,7 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 1diff --git a/state.c b/state.c /scm/dedup/file/state.c.gph bitreich.org 70 i@@ -6,6 +6,8 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i #include "config.h" Err bitreich.org 70 i #include "misc.h" Err bitreich.org 70 i #include "state.h" Err bitreich.org 70 i@@ -27,7 +29,9 @@ Err bitreich.org 70 i #define ENONETYPE 0 Err bitreich.org 70 i #define ECHACHATYPE 1 Err bitreich.org 70 i Err bitreich.org 70 i-#define SHDRSIZE 8 Err bitreich.org 70 i+#define MSEEDSIZE 4 Err bitreich.org 70 i+#define CSEEDSIZE (MSEEDSIZE + 16) Err bitreich.org 70 i+#define SHDRSIZE (8 + 24 + CSEEDSIZE) Err bitreich.org 70 i Err bitreich.org 70 i /* misc helpers */ Err bitreich.org 70 i extern int pack(unsigned char *, char *, ...); Err bitreich.org 70 i@@ -35,6 +39,8 @@ extern int unpack(unsigned char *, char *, ...); Err bitreich.org 70 i Err bitreich.org 70 i struct shdr { Err bitreich.org 70 i uint64_t flags; Err bitreich.org 70 i+ unsigned char nonce[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES]; Err bitreich.org 70 i+ unsigned char seed[CSEEDSIZE]; Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i /* Unpack state header */ Err bitreich.org 70 i@@ -43,7 +49,10 @@ unpackshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i { Err bitreich.org 70 i int n; Err bitreich.org 70 i Err bitreich.org 70 i- n = unpack(buf, "q", &shdr->flags); Err bitreich.org 70 i+ n = unpack(buf, "q'24'20", Err bitreich.org 70 i+ &shdr->flags, Err bitreich.org 70 i+ shdr->nonce, Err bitreich.org 70 i+ shdr->seed); Err bitreich.org 70 i assert(n == SHDRSIZE); Err bitreich.org 70 i return n; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -54,7 +63,10 @@ packshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i { Err bitreich.org 70 i int n; Err bitreich.org 70 i Err bitreich.org 70 i- n = pack(buf, "q", shdr->flags); Err bitreich.org 70 i+ n = pack(buf, "q'24'20", Err bitreich.org 70 i+ shdr->flags, Err bitreich.org 70 i+ shdr->nonce, Err bitreich.org 70 i+ shdr->seed); Err bitreich.org 70 i assert(n == SHDRSIZE); Err bitreich.org 70 i return n; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -65,6 +77,11 @@ writestate(int fd, struct param *par) Err bitreich.org 70 i unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i struct shdr shdr; Err bitreich.org 70 i Err bitreich.org 70 i+ if (sodium_init() < 0) { Err bitreich.org 70 i+ seterr("sodium_init: failed"); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i /* Set version */ Err bitreich.org 70 i shdr.flags = (VMAJ << VMAJSHIFT) | VMIN; Err bitreich.org 70 i Err bitreich.org 70 i@@ -80,11 +97,29 @@ writestate(int fd, struct param *par) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Clear seed + authentication tag */ Err bitreich.org 70 i+ memset(shdr.seed, 0, sizeof(shdr.seed)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* Pack seed */ Err bitreich.org 70 i+ shdr.seed[0] = par->seed; Err bitreich.org 70 i+ shdr.seed[1] = par->seed >> 8; Err bitreich.org 70 i+ shdr.seed[2] = par->seed >> 16; Err bitreich.org 70 i+ shdr.seed[3] = par->seed >> 24; Err bitreich.org 70 i+ Err bitreich.org 70 i /* Set encryption type */ Err bitreich.org 70 i if (strcasecmp(par->ealgo, "none") == 0) { Err bitreich.org 70 i shdr.flags |= ENONETYPE << EALGOSHIFT; Err bitreich.org 70 i+ memset(shdr.nonce, 0, sizeof(shdr.nonce)); Err bitreich.org 70 i } else if (strcasecmp(par->ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i+ unsigned long long elen; Err bitreich.org 70 i+ Err bitreich.org 70 i shdr.flags |= ECHACHATYPE << EALGOSHIFT; Err bitreich.org 70 i+ randombytes_buf(shdr.nonce, sizeof(shdr.nonce)); Err bitreich.org 70 i+ crypto_aead_xchacha20poly1305_ietf_encrypt(shdr.seed, &elen, Err bitreich.org 70 i+ shdr.seed, MSEEDSIZE, Err bitreich.org 70 i+ NULL, 0, NULL, Err bitreich.org 70 i+ shdr.nonce, par->key); Err bitreich.org 70 i+ assert(elen == CSEEDSIZE); Err bitreich.org 70 i } else { Err bitreich.org 70 i seterr("invalid encryption type: %s", par->ealgo); Err bitreich.org 70 i return -1; Err bitreich.org 70 i@@ -103,8 +138,14 @@ readstate(int fd, struct param *par) Err bitreich.org 70 i { Err bitreich.org 70 i unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i struct shdr shdr; Err bitreich.org 70 i+ unsigned long long dlen; Err bitreich.org 70 i int algo; Err bitreich.org 70 i Err bitreich.org 70 i+ if (sodium_init() < 0) { Err bitreich.org 70 i+ seterr("sodium_init: failed"); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i if (xread(fd, buf, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i seterr("failed to read state header: %s", strerror(errno)); Err bitreich.org 70 i return -1; Err bitreich.org 70 i@@ -142,10 +183,26 @@ readstate(int fd, struct param *par) Err bitreich.org 70 i break; Err bitreich.org 70 i case ECHACHATYPE: Err bitreich.org 70 i par->ealgo = "XChaCha20-Poly1305"; Err bitreich.org 70 i+ if (crypto_aead_xchacha20poly1305_ietf_decrypt(shdr.seed, &dlen, Err bitreich.org 70 i+ NULL, Err bitreich.org 70 i+ shdr.seed, CSEEDSIZE, Err bitreich.org 70 i+ NULL, 0, Err bitreich.org 70 i+ shdr.nonce, par->key) < 0) { Err bitreich.org 70 i+ seterr("authentication failed"); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ assert(dlen == MSEEDSIZE); Err bitreich.org 70 i break; Err bitreich.org 70 i default: Err bitreich.org 70 i seterr("invalid encryption type: %d", algo); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* Unpack seed */ Err bitreich.org 70 i+ par->seed = (uint32_t)shdr.seed[0]; Err bitreich.org 70 i+ par->seed |= (uint32_t)shdr.seed[1] << 8; Err bitreich.org 70 i+ par->seed |= (uint32_t)shdr.seed[2] << 16; Err bitreich.org 70 i+ par->seed |= (uint32_t)shdr.seed[3] << 24; Err bitreich.org 70 i+ Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/state.h b/state.h /scm/dedup/file/state.h.gph bitreich.org 70 i@@ -1,8 +1,9 @@ Err bitreich.org 70 i struct param { Err bitreich.org 70 i- char *calgo; Err bitreich.org 70 i- char *ealgo; Err bitreich.org 70 i- unsigned char key[KEYSIZE]; Err bitreich.org 70 i- int keyloaded; Err bitreich.org 70 i+ char *calgo; /* compression algorithm */ Err bitreich.org 70 i+ char *ealgo; /* encryption algorithm */ Err bitreich.org 70 i+ unsigned char key[KEYSIZE]; /* secret key */ Err bitreich.org 70 i+ int keyloaded; /* 1 if key is loaded, 0 otherwise */ Err bitreich.org 70 i+ uint32_t seed; /* XOR-ed with initial state of chunker */ Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i extern int writestate(int, struct param *); Err bitreich.org 70 .