iEncrypt/authenticate snapshot metadata - 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 72ba1a8a75b1990156ec209538cc00498efcb43d /scm/dedup/commit/72ba1a8a75b1990156ec209538cc00498efcb43d.gph bitreich.org 70 1parent 9c6cdcc42dc9b0def23ed2839cb528f3867f9cfb /scm/dedup/commit/9c6cdcc42dc9b0def23ed2839cb528f3867f9cfb.gph bitreich.org 70 hAuthor: sin URL:mailto:sin@2f30.org bitreich.org 70 iDate: Sun, 12 May 2019 15:24:55 +0100 Err bitreich.org 70 i Err bitreich.org 70 iEncrypt/authenticate snapshot metadata Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M bencrypt.c | 2 +- Err bitreich.org 70 i M snap.c | 197 +++++++++++++++++++++++++------ Err bitreich.org 70 i Err bitreich.org 70 i2 files changed, 160 insertions(+), 39 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/bencrypt.c b/bencrypt.c /scm/dedup/file/bencrypt.c.gph bitreich.org 70 i@@ -112,7 +112,7 @@ becreat(struct bctx *bctx, char *path, int mode) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- /* Ensure that if caller requested encryption, a key was provided */ Err bitreich.org 70 i+ /* Ensure a key has been provided if caller requested encryption */ Err bitreich.org 70 i if (type != EDNONETYPE && !param.keyloaded) { Err bitreich.org 70 i seterr("expected encryption key"); Err bitreich.org 70 i return -1; Err bitreich.org 70 1diff --git a/snap.c b/snap.c /scm/dedup/file/snap.c.gph bitreich.org 70 i@@ -10,6 +10,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 Err bitreich.org 70 i #include Err bitreich.org 70 i@@ -18,6 +19,7 @@ Err bitreich.org 70 i #include "misc.h" Err bitreich.org 70 i #include "queue.h" Err bitreich.org 70 i #include "snap.h" Err bitreich.org 70 i+#include "state.h" Err bitreich.org 70 i Err bitreich.org 70 i /* snapshot header constants */ Err bitreich.org 70 i #define SHDRMAGIC "SNAPSNAPPYSNOOP" Err bitreich.org 70 i@@ -29,7 +31,9 @@ Err bitreich.org 70 i #define VMAJSHIFT 8 Err bitreich.org 70 i #define VMAJMASK 0xff Err bitreich.org 70 i Err bitreich.org 70 i-#define SHDRSIZE (NSHDRMAGIC + 24 + 24 + 8 + 8) Err bitreich.org 70 i+#define SHDRSIZE (NSHDRMAGIC + 24 + 8 + 8) Err bitreich.org 70 i+ Err bitreich.org 70 i+extern struct param param; 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@@ -38,7 +42,6 @@ extern int unpack(unsigned char *, char *, ...); Err bitreich.org 70 i /* Snapshot header structure */ Err bitreich.org 70 i struct shdr { Err bitreich.org 70 i char magic[NSHDRMAGIC]; /* magic number for file(1) */ Err bitreich.org 70 i- unsigned char nonce[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES]; Err bitreich.org 70 i unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; Err bitreich.org 70 i uint64_t flags; /* version number */ Err bitreich.org 70 i uint64_t nbd; /* number of block hashes */ Err bitreich.org 70 i@@ -52,6 +55,7 @@ struct mdnode { Err bitreich.org 70 i struct sctx { Err bitreich.org 70 i TAILQ_HEAD(mdhead, mdnode) mdhead; /* list of hashes contained in snapshot */ Err bitreich.org 70 i struct mdnode *mdnext; /* next hash to be returned via sget() */ Err bitreich.org 70 i+ int crypto; /* when set, snapshots are encrypted */ Err bitreich.org 70 i int fd; /* underlying snapshot file descriptor */ Err bitreich.org 70 i int rdonly; /* when set, ssync() is a no-op */ Err bitreich.org 70 i struct shdr shdr; /* snapshot header */ Err bitreich.org 70 i@@ -69,9 +73,8 @@ unpackshdr(int fd, struct shdr *shdr) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- n = unpack(buf, "'16'24'24qq", Err bitreich.org 70 i+ n = unpack(buf, "'16'24qq", Err bitreich.org 70 i shdr->magic, Err bitreich.org 70 i- shdr->nonce, Err bitreich.org 70 i shdr->header, Err bitreich.org 70 i &shdr->flags, Err bitreich.org 70 i &shdr->nbd); Err bitreich.org 70 i@@ -87,9 +90,8 @@ packshdr(int fd, struct shdr *shdr) Err bitreich.org 70 i unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i int n; Err bitreich.org 70 i Err bitreich.org 70 i- n = pack(buf, "'16'24'24qq", Err bitreich.org 70 i+ n = pack(buf, "'16'24qq", Err bitreich.org 70 i shdr->magic, Err bitreich.org 70 i- shdr->nonce, Err bitreich.org 70 i shdr->header, Err bitreich.org 70 i shdr->flags, Err bitreich.org 70 i shdr->nbd); Err bitreich.org 70 i@@ -103,52 +105,99 @@ packshdr(int fd, struct shdr *shdr) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i static int Err bitreich.org 70 i-loadmd(struct sctx *sctx) Err bitreich.org 70 i+initmdhead(struct sctx *sctx) Err bitreich.org 70 i { Err bitreich.org 70 i- struct mdnode *mdnode; Err bitreich.org 70 i+ unsigned char ad[SHDRSIZE]; Err bitreich.org 70 i+ struct shdr *shdr; Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i Err bitreich.org 70 i- mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i- if (mdnode == NULL) { Err bitreich.org 70 i- seterr("calloc: %s", strerror(errno)); Err bitreich.org 70 i+ if (lseek(sctx->fd, 0, SEEK_SET) < 0) { Err bitreich.org 70 i+ seterr("lseek: %s", strerror(errno)); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i- if (xread(sctx->fd, mdnode->md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i- free(mdnode); Err bitreich.org 70 i- seterr("failed to read block hash: %s", strerror(errno)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (xread(sctx->fd, ad, sizeof(ad)) != sizeof(ad)) { Err bitreich.org 70 i+ seterr("failed to read snapshot header: %s\n", strerror(errno)); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i- TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-initmdhead(struct sctx *sctx) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct shdr *shdr; Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i Err bitreich.org 70 i shdr = &sctx->shdr; Err bitreich.org 70 i- for (i = 0; i < shdr->nbd; i++) { Err bitreich.org 70 i- if (loadmd(sctx) == 0) Err bitreich.org 70 i- continue; Err bitreich.org 70 i+ if (sctx->crypto) { Err bitreich.org 70 i+ crypto_secretstream_xchacha20poly1305_state state; Err bitreich.org 70 i+ struct shdr *shdr; Err bitreich.org 70 i+ Err bitreich.org 70 i+ shdr = &sctx->shdr; Err bitreich.org 70 i+ if (crypto_secretstream_xchacha20poly1305_init_pull(&state, Err bitreich.org 70 i+ shdr->header, Err bitreich.org 70 i+ param.key) != 0) { Err bitreich.org 70 i+ seterr("invalid crypto header"); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i Err bitreich.org 70 i- /* Cleanup */ Err bitreich.org 70 i- while (!TAILQ_EMPTY(&sctx->mdhead)) { Err bitreich.org 70 i+ for (i = 0; i < shdr->nbd; i++) { Err bitreich.org 70 i+ unsigned char buf[MDSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; Err bitreich.org 70 i+ unsigned char md[MDSIZE]; Err bitreich.org 70 i+ struct mdnode *mdnode; Err bitreich.org 70 i+ unsigned char tag; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (xread(sctx->fd, buf, sizeof(buf)) != sizeof(buf)) { Err bitreich.org 70 i+ seterr("failed to read block hash: %s", strerror(errno)); Err bitreich.org 70 i+ goto err0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (crypto_secretstream_xchacha20poly1305_pull(&state, md, NULL, &tag, Err bitreich.org 70 i+ buf, sizeof(buf), Err bitreich.org 70 i+ ad, sizeof(ad)) != 0) { Err bitreich.org 70 i+ seterr("authentication failed"); Err bitreich.org 70 i+ goto err0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i+ if (mdnode == NULL) { Err bitreich.org 70 i+ seterr("calloc: %s", strerror(errno)); Err bitreich.org 70 i+ goto err0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ memcpy(mdnode->md, md, MDSIZE); Err bitreich.org 70 i+ TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ for (i = 0; i < shdr->nbd; i++) { Err bitreich.org 70 i+ unsigned char md[MDSIZE]; Err bitreich.org 70 i struct mdnode *mdnode; Err bitreich.org 70 i Err bitreich.org 70 i- mdnode = TAILQ_FIRST(&sctx->mdhead); Err bitreich.org 70 i- TAILQ_REMOVE(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i- free(mdnode); Err bitreich.org 70 i+ if (xread(sctx->fd, md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i+ seterr("failed to read block hash: %s", strerror(errno)); Err bitreich.org 70 i+ goto err0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ mdnode = calloc(1, sizeof(*mdnode)); Err bitreich.org 70 i+ if (mdnode == NULL) { Err bitreich.org 70 i+ seterr("calloc: %s", strerror(errno)); Err bitreich.org 70 i+ goto err0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ memcpy(mdnode->md, md, MDSIZE); Err bitreich.org 70 i+ TAILQ_INSERT_TAIL(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i } Err bitreich.org 70 i- return -1; Err bitreich.org 70 i } Err bitreich.org 70 i return 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+err0: Err bitreich.org 70 i+ /* Cleanup */ Err bitreich.org 70 i+ while (!TAILQ_EMPTY(&sctx->mdhead)) { Err bitreich.org 70 i+ struct mdnode *mdnode; Err bitreich.org 70 i+ Err bitreich.org 70 i+ mdnode = TAILQ_FIRST(&sctx->mdhead); Err bitreich.org 70 i+ TAILQ_REMOVE(&sctx->mdhead, mdnode, e); Err bitreich.org 70 i+ free(mdnode); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i int Err bitreich.org 70 i screat(char *path, int mode, struct sctx **sctx) Err bitreich.org 70 i { Err bitreich.org 70 i struct shdr *shdr; Err bitreich.org 70 i+ int crypto; Err bitreich.org 70 i int fd; Err bitreich.org 70 i Err bitreich.org 70 i if (path == NULL || sctx == NULL) { Err bitreich.org 70 i@@ -156,6 +205,22 @@ screat(char *path, int mode, struct sctx **sctx) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Determine algorithm type */ Err bitreich.org 70 i+ if (strcasecmp(param.ealgo, "none") == 0) { Err bitreich.org 70 i+ crypto = 0; Err bitreich.org 70 i+ } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i+ crypto = 1; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ seterr("invalid encryption type: %s", param.ealgo); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* Ensure a key has been provided if caller requested encryption */ Err bitreich.org 70 i+ if (crypto && !param.keyloaded) { Err bitreich.org 70 i+ seterr("expected encryption key"); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } 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@@ -176,6 +241,7 @@ screat(char *path, int mode, struct sctx **sctx) Err bitreich.org 70 i Err bitreich.org 70 i TAILQ_INIT(&(*sctx)->mdhead); Err bitreich.org 70 i (*sctx)->mdnext = NULL; Err bitreich.org 70 i+ (*sctx)->crypto = crypto; Err bitreich.org 70 i (*sctx)->fd = fd; Err bitreich.org 70 i Err bitreich.org 70 i shdr = &(*sctx)->shdr; Err bitreich.org 70 i@@ -196,6 +262,7 @@ int Err bitreich.org 70 i sopen(char *path, int flags, int mode, struct sctx **sctx) Err bitreich.org 70 i { Err bitreich.org 70 i struct shdr *shdr; Err bitreich.org 70 i+ int crypto; Err bitreich.org 70 i int fd; Err bitreich.org 70 i Err bitreich.org 70 i if (path == NULL || sctx == NULL) { Err bitreich.org 70 i@@ -209,6 +276,16 @@ sopen(char *path, int flags, int mode, struct sctx **sctx) Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+ /* Determine algorithm type */ Err bitreich.org 70 i+ if (strcasecmp(param.ealgo, "none") == 0) { Err bitreich.org 70 i+ crypto = 0; Err bitreich.org 70 i+ } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i+ crypto = 1; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ seterr("invalid encryption type: %s", param.ealgo); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } 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@@ -229,6 +306,7 @@ sopen(char *path, int flags, int mode, struct sctx **sctx) Err bitreich.org 70 i Err bitreich.org 70 i TAILQ_INIT(&(*sctx)->mdhead); Err bitreich.org 70 i (*sctx)->mdnext = NULL; Err bitreich.org 70 i+ (*sctx)->crypto = crypto; Err bitreich.org 70 i (*sctx)->fd = fd; Err bitreich.org 70 i (*sctx)->rdonly = 1; Err bitreich.org 70 i Err bitreich.org 70 i@@ -340,16 +418,59 @@ ssync(struct sctx *sctx) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i shdr = &sctx->shdr; Err bitreich.org 70 i- if (packshdr(sctx->fd, shdr) < 0) Err bitreich.org 70 i- return -1; Err bitreich.org 70 i- TAILQ_FOREACH(mdnode, &sctx->mdhead, e) { Err bitreich.org 70 i- if (xwrite(sctx->fd, mdnode->md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i- seterr("failed to write block hash: %s", Err bitreich.org 70 i- strerror(errno)); Err bitreich.org 70 i+ if (sctx->crypto) { Err bitreich.org 70 i+ unsigned char ad[SHDRSIZE]; Err bitreich.org 70 i+ crypto_secretstream_xchacha20poly1305_state state; Err bitreich.org 70 i+ Err bitreich.org 70 i+ crypto_secretstream_xchacha20poly1305_init_push(&state, Err bitreich.org 70 i+ shdr->header, Err bitreich.org 70 i+ param.key); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (packshdr(sctx->fd, shdr) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (lseek(sctx->fd, 0, SEEK_SET) < 0) { Err bitreich.org 70 i+ seterr("lseek: %s", strerror(errno)); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (xread(sctx->fd, ad, sizeof(ad)) != sizeof(ad)) { Err bitreich.org 70 i+ seterr("failed to read snapshot header: %s\n", strerror(errno)); Err bitreich.org 70 i return -1; Err bitreich.org 70 i } Err bitreich.org 70 i+ Err bitreich.org 70 i+ TAILQ_FOREACH(mdnode, &sctx->mdhead, e) { Err bitreich.org 70 i+ unsigned char buf[MDSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; Err bitreich.org 70 i+ unsigned char tag; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (TAILQ_LAST(&sctx->mdhead, mdhead) == mdnode) Err bitreich.org 70 i+ tag = crypto_secretstream_xchacha20poly1305_TAG_FINAL; Err bitreich.org 70 i+ else Err bitreich.org 70 i+ tag = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ crypto_secretstream_xchacha20poly1305_push(&state, Err bitreich.org 70 i+ buf, NULL, Err bitreich.org 70 i+ mdnode->md, MDSIZE, Err bitreich.org 70 i+ ad, sizeof(ad), tag); Err bitreich.org 70 i+ if (xwrite(sctx->fd, buf, sizeof(buf)) != sizeof(buf)) { Err bitreich.org 70 i+ seterr("failed to write block hash: %s", Err bitreich.org 70 i+ strerror(errno)); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ if (packshdr(sctx->fd, shdr) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ TAILQ_FOREACH(mdnode, &sctx->mdhead, e) { Err bitreich.org 70 i+ if (xwrite(sctx->fd, mdnode->md, MDSIZE) != MDSIZE) { Err bitreich.org 70 i+ seterr("failed to write block hash: %s", Err bitreich.org 70 i+ strerror(errno)); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i } Err bitreich.org 70 i fsync(sctx->fd); Err bitreich.org 70 i+ Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 .