summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux2022-04-05 15:35:02 +0200
committerQuentin Carbonneaux2022-04-05 15:35:02 +0200
commit737202fcafa7812d5d758c8e360a142b4b11dd43 (patch)
treeba3e4866aaf4e16c588e1c2ab4954e184bc340b4
parent8fe4eaa0fbfd2b92071ab1d4de7ef84adfa3db00 (diff)
sdar overhaul
- new Slice API for managing buffers; it wraps the error-prone APIs from nacl - kill use of global static buffers; the new slice API offers allocation and freeing functions that should be efficient
-rw-r--r--sdar/all.h78
-rw-r--r--sdar/arch.c276
-rw-r--r--sdar/cache.c8
-rw-r--r--sdar/crypt.c77
-rw-r--r--sdar/hmac.c13
-rw-r--r--sdar/key.c48
-rw-r--r--sdar/lib/crypto/scrypt.c10
-rw-r--r--sdar/lib/crypto/smix.c4
-rw-r--r--sdar/main.c104
-rw-r--r--sdar/sdar.120
-rw-r--r--sdar/slice.c158
-rw-r--r--sdar/stash.c314
-rw-r--r--sdar/util.c8
-rw-r--r--sdar/write.c (renamed from sdar/writer.c)77
14 files changed, 644 insertions, 551 deletions
diff --git a/sdar/all.h b/sdar/all.h
index e54d203..47972a0 100644
--- a/sdar/all.h
+++ b/sdar/all.h
@@ -6,6 +6,8 @@
enum {
Plnpad = 32,
Cippad = 16,
+ Cipovh = Plnpad - Cippad,
+ Bufpad = 32,
Prepsz = 32,
Noncesz = 24,
Hmacsz = 32,
@@ -19,10 +21,7 @@ enum {
Indexsz = Maxblk / Entrysz,
Magicsz = 8,
Segmetasz = 8 + 8 + 8 + 128,
- Seghdsz =
- Magicsz + Keysz +
- (Plnpad - Cippad) +
- Segmetasz,
+ Seghdsz = Magicsz + Keysz + Cipovh + Segmetasz,
Segitemsz = Hmacsz + 4,
Permf = 0666,
@@ -47,17 +46,24 @@ typedef struct Loghd Loghd;
typedef struct Reader Reader;
typedef struct Segfile Segfile;
typedef struct Segmeta Segmeta;
+typedef struct Slice Slice;
typedef struct Writer Writer;
typedef uchar hmac_t[Hmacsz];
-typedef int flushcb(void *, hmac_t, uchar *, int);
-typedef int blockcb(Block *, hmac_t, uchar *, void *);
+typedef int flushcb(void *, hmac_t, Slice);
+typedef int blockcb(Block *, hmac_t, uchar[Prepsz], void *);
+
+
+struct Slice {
+ uchar *buf;
+ long len;
+};
struct Key {
uchar *hmac;
- uchar *masterpub;
- uchar *mastersec;
+ uchar *pub;
+ uchar *sec;
};
struct Block {
@@ -98,7 +104,7 @@ struct Reader {
/* open segment */
FILE *segf;
int segno;
- uchar segpre[Prepsz];
+ uchar segp[Prepsz];
};
struct Writer {
@@ -109,7 +115,7 @@ struct Writer {
vlong vlen;
vlong vlen0;
Ilevel level[2];
- uchar buf[Plnpad + 2*Maxblk];
+ uchar buf[Bufpad + 2*Maxblk];
};
struct Segmeta {
@@ -125,8 +131,8 @@ struct Segfile {
};
struct Loghd {
- uchar kpub[Keysz];
- uchar kpre[Prepsz];
+ uchar segk[Keysz];
+ uchar segp[Prepsz];
vlong nitem;
vlong dlen;
};
@@ -151,10 +157,6 @@ struct Addr {
#define MAKESURE(what, x) _Static_assert(x, #what)
#define min(a, b) ((a) > (b) ? (b) : (a))
-#define sizeof (vlong)sizeof
-
-extern uchar iobuf[Maxblk];
-extern uchar inflate[Maxblk];
/* util.c */
extern FILE *flog;
@@ -165,6 +167,7 @@ char *segs(uchar[Segidsz]);
char *hmacs(hmac_t);
void hmaccpy(hmac_t, hmac_t);
FILE *fopenat(int, int, char *, ...);
+int flushsync(FILE *);
void enc32be(uchar *, uvlong);
void enc32le(uchar *, uvlong);
void enc64be(uchar *, uvlong);
@@ -172,12 +175,18 @@ uvlong dec32be(uchar *);
uvlong dec32le(uchar *);
uvlong dec64be(uchar *);
-/* crypt.c */
-extern uchar plain[Plnpad + Maxblk];
-extern uchar cipher[Plnpad + Maxblk];
-char *cread(FILE *, uchar *, vlong, long);
-char *creadp(FILE *, uchar *, vlong, long);
-char *cwritep(FILE *, uchar *, vlong, uchar *, long);
+/* slice.c */
+Slice mksl(uchar *, long);
+Slice newsl();
+void freesl(Slice);
+void sldeflate(Slice *, Slice);
+int slinflate(Slice *, Slice);
+void slencryptp(Slice *, Slice, uchar[Prepsz], vlong);
+int sldecryptp(Slice *, Slice, uchar[Prepsz], vlong);
+int decrypt(Slice *, FILE *, long, uchar[Prepsz], vlong);
+void slhmac(Slice, hmac_t);
+int slwrite(Slice, FILE *);
+int slread(Slice *, long, FILE *);
/* key.c */
extern Key key;
@@ -207,33 +216,26 @@ void readerinit(Reader *, Arch *);
int readerstart(Reader *, Addr *, vlong);
void readerdone(Reader *);
int readerseek(Reader *, vlong);
-int reader(Reader *, uchar **, long *);
-void encmeta(uchar *, Segmeta *);
+int reader(Reader *, Slice *);
+void encmeta(Slice *, Segmeta *);
void decitem(uchar *, Block *);
-int walkblocks(FILE *, blockcb *, void *);
+int walkblocks(FILE *, blockcb, void *);
/* stash.c */
int stashinit(Arch *);
int stashadd(Arch *, uchar *, vlong);
-int stashblk(Arch *, hmac_t, int, uchar *, int);
+int stashblk(Arch *, hmac_t, int, Slice);
int stashdone(Arch *, Addr *);
int stashsync(Arch *);
int stashcommit(Arch *, char *, uchar[Segidsz]);
-/* writer.c */
+/* write.c */
void writerinit(Writer *, flushcb *, void *);
int writer(Writer *, uchar *, vlong);
int writerdone(Writer *, Addr *);
-int getlevel(Ilevel *, uchar *, long);
-
-/* hmac.c */
-void hmac_blake3(uchar *, long, uchar *, long, hmac_t);
+int declevel(Ilevel *, Slice);
/* lib/crypto */
-void crypto_scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *);
-int crypto_scrypt(
- uint8_t *passwd, size_t passwdlen, uint8_t *salt, size_t saltlen,
- uint64_t N, uint32_t _r, uint32_t _p, uint8_t *buf, size_t buflen);
-int crypto_scrypt_test();
-void pbkdf2_sha256(uchar *p, size_t np, uint8_t *s, size_t ns,
- uint64_t c, uint8_t *buf, size_t dkLen);
+void scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *);
+int scrypt(uint8_t *, size_t, uint8_t *, size_t, uint64_t, uint32_t, uint32_t, uint8_t *, size_t);
+void pbkdf2_sha256(uchar *, size_t, uint8_t *, size_t, uint64_t, uint8_t *, size_t);
diff --git a/sdar/arch.c b/sdar/arch.c
index 14160ef..104783c 100644
--- a/sdar/arch.c
+++ b/sdar/arch.c
@@ -12,6 +12,8 @@
typedef struct Cacheblk Cacheblk;
+typedef int walkcb(Arch *, uchar[Segidsz], void *);
+
struct Cacheblk {
Cache *cache;
int segno;
@@ -24,7 +26,7 @@ uchar segmagic[Magicsz] = {
uchar inflate[Maxblk];
static int
-walkseg(Arch *a, int fn(Arch *, uchar[Segidsz], void *), void *arg)
+walkseg(Arch *a, walkcb fn, void *arg)
{
uchar segid[Segidsz];
struct dirent *de;
@@ -51,8 +53,7 @@ walkseg(Arch *a, int fn(Arch *, uchar[Segidsz], void *), void *arg)
logs("W ignoring seg/%s", de->d_name);
continue;
}
- err = fn(a, segid, arg);
- if (err)
+ if ((err = fn(a, segid, arg)) != 0)
break;
}
@@ -64,12 +65,13 @@ walkseg(Arch *a, int fn(Arch *, uchar[Segidsz], void *), void *arg)
}
void
-encmeta(uchar *buf, Segmeta *meta)
+encmeta(Slice *s, Segmeta *meta)
{
- enc64be(buf, meta->nitem);
- enc64be(buf + 8, meta->dlen);
- enc64be(buf + 16, meta->date);
- memcpy(buf + 24, meta->msg, sizeof meta->msg);
+ enc64be(s->buf, meta->nitem);
+ enc64be(s->buf + 8, meta->dlen);
+ enc64be(s->buf + 16, meta->date);
+ memcpy(s->buf + 24, meta->msg, sizeof meta->msg);
+ s->len = Segmetasz;
}
static void
@@ -82,70 +84,87 @@ decmeta(uchar *buf, Segmeta *meta)
}
void
-decitem(uchar *buf, Block *b)
+decitem(uchar *p, Block *b)
{
- b->len = dec32be(buf + Hmacsz);
+ b->len = dec32be(p + Hmacsz);
b->lz4 = b->len & 1;
b->len >>= 1;
}
-int
-walkblocks(FILE *f, blockcb *fn, void *arg)
+static int
+prepseg(FILE *f, uchar prep[Prepsz])
{
- static uchar scratch[sizeof plain];
- uchar buf[Magicsz + Keysz];
- uchar *it, *end, *segkey;
- vlong idx, blk, sz, rd;
- Segmeta meta;
- char *e;
- Block b = {.off = 0};
-
- if (fread(buf, sizeof buf, 1, f) != 1
- || memcmp(segmagic, buf, Magicsz) != 0) {
- logs("E invalid header");
+ uchar seghd[Magicsz + Keysz];
+
+ if (fread(seghd, sizeof seghd, 1, f) != 1
+ || memcmp(segmagic, seghd, Magicsz) != 0) {
+ logs("E invalid semment header");
return 1;
}
+ crypto_box_beforenm(prep, seghd + Magicsz, key.sec);
+ return 0;
+}
- segkey = buf + Magicsz;
- e = cread(f, segkey, -1, Segmetasz);
- if (e) {
- logs("E cannot read metadata (%s)", e);
+int
+walkblocks(FILE *f, blockcb fn, void *arg)
+{
+ uchar segp[Prepsz];
+ Slice s;
+ uchar *p, *pp;
+ vlong n, len, idx;
+ Segmeta m;
+ Block b;
+ int err;
+
+ if (prepseg(f, segp))
return 1;
+
+ err = 1;
+ s = newsl();
+
+ if (decrypt(&s, f, Segmetasz, segp, -1)) {
+ logs("E cannot read metadata");
+ goto out;
}
- decmeta(plain + Plnpad, &meta);
+ decmeta(s.buf, &m);
- if (fseek(f, meta.dlen, SEEK_CUR))
- return 1;
+ if (fseek(f, m.dlen, SEEK_CUR) == -1)
+ goto out;
+ b.off = 0;
idx = -1;
- sz = meta.nitem * Segitemsz;
- blk = (Maxblk / Segitemsz) * Segitemsz;
- for (; sz > 0; sz -= rd) {
- rd = min(sz, blk);
- e = cread(f, segkey, --idx, rd);
- if (e) {
- logs("E cannot read items (%s)", e);
- return 1;
+ len = m.nitem * Segitemsz;
+ while (len > 0) {
+ n = (Maxblk/Segitemsz) * Segitemsz;
+ n = min(len, n);
+ len -= n;
+ if (decrypt(&s, f, n, segp, --idx)) {
+ logs("E cannot read items");
+ goto out;
}
- memcpy(scratch, plain, Plnpad+rd);
- it = scratch + Plnpad;
- end = it + rd;
- for (; it != end; it += Segitemsz) {
- decitem(it, &b);
- if (fn(&b, it, segkey, arg))
- return 1;
- b.off += b.len + (Plnpad - Cippad);
+ p = s.buf;
+ pp = p + n;
+ while (p < pp) {
+ decitem(p, &b);
+ if (fn(&b, p, segp, arg))
+ goto out;
+ b.off += b.len + Cipovh;
+ p += Segitemsz;
}
}
- return 0;
+ err = 0;
+
+out:
+ freesl(s);
+ return err;
}
static int
-cacheblk(Block *b, hmac_t hmac, uchar *key, void *arg)
+cacheblk(Block *b, hmac_t hmac, uchar segp[Prepsz], void *arg)
{
Cacheblk *cb;
- (void)key;
+ (void)segp;
cb = arg;
b->seg = cb->segno;
if (cput(cb->cache, hmac, b)) {
@@ -176,8 +195,8 @@ indexseg(Arch *a, uchar segid[Segidsz])
}
/* returns 2 when a new segment cannot be
- * indexed because the master key is not
- * available */
+ * indexed because the archive secret key
+ * is not available */
static int
addseg(Arch *a, uchar segid[Segidsz], void *arg)
{
@@ -185,14 +204,14 @@ addseg(Arch *a, uchar segid[Segidsz], void *arg)
int n;
if (cgetseg(&a->cache, segid, &n)) {
- if (!key.mastersec)
+ if (!key.sec)
return 2;
/* index the unknown segment */
if (indexseg(a, segid))
return 1;
n = a->nseg;
p = realloc(a->seg, n*sizeof *p);
- if (!p) {
+ if (p == 0) {
a->nseg--;
return 1;
}
@@ -215,7 +234,7 @@ readcache(Arch *a)
{
int nold, nin;
- /* TODO, grab a lock if writing */
+ /* TODO: grab a lock if writing */
if (cinit(&a->cache, a->fd, "cache", 0)) {
if (errno != ENOENT)
@@ -226,6 +245,8 @@ readcache(Arch *a)
a->nseg = a->cache.meta->nseg;
a->seg = calloc(a->nseg, sizeof a->seg[0]);
+ if (a->seg == 0)
+ goto error;
nold = a->nseg;
nin = 0;
switch (walkseg(a, addseg, &nin)) {
@@ -233,7 +254,7 @@ readcache(Arch *a)
creset(&a->cache);
goto error;
case 2:
- logs("W could not update cache in write operation");
+ logs("W archive open in write-only mode");
goto error;
}
a->cache.meta->nseg = a->nseg;
@@ -257,19 +278,21 @@ archinit(Arch *a, char *path)
logs("E %s/seg does not exist", path);
goto error;
}
+
a->fd = fd;
a->log = 0;
a->data = 0;
a->logh = 0;
if (readcache(a)) {
- logs("E could not initialize archive cache");
+ logs("E cache init failed");
goto error;
}
+
return 0;
error:
- close(fd);
memset(a, 0, sizeof *a);
+ close(fd);
return 1;
}
@@ -304,60 +327,67 @@ archhas(Arch *a, hmac_t hmac)
}
static int
-readblock(Reader *r, hmac_t hmac, Block *b, uchar **data, long *blen)
+openseg(Reader *r, uchar *segid, int segno)
{
- uchar buf[Magicsz + Keysz];
- hmac_t check;
- char *src, *dst, *seg;
- int decomp;
FILE *f;
- if (cget(&r->arch->cache, hmac, b)) {
- logs("E missing block %s", hmacs(hmac));
+ f = fopenat(r->arch->fd, O_RDONLY, segs(segid));
+ if (f == 0)
+ return 1;
+ if (prepseg(f, r->segp)) {
+ fclose(f);
return 1;
}
- if (!getsegid(r->arch, b->seg)) {
- logs("W block %s in deleted segment", hmacs(hmac));
+ if (r->segf != 0)
+ fclose(r->segf);
+ r->segf = f;
+ r->segno = segno;
+ return 0;
+}
+
+static int
+readblock(Reader *r, hmac_t hmac, Block *b, Slice *ps)
+{
+ hmac_t bhmac;
+ Slice s;
+ uchar *segid, *segp;
+ FILE *segf;
+ vlong off;
+ int len, err;
+
+ if (cget(&r->arch->cache, hmac, b)
+ || (segid = getsegid(r->arch, b->seg)) == 0) {
+ logs("E block %s not found", hmacs(hmac));
return 1;
}
+ off = b->off;
+ len = b->len;
- if (!r->segf || r->segno != b->seg) {
- if (r->segf)
- fclose(r->segf);
- seg = segs(getsegid(r->arch, b->seg));
- f = fopenat(r->arch->fd, O_RDONLY, seg);
- r->segf = f;
- r->segno = b->seg;
- if (!f)
- goto error;
- if (fread(buf, sizeof buf, 1, f) != 1)
+ if (r->segf == 0 || r->segno != b->seg)
+ if (openseg(r, segid, b->seg)) {
+ logs("E cannot open segment");
goto error;
- assert(key.mastersec);
- crypto_box_beforenm(r->segpre, buf + Magicsz, key.mastersec);
- }
+ }
+ segf = r->segf;
+ segp = r->segp;
- if (fseek(r->segf, Seghdsz + b->off, SEEK_SET))
- goto error;
- if (creadp(r->segf, r->segpre, b->off, b->len))
+ if (fseek(segf, Seghdsz + off, SEEK_SET) == -1)
goto error;
if (b->lz4) {
- src = (char*)plain + Plnpad;
- dst = (char*)inflate;
- decomp = LZ4_decompress_safe(src, dst, b->len, Maxblk);
- if (decomp < 0) {
- logs("E lz4 decompression failure");
- goto error;
- }
- *data = inflate;
- *blen = decomp;
- } else {
- *data = plain + Plnpad;
- *blen = b->len;
+ s = newsl();
+ err = decrypt(&s, segf, len, segp, off);
+ err = err || slinflate(ps, s);
+ freesl(s);
+ } else
+ err = decrypt(ps, segf, len, segp, off);
+ if (err) {
+ logs("E decrypt/inflate failed");
+ goto error;
}
- assert(key.hmac);
- hmac_blake3(key.hmac, Keysz, *data, *blen, check);
- if (memcmp(hmac, check, Hmacsz) != 0) {
+ slhmac(*ps, bhmac);
+ if (ps->len != len
+ || memcmp(hmac, bhmac, Hmacsz) != 0) {
logs("E corrupt block");
goto error;
}
@@ -365,13 +395,8 @@ readblock(Reader *r, hmac_t hmac, Block *b, uchar **data, long *blen)
return 0;
error:
- seg = segs(getsegid(r->arch, b->seg));
logs("E read failed for %s", hmacs(hmac));
- logs("E at %s off:%lld len:%d", seg, b->off, b->len);
- if (r->segf) {
- fclose(r->segf);
- r->segf = 0;
- }
+ logs("E at %s off:%lld len:%d", segs(segid), off, len);
return 1;
}
@@ -379,16 +404,15 @@ static int
readlevel(Reader *rd, hmac_t hmac, Ilevel *l)
{
Block b;
- uchar *data;
- long blen;
+ Slice s;
+ int err;
- if (readblock(rd, hmac, &b, &data, &blen))
- return 1;
- if (getlevel(l, data, blen)) {
+ s = newsl();
+ err = readblock(rd, hmac, &b, &s);
+ if (!err && (err = declevel(l, s)))
logs("E invalid level %s", hmacs(hmac));
- return 1;
- }
- return 0;
+ freesl(s);
+ return err;
}
void
@@ -405,9 +429,11 @@ readerstart(Reader *r, Addr *addr, vlong off)
Ientry *ent;
hmac_t hmac;
+ assert(key.sec);
+
r->pos1 = 0;
r->pos = 0;
- hmaccpy(r->hmac0, (hmac_t){0});
+ memset(r->hmac0, 0, Hmacsz);
l = r->level;
l[0].nent = 0;
l[1].nent = 0;
@@ -490,30 +516,28 @@ readerseek(Reader *r, vlong pos)
}
int
-reader(Reader *r, uchar **data, long *len)
+reader(Reader *r, Slice *s)
{
- Ientry *e;
- vlong pos;
Block b;
- long n, blen;
+ vlong pos;
+ long n;
+ Ientry *e;
if (readerseek(r, r->pos))
return 1;
pos = r->pos1;
e = findentry(&r->level[0], &pos, r->pos);
-
- if (readblock(r, e->hmac, &b, data, &blen))
+ if (readblock(r, e->hmac, &b, s))
return 1;
- if (r->pos >= pos + blen) {
- *len = 0;
- *data = 0;
+ if (r->pos >= pos + b.len) {
+ s->len = 0;
return 0;
}
-
n = r->pos - pos;
- *data += n;
- *len = blen - n;
-
- r->pos += *len;
+ if (n != 0) {
+ s->len -= n;
+ memmove(s->buf, s->buf + n, s->len);
+ }
+ r->pos += s->len;
return 0;
}
diff --git a/sdar/cache.c b/sdar/cache.c
index a44cc5e..b3bb4fd 100644
--- a/sdar/cache.c
+++ b/sdar/cache.c
@@ -14,23 +14,23 @@ static uchar cachemagic[4] = {
};
int
-cinit(Cache *c, int afd, char *path, int new)
+cinit(Cache *c, int afd, char *path, int create)
{
int flags, fd;
c->meta = 0;
flags = O_RDWR;
- if (new)
+ if (create)
flags |= O_CREAT|O_TRUNC;
fd = openat(afd, path, flags, Permf);
if (fd == -1)
return 1;
- if (mmhmap(&c->hash, fd, new) == -1) {
+ if (mmhmap(&c->hash, fd, create) == -1) {
close(fd);
return 1;
}
c->meta = mmhhdr(&c->hash);
- if (new)
+ if (create)
creset(c);
if (memcmp(c->meta->magic, cachemagic, 4) != 0) {
logs("E invalid cache file %s", path);
diff --git a/sdar/crypt.c b/sdar/crypt.c
deleted file mode 100644
index a7f8465..0000000
--- a/sdar/crypt.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "all.h"
-#include <stdio.h>
-#include <string.h>
-#include <crypto_box.h>
-
-MAKESURE(nacl_nonce_len_is_Noncesz, crypto_box_NONCEBYTES == Noncesz);
-MAKESURE(nacl_pubkey_len_is_Keysz, crypto_box_PUBLICKEYBYTES == Keysz);
-MAKESURE(nacl_seckey_len_is_Keysz, crypto_box_SECRETKEYBYTES == Keysz);
-MAKESURE(nacl_plain_pad_is_Plnpad, crypto_box_ZEROBYTES == Plnpad);
-MAKESURE(nacl_cipher_pad_is_Cippad, crypto_box_BOXZEROBYTES == Cippad);
-MAKESURE(nacl_prep_len_is_Prepsz, crypto_box_BEFORENMBYTES == Prepsz);
-MAKESURE(cipher_pad_leq_plain_pad, Cippad <= Plnpad);
-
-uchar plain[Plnpad + Maxblk];
-uchar cipher[Plnpad + Maxblk];
-
-static void
-noncegen(uchar *dst, vlong i)
-{
- memset(dst, 0, Noncesz);
- enc64be(dst, dec64be(dst) + (uvlong)i);
-}
-
-char *
-cread(FILE *f, uchar *sendkey, vlong nonceidx, long sz)
-{
- uchar prep[Prepsz];
-
- assert(key.mastersec);
-
- crypto_box_beforenm(prep, sendkey, key.mastersec);
- return creadp(f, prep, nonceidx, sz);
-}
-
-char *
-creadp(FILE *f, uchar *prep, vlong nonceidx, long sz)
-{
- uchar nonce[Noncesz];
- long cryptsz;
-
- if (Plnpad + sz > sizeof cipher)
- return "too big";
-
- cryptsz = (Plnpad - Cippad) + sz;
- if ((long)fread(cipher + Cippad, 1, cryptsz, f) != cryptsz)
- return "could not read file";
- sz += Plnpad;
-
- memset(cipher, 0, Cippad);
- noncegen(nonce, nonceidx);
- if (crypto_box_open_afternm(plain, cipher, sz, nonce, prep) != 0)
- return "decryption failure";
-
- return 0;
-}
-
-char *
-cwritep(FILE *f, uchar *prep, vlong nonceidx, uchar *buf, long sz)
-{
- uchar nonce[Noncesz];
-
- assert(key.masterpub);
- assert(sz >= Plnpad);
-
- if (sz > sizeof cipher)
- return "too big";
-
- memset(buf, 0, Plnpad);
- noncegen(nonce, nonceidx);
- crypto_box_afternm(cipher, buf, sz, nonce, prep);
-
- sz -= Cippad;
- if ((long)fwrite(&cipher[Cippad], 1, sz, f) != sz)
- return "could not write file";
-
- return 0;
-}
diff --git a/sdar/hmac.c b/sdar/hmac.c
deleted file mode 100644
index d68723e..0000000
--- a/sdar/hmac.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "all.h"
-#include <blake3.h>
-
-void
-hmac_blake3(uchar *key, long nk, uchar *buf, long sz, hmac_t hmac)
-{
- blake3_hasher bh;
-
- assert(nk == BLAKE3_KEY_LEN);
- blake3_hasher_init_keyed(&bh, key);
- blake3_hasher_update(&bh, buf, sz);
- blake3_hasher_finalize(&bh, hmac, 32);
-}
diff --git a/sdar/key.c b/sdar/key.c
index 6a92454..a706a6c 100644
--- a/sdar/key.c
+++ b/sdar/key.c
@@ -27,18 +27,18 @@ static uchar keymagic[Magicsz] = {
Key key;
static uchar hmac[Keysz];
-static uchar masterpub[Keysz];
-static uchar mastersec[Plnpad + Keysz];
+static uchar pub[Keysz];
+static uchar sec[Plnpad + Keysz];
void
keygen()
{
randombytes(hmac, Keysz);
- crypto_box_keypair(masterpub, mastersec + Plnpad);
+ crypto_box_keypair(pub, sec + Plnpad);
key.hmac = hmac;
- key.masterpub = masterpub;
- key.mastersec = mastersec + Plnpad;
+ key.pub = pub;
+ key.sec = sec + Plnpad;
}
void
@@ -49,8 +49,8 @@ keydump()
vlong off;
} *p, parts[] = {
{ "hmac: ", offsetof(Key, hmac) },
- { "masterpub: ", offsetof(Key, masterpub) },
- { "mastersec: ", offsetof(Key, mastersec) },
+ { "pub: ", offsetof(Key, pub) },
+ { "sec: ", offsetof(Key, sec) },
{0}
};
uchar *k;
@@ -69,9 +69,9 @@ keydump()
enum {
Osalt = Magicsz,
Ohmackey = Osalt + Saltsz,
- Omasterpub = Ohmackey + Keysz,
- Omastersec = Omasterpub + Keysz,
- Oend = Omastersec + (Plnpad - Cippad) + Keysz,
+ Opub = Ohmackey + Keysz,
+ Osec = Opub + Keysz,
+ Oend = Osec + (Plnpad - Cippad) + Keysz,
};
int
@@ -82,21 +82,21 @@ keywrite(char *p, long np, FILE *f)
uchar buf[Oend];
int ret;
- assert(key.mastersec);
+ assert(key.sec);
memcpy(buf, keymagic, Magicsz);
randombytes(buf + Osalt, Saltsz);
memcpy(buf + Ohmackey, key.hmac, Keysz);
- memcpy(buf + Omasterpub, key.masterpub, Keysz);
+ memcpy(buf + Opub, key.pub, Keysz);
- ret = crypto_scrypt((uint8_t*)p, np, buf + Osalt, Saltsz,
+ ret = scrypt((uint8_t*)p, np, buf + Osalt, Saltsz,
ScryptN, Scryptr, Scryptp, nk, sizeof nk);
if (ret != 0)
return 1;
- memset(mastersec, 0, Plnpad);
- crypto_secretbox(cip, mastersec, Plnpad + Keysz, nk, nk + Noncesz);
- memcpy(buf + Omastersec, cip + Cippad, Oend - Omastersec);
+ memset(sec, 0, Plnpad);
+ crypto_secretbox(cip, sec, Plnpad + Keysz, nk, nk + Noncesz);
+ memcpy(buf + Osec, cip + Cippad, Oend - Osec);
return (fwrite(buf, Oend, 1, f) != 1);
}
@@ -113,10 +113,10 @@ keyreadpub(FILE *f)
return "invalid key file";
memcpy(hmac, buf + Ohmackey, Keysz);
- memcpy(masterpub, buf + Omasterpub, Keysz);
+ memcpy(pub, buf + Opub, Keysz);
key.hmac = hmac;
- key.masterpub = masterpub;
+ key.pub = pub;
return 0;
}
@@ -136,23 +136,23 @@ keyreadsec(char *p, long np, FILE *f)
return "invalid key file";
memcpy(hmac, buf + Ohmackey, Keysz);
- memcpy(masterpub, buf + Omasterpub, Keysz);
+ memcpy(pub, buf + Opub, Keysz);
- ret = crypto_scrypt((uint8_t*)p, np, buf + Osalt, Saltsz,
+ ret = scrypt((uint8_t*)p, np, buf + Osalt, Saltsz,
ScryptN, Scryptr, Scryptp, nk, sizeof nk);
if (ret != 0)
return "out of memory";
- memcpy(cip + Cippad, buf + Omastersec, Oend - Omastersec);
+ memcpy(cip + Cippad, buf + Osec, Oend - Osec);
memset(cip, 0, Cippad);
- ret = crypto_secretbox_open(mastersec, cip, Plnpad + Keysz,
+ ret = crypto_secretbox_open(sec, cip, Plnpad + Keysz,
nk, nk + Noncesz);
if (ret != 0)
return "decryption failed";
key.hmac = hmac;
- key.masterpub = masterpub;
- key.mastersec = mastersec + Plnpad;
+ key.pub = pub;
+ key.sec = sec + Plnpad;
return 0;
}
diff --git a/sdar/lib/crypto/scrypt.c b/sdar/lib/crypto/scrypt.c
index 3f53e0a..730321c 100644
--- a/sdar/lib/crypto/scrypt.c
+++ b/sdar/lib/crypto/scrypt.c
@@ -35,7 +35,7 @@
#include <sys/mman.h>
/**
- * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
+ * scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
* p, buflen) and write the result into buf. The parameters r, p, and buflen
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
@@ -44,7 +44,7 @@
* Return 0 on success; or -1 on error.
*/
int
-crypto_scrypt(uint8_t * passwd, size_t passwdlen,
+scrypt(uint8_t * passwd, size_t passwdlen,
uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,
uint8_t * buf, size_t buflen)
{
@@ -123,7 +123,7 @@ crypto_scrypt(uint8_t * passwd, size_t passwdlen,
/* 2: for i = 0 to p - 1 do */
for (i = 0; i < p; i++) {
/* 3: B_i <-- MF(B_i, N) */
- crypto_scrypt_smix(&B[i * 128 * r], r, N, V, XY);
+ scrypt_smix(&B[i * 128 * r], r, N, V, XY);
}
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
@@ -178,12 +178,12 @@ static struct scrypt_test {
};
int
-crypto_scrypt_test()
+scrypt_test()
{
uint8_t hbuf[TESTLEN];
/* Perform the computation. */
- if (crypto_scrypt(
+ if (scrypt(
(uint8_t *)testcase.passwd, strlen(testcase.passwd),
(uint8_t *)testcase.salt, strlen(testcase.salt),
testcase.N, testcase.r, testcase.p, hbuf, TESTLEN))
diff --git a/sdar/lib/crypto/smix.c b/sdar/lib/crypto/smix.c
index 9166d2e..f2a955b 100644
--- a/sdar/lib/crypto/smix.c
+++ b/sdar/lib/crypto/smix.c
@@ -143,7 +143,7 @@ integerify(const void * B, size_t r)
}
/**
- * crypto_scrypt_smix(B, r, N, V, XY):
+ * scrypt_smix(B, r, N, V, XY):
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
* the temporary storage V must be 128rN bytes in length; the temporary
* storage XY must be 256r + 64 bytes in length. The value N must be a
@@ -151,7 +151,7 @@ integerify(const void * B, size_t r)
* multiple of 64 bytes.
*/
void
-crypto_scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _V, void * XY)
+scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _V, void * XY)
{
uint32_t * X = XY;
uint32_t * Y = (void *)((uint8_t *)(XY) + 128 * r);
diff --git a/sdar/main.c b/sdar/main.c
index 83da93e..b23f933 100644
--- a/sdar/main.c
+++ b/sdar/main.c
@@ -13,8 +13,7 @@
#include <unistd.h>
enum {
- /* length of an address as a string */
- Addrsz = 1 + 2*Hmacsz,
+ Addrsz = 1 + 2 * Hmacsz, /* length of an address as a string */
};
uchar iobuf[Maxblk];
@@ -103,7 +102,7 @@ readpass(char *prefix, int *interact)
memcpy(&new, &old, sizeof new);
new.c_lflag &= ~ECHO;
tcsetattr(fd, TCSANOW, &new);
- for (i = 0; i < sizeof buf - 1; i++) {
+ for (i = 0; i < (int)sizeof buf - 1; i++) {
n = read(fd, buf+i, 1);
if (n <= 0 || buf[i] == '\n')
break;
@@ -261,7 +260,7 @@ pkt(char *msg, ...)
va_start(vl, msg);
n = vsnprintf(buf, sizeof buf, msg, vl);
va_end(vl);
- assert(n < sizeof buf);
+ assert(n < (int)sizeof buf);
printf("%02x%s\n", n+1, buf);
}
@@ -269,23 +268,25 @@ static int
addbatch(Arch *a)
{
char buf[65] = {0};
+ Slice s;
int rc, werr, lz4;
- vlong sz, rd;
- uchar *blk;
+ vlong n, len;
hmac_t hmac;
Addr addr;
+ s = newsl();
pkt("ready");
rc = 0;
- blk = plain + Plnpad;
for (;;) {
fflush(stdout);
- sz = fread(buf, 6, 1, stdin);
- if (sz == 0)
+ n = fread(buf, 6, 1, stdin);
+ if (n == 0) {
+ freesl(s);
return rc;
- if (sz != 1)
+ }
+ if (n != 1)
goto error;
if (memcmp(buf+2, "blk ", 4) == 0) {
@@ -299,12 +300,12 @@ addbatch(Arch *a)
goto error;
getchar();
- if (readnum(&sz, stdin)
- || sz > Maxblk
- || (sz > 0 && fread(blk, sz, 1, stdin) != 1))
+ if (readnum(&len, stdin)
+ || len > Maxblk
+ || (len > 0 && slread(&s, len, stdin)))
goto error;
- if (stashblk(a, hmac, lz4, blk, sz)) {
+ if (stashblk(a, hmac, lz4, s)) {
pkt("err");
rc = 1;
} else
@@ -316,17 +317,17 @@ addbatch(Arch *a)
if (memcmp(buf+2, "raw ", 4) != 0)
goto error;
- if (readnum(&sz, stdin))
+ if (readnum(&len, stdin))
goto error;
werr = 0;
- while (sz > 0) {
- rd = min(sz, sizeof iobuf);
- rd = fread(iobuf, 1, rd, stdin);
- sz -= rd;
- if (rd == 0)
+ while (len > 0) {
+ n = min(len, (long)sizeof iobuf);
+ n = fread(iobuf, 1, n, stdin);
+ len -= n;
+ if (n == 0)
goto error;
- if (!werr && stashadd(a, iobuf, rd))
+ if (!werr && stashadd(a, iobuf, n))
werr = 1;
}
@@ -340,6 +341,7 @@ addbatch(Arch *a)
error:
err("batch protocol error");
+ freesl(s);
return 1;
}
@@ -443,7 +445,7 @@ idbatch(Writer *w)
{
Addr a;
char cmd[6];
- vlong sz, rd;
+ vlong n, len;
int werr, rc;
pkt("ready");
@@ -451,10 +453,10 @@ idbatch(Writer *w)
werr = 0;
for (;;) {
fflush(stdout);
- sz = fread(cmd, 6, 1, stdin);
- if (sz == 0)
+ n = fread(cmd, 6, 1, stdin);
+ if (n == 0)
return rc;
- if (sz != 1)
+ if (n != 1)
goto error;
if (memcmp(cmd+2, "end\n", 4) == 0) {
@@ -473,15 +475,15 @@ idbatch(Writer *w)
goto error;
/* write more data in w */
- if (readnum(&sz, stdin))
+ if (readnum(&len, stdin))
goto error;
- while (sz > 0) {
- rd = min(sz, sizeof iobuf);
- rd = fread(iobuf, 1, rd, stdin);
- sz -= rd;
- if (rd == 0)
+ while (len > 0) {
+ n = min(len, (long)sizeof iobuf);
+ n = fread(iobuf, 1, n, stdin);
+ len -= n;
+ if (n == 0)
goto error;
- if (!werr && writer(w, iobuf, rd))
+ if (!werr && writer(w, iobuf, n))
werr = 1;
}
}
@@ -539,24 +541,23 @@ parseaddr(char *s, Addr *a)
static int
readdata(Reader *rd, Addr *addr, vlong off, vlong len, int batch)
{
- uchar *buf;
- long sz;
+ Slice s;
if (readerstart(rd, addr, off))
return 1;
do {
- if (reader(rd, &buf, &sz))
+ if (reader(rd, &s))
return 1;
- if (!sz)
+ if (!s.len)
break;
if (len > 0) {
- if (sz > len)
- sz = len;
- len -= sz;
+ if (s.len > len)
+ s.len = len;
+ len -= s.len;
}
if (batch)
- pkt("raw %ld", sz);
- fwrite(buf, 1, sz, stdout);
+ pkt("raw %ld", s.len);
+ fwrite(s.buf, 1, s.len, stdout);
} while (len != 0);
return 0;
}
@@ -564,11 +565,12 @@ readdata(Reader *rd, Addr *addr, vlong off, vlong len, int batch)
static int
readbatch(Reader *rd)
{
- char buf[Addrsz+1+20+1+20+1+1] = {0}, *cur;
+ char buf[Addrsz+1+20+1+20+1+1], *cur;
vlong off, len;
Addr addr;
uchar n;
+ memset(buf, 0, sizeof buf);
pkt("ready");
for (;;) {
fflush(stdout);
@@ -694,20 +696,24 @@ cmd_update(int argc, char *argv[])
}
static int
-emitblock(Block *b, hmac_t hmac, uchar *key, void *arg)
+emitblock(Block *b, hmac_t hmac, uchar segp[Prepsz], void *arg)
{
- FILE *data;
+ Slice s;
+ FILE *f;
- data = arg;
- if (fseek(data, Seghdsz + b->off, SEEK_SET))
+ f = arg;
+ if (fseek(f, Seghdsz + b->off, SEEK_SET) == 1)
return 1;
- if (cread(data, key, b->off, b->len)) {
+ s = newsl();
+ if (decrypt(&s, f, b->len, segp, b->off)) {
logs("E could not read block");
err("could not read block");
+ freesl(s);
return 1;
}
pkt("blk %d %s %d", b->lz4, hmacs(hmac), b->len);
- fwrite(plain + Plnpad, 1, b->len, stdout);
+ fwrite(s.buf, 1, b->len, stdout);
+ freesl(s);
return 0;
}
@@ -789,7 +795,7 @@ openlog()
exit(1);
}
n = snprintf(buf, sizeof buf, "%s/.sdar.log", p);
- if (n >= sizeof buf) {
+ if (n >= (int)sizeof buf) {
err("log path too long");
exit(1);
}
diff --git a/sdar/sdar.1 b/sdar/sdar.1
deleted file mode 100644
index 069d350..0000000
--- a/sdar/sdar.1
+++ /dev/null
@@ -1,20 +0,0 @@
-.TH sdar 1
-.SH NAME
-sdar \- implements secure deduplicated archives
-.SH SYNOPSIS
-.B sdar
-.RB [ \-p
-.IR passphrase ]
-.SH DESCRIPTION
-.B sdar
-creates and updates encrypted archives.
-.SH OPTIONS
-.TP
-.B \-p " passphrase"
-the archive key's
-.I passphrase
-.SH AUTHORS
-Quentin Carbonneaux <quentin@c9x.me>
-.SH SEE ALSO
-.BR ar (1)
-.BR tarsnap (1)
diff --git a/sdar/slice.c b/sdar/slice.c
new file mode 100644
index 0000000..c2ecc18
--- /dev/null
+++ b/sdar/slice.c
@@ -0,0 +1,158 @@
+#include "all.h"
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <blake3.h>
+#include <crypto_box.h>
+#include <lz4.h>
+
+/* module wrapping buffer allocation, crypto,
+ * and compression functions in a uniform api */
+
+enum {
+ Nstk = 4,
+ Bufdat = LZ4_COMPRESSBOUND(Maxblk),
+};
+
+MAKESURE(Noncesz, crypto_box_NONCEBYTES == Noncesz);
+MAKESURE(Keysz0, crypto_box_PUBLICKEYBYTES == Keysz);
+MAKESURE(Keysz1, crypto_box_SECRETKEYBYTES == Keysz);
+MAKESURE(Keysz2, BLAKE3_KEY_LEN == Keysz);
+MAKESURE(Plnpad, crypto_box_ZEROBYTES == Plnpad);
+MAKESURE(Cippad, crypto_box_BOXZEROBYTES == Cippad);
+MAKESURE(Prepsz, crypto_box_BEFORENMBYTES == Prepsz);
+MAKESURE(Plncip, Plnpad >= Cippad);
+MAKESURE(Bufpad0, (int)Bufpad >= (int)Plnpad);
+MAKESURE(Bufpad1, (int)Bufpad >= (int)Cippad);
+MAKESURE(Bufpad2, (Bufpad & 7) == 0);
+
+static uchar bstk[Nstk][Bufpad + Bufdat];
+static int bid;
+
+Slice
+mksl(uchar *buf, long len)
+{
+ /*
+ * it is required that Bufpad bytes
+ * are available right before the
+ * buf pointer
+ */
+ return (Slice){buf, len};
+}
+
+/* buffers life cycle must adhere to a
+ * stack discipline */
+Slice
+newsl()
+{
+ uchar *buf;
+
+ if (bid == Nstk) {
+ logs("E out of buffers!");
+ abort();
+ }
+ buf = &bstk[bid++][Bufpad];
+ return (Slice){buf, 0};
+}
+
+void
+freesl(Slice s)
+{
+ bid--;
+ assert(s.buf == &bstk[bid][Bufpad]);
+}
+
+void
+slencryptp(Slice *sc, Slice sp, uchar prep[Prepsz], vlong nonce)
+{
+ uchar nbuf[Noncesz] = {0};
+
+ memset(sp.buf - Plnpad, 0, Plnpad);
+ enc64be(nbuf, nonce);
+ crypto_box_afternm(
+ sc->buf - Cippad, sp.buf - Plnpad,
+ sp.len + Plnpad, nbuf, prep);
+ sc->len = sp.len + Cipovh;
+}
+
+int
+sldecryptp(Slice *sp, Slice sc, uchar prep[Prepsz], vlong nonce)
+{
+ uchar nbuf[Noncesz] = {0};
+
+ memset(sc.buf - Cippad, 0, Cippad);
+ enc64be(nbuf, nonce);
+ if (crypto_box_open_afternm(
+ sp->buf - Plnpad, sc.buf - Cippad,
+ sc.len + Cippad, nbuf, prep) != 0)
+ return 1;
+ sp->len = sc.len - Cipovh;
+ return 0;
+}
+
+int
+decrypt(Slice *s, FILE *f, long sz, uchar prep[Prepsz], vlong nonce)
+{
+ Slice sr;
+ int err;
+
+ sr = newsl();
+ if ((err = slread(&sr, Cipovh + sz, f)) == 0)
+ err = sldecryptp(s, sr, prep, nonce);
+ freesl(sr);
+ return err;
+}
+
+void
+slhmac(Slice s, hmac_t hmac)
+{
+ blake3_hasher bh;
+
+ assert(key.hmac);
+ blake3_hasher_init_keyed(&bh, key.hmac);
+ blake3_hasher_update(&bh, s.buf, s.len);
+ blake3_hasher_finalize(&bh, hmac, 32);
+}
+
+void
+sldeflate(Slice *sd, Slice si)
+{
+ sd->len = LZ4_compress_default(
+ (char*)si.buf, (char*)sd->buf,
+ si.len, Bufdat);
+ assert(sd->len != 0);
+}
+
+int
+slinflate(Slice *si, Slice sd)
+{
+ int sz;
+
+ sz = LZ4_decompress_safe(
+ (char*)sd.buf, (char*)si->buf,
+ sd.len, Bufdat);
+ if (sz < 0)
+ return 1;
+ si->len = sz;
+ return 0;
+}
+
+int
+slwrite(Slice s, FILE *f)
+{
+ long n;
+
+ n = fwrite(s.buf, 1, s.len, f);
+ return n != s.len;
+}
+
+int
+slread(Slice *s, long sz, FILE *f)
+{
+ long n;
+
+ n = fread(s->buf, 1, sz, f);
+ s->len = n;
+ return n != sz;
+}
diff --git a/sdar/stash.c b/sdar/stash.c
index bdd6354..12abf67 100644
--- a/sdar/stash.c
+++ b/sdar/stash.c
@@ -1,5 +1,4 @@
#include "all.h"
-#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
@@ -8,73 +7,62 @@
#include <sys/time.h>
#include <unistd.h>
#include <crypto_box.h>
-#include <lz4.h>
MAKESURE(Segidsz_is_ok, Segidsz <= Keysz);
-static flushcb flushblock;
+static flushcb flushblk;
int
stashinit(Arch *a)
{
- uchar seckey[Keysz];
+ uchar sec[Keysz];
struct stat sb;
- vlong sz, pg;
- int log, flags;
Loghd *h;
+ int fd;
- assert(!a->log);
- writerinit(&a->writer, flushblock, a);
-
- flags = O_CREAT|O_RDWR;
- log = openat(a->fd, "stash/log", flags, Permf);
- if (log == -1)
+ if (a->log != 0)
return 1;
- flags = PROT_READ|PROT_WRITE;
- pg = sysconf(_SC_PAGESIZE);
- h = mmap(0, pg, flags, MAP_SHARED, log, 0);
+ writerinit(&a->writer, flushblk, a);
+ a->log = fopenat(a->fd, O_CREAT|O_RDWR, "stash/log");
+ a->data = fopenat(a->fd, O_CREAT|O_RDWR, "stash/data");
+ if (a->log == 0 || a->data == 0)
+ goto error;
+
+ fd = fileno(a->log);
+ h = mmap(0, sizeof(Loghd), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (h == MAP_FAILED)
goto error;
- if (fstat(log, &sb) == -1)
+ if (fstat(fd, &sb) == -1)
goto error1;
- sz = sb.st_size;
-
- if (sz < sizeof *h) {
- if (ftruncate(log, sizeof *h) == -1)
+ if (sb.st_size < (int)sizeof(Loghd)) {
+ if (ftruncate(fd, sizeof(Loghd)) == -1)
goto error1;
- crypto_box_keypair(h->kpub, seckey);
- crypto_box_beforenm(h->kpre, key.masterpub, seckey);
+ crypto_box_keypair(h->segk, sec);
+ crypto_box_beforenm(h->segp, key.pub, sec);
h->nitem = 0;
h->dlen = 0;
- msync(h, sizeof *h, MS_SYNC);
+ msync(h, sizeof(Loghd), MS_SYNC);
}
- a->log = fdopen(log, "w+");
- if (!a->log)
+ if (fseek(a->log, 0, SEEK_END) == -1)
+ goto error1;
+ if (fseek(a->data, 0, SEEK_END) == -1)
goto error1;
- log = -1;
-
- if (fseek(a->log, 0, SEEK_END))
- goto error2;
-
- flags = O_CREAT|O_RDWR|O_APPEND;
- a->data = fopenat(a->fd, flags, "stash/data");
- if (!a->data)
- goto error2;
a->logh = h;
return 0;
-error2:
- fclose(a->log);
- a->log = 0;
error1:
munmap(h, sizeof(Loghd));
error:
- if (log != -1)
- close(log);
+ if (a->data)
+ fclose(a->data);
+ if (a->log)
+ fclose(a->log);
+ a->data = 0;
+ a->log = 0;
return 1;
}
@@ -87,17 +75,15 @@ stashadd(Arch *a, uchar *buf, vlong sz)
int
stashsync(Arch *a)
{
- int rc;
-
- rc = 0;
- rc |= (msync(a->logh, sizeof(Loghd), MS_SYNC) == -1);
- rc |= (fflush(a->log) == EOF);
- rc |= (fsync(fileno(a->log)) == -1);
- rc |= (fflush(a->data) == EOF);
- rc |= (fsync(fileno(a->data)) == -1);
- if (rc)
+ int err;
+
+ err = 0;
+ err |= msync(a->logh, sizeof(Loghd), MS_SYNC) == -1;
+ err |= flushsync(a->log);
+ err |= flushsync(a->data);
+ if (err)
logs("E error while syncing stash");
- return rc;
+ return err;
}
int
@@ -107,58 +93,64 @@ stashdone(Arch *a, Addr *addr)
}
static int
-flushraw(Arch *a, hmac_t hmac, int lz4, uchar *buf, int sz)
+flushraw(Arch *a, hmac_t hmac, int lz4, Slice s)
{
- uchar item[Hmacsz + 4];
+ uchar item[Segitemsz];
+ Slice sc;
Loghd *h;
h = a->logh;
- if (cwritep(a->data, h->kpre, h->dlen, buf - Plnpad, sz + Plnpad))
+ sc = newsl();
+
+ slencryptp(&sc, s, h->segp, h->dlen);
+ if (slwrite(sc, a->data))
goto ioerror;
hmaccpy(item, hmac);
- enc32be(item + Hmacsz, lz4 | sz << 1);
- if (fwrite(item, Hmacsz + 4, 1, a->log) != 1)
+ enc32be(item + Hmacsz, lz4 | s.len << 1);
+ if (fwrite(item, Segitemsz, 1, a->log) != 1)
goto ioerror;
h->nitem++;
- h->dlen += sz + (Plnpad - Cippad);
+ h->dlen += sc.len;
+
+ freesl(sc);
return 0;
ioerror:
logs("E io error while writing to stash");
+ freesl(sc);
return 1;
}
/* adds a block directly to the stash;
- * we will check if the provided hmac
- * is correct and if the block size is
- * fine */
+ * we will check that the provided hmac
+ * is correct and that the block size
+ * is fine */
int
-stashblk(Arch *a, hmac_t hmac, int lz4, uchar *buf, int sz)
+stashblk(Arch *a, hmac_t hmac, int lz4, Slice sb)
{
- char *src, *dst;
- hmac_t check;
- uchar *dbuf;
- int dsz;
+ hmac_t bhmac;
+ Slice s;
+ int bsz;
if (lz4) {
- src = (char*)buf;
- dst = (char*)inflate;
- dsz = LZ4_decompress_safe(src, dst, sz, Maxblk);
- if (dsz < 0)
+ s = newsl();
+ if (slinflate(&s, sb)) {
+ freesl(s);
return 1;
- dbuf = inflate;
+ }
+ bsz = s.len;
+ slhmac(s, bhmac);
+ freesl(s);
} else {
- dbuf = buf;
- dsz = sz;
+ slhmac(sb, bhmac);
+ bsz = sb.len;
}
- if (dsz > Maxblk)
- return 1;
- assert(key.hmac);
- hmac_blake3(key.hmac, Keysz, dbuf, dsz, check);
- if (memcmp(hmac, check, Hmacsz) != 0) {
+ if (bsz > Maxblk)
+ return 1;
+ if (memcmp(hmac, bhmac, Hmacsz) != 0) {
logs("E invalid block hmac %s", hmacs(hmac));
return 1;
}
@@ -166,115 +158,127 @@ stashblk(Arch *a, hmac_t hmac, int lz4, uchar *buf, int sz)
if (archhas(a, hmac))
return 0;
- return flushraw(a, hmac, lz4, buf, sz);
+ return flushraw(a, hmac, lz4, sb);
}
static int
-flushblock(void *arg, hmac_t hmac, uchar *buf, int sz)
+flushblk(void *arg, hmac_t hmac, Slice sb)
{
- static uchar deflate[Plnpad + LZ4_COMPRESSBOUND(Maxblk)];
- char *dst;
- int compsz, dstsz;
+ Slice sd;
+ int err;
Arch *a;
a = arg;
if (archhas(a, hmac))
return 0;
- /* we may also want to dedup within the stash */
-
- dst = (char*)deflate + Plnpad;
- dstsz = sizeof deflate - Plnpad;
- compsz = LZ4_compress_default((char*)buf, dst, sz, dstsz);
- if (compsz && compsz < sz) {
- buf = deflate + Plnpad;
- sz = compsz;
- } else
- compsz = 0;
-
- return flushraw(a, hmac, (compsz != 0), buf, sz);
+ /* TODO: we may also want to dedup within the stash */
+
+ sd = newsl();
+ sldeflate(&sd, sb);
+ if (sd.len < sb.len)
+ err = flushraw(a, hmac, 1, sd);
+ else
+ err = flushraw(a, hmac, 0, sb);
+ freesl(sd);
+ return err;
}
static int
-writeseg(Arch *a, char *msg, FILE *segf)
+writeseg(Arch *a, char *msg, FILE *f)
{
- vlong ni, sz, idx, nleft, total;
struct timeval tv;
- Segmeta meta;
+ Slice sb, sc;
+ Segmeta m;
+ vlong len, idx;
+ int err, n;
Loghd *h;
+ err = 1;
h = a->logh;
- if (fwrite(segmagic, Magicsz, 1, segf) != 1)
- return 1;
- if (fwrite(h->kpub, Keysz, 1, segf) != 1)
- return 1;
+ sb = newsl();
+ sc = newsl();
- meta.nitem = h->nitem;
- meta.dlen = h->dlen;
- meta.date = 0;
- if (gettimeofday(&tv, 0) == 0)
- meta.date = tv.tv_sec;
- strncpy(meta.msg, msg, sizeof meta.msg - 1);
- encmeta(plain + Plnpad, &meta);
- idx = -1;
- if (cwritep(segf, h->kpre, idx, plain, Plnpad + Segmetasz))
- return 1;
+ if (fwrite(segmagic, Magicsz, 1, f) != 1)
+ goto out;
+ if (fwrite(h->segk, Keysz, 1, f) != 1)
+ goto out;
- if (fseek(a->data, 0, SEEK_SET))
- return 1;
- total = 0;
- while ((sz = fread(iobuf, 1, sizeof iobuf, a->data))) {
- if ((vlong)fwrite(iobuf, 1, sz, segf) != sz)
- return 1;
- total += sz;
+ memset(&m, 0, sizeof(Segmeta));
+ m.nitem = h->nitem;
+ m.dlen = h->dlen;
+ if (gettimeofday(&tv, 0) == 0)
+ m.date = tv.tv_sec;
+ strncpy(m.msg, msg, sizeof m.msg - 1);
+ encmeta(&sb, &m);
+
+ slencryptp(&sc, sb, h->segp, -1);
+ if (slwrite(sc, f))
+ goto out;
+
+ if (fseek(a->data, 0, SEEK_SET) == -1)
+ goto out;
+ for (len = 0;; len += n) {
+ n = fread(sb.buf, 1, Maxblk, a->data);
+ if (n == 0)
+ break;
+ if (fwrite(sb.buf, 1, n, f) != (size_t)n)
+ goto out;
}
- if (total != h->dlen) {
- logs("E inconsistent stash, aborting commit");
- return 1;
+ if (len != h->dlen) {
+ logs("E inconsistent stash");
+ goto out;
}
- if (fseek(a->log, sizeof(Loghd), SEEK_SET))
- return 1;
- nleft = h->nitem;
- while (nleft > 0) {
- ni = min(nleft, Maxblk / Segitemsz);
- nleft -= ni;
- sz = ni * Segitemsz;
- if ((vlong)fread(plain + Plnpad, 1, sz, a->log) != sz)
- return 1;
- idx--;
- if (cwritep(segf, h->kpre, idx, plain, Plnpad + sz))
- return 1;
+ if (fseek(a->log, sizeof(Loghd), SEEK_SET) == -1)
+ goto out;
+ idx = -1;
+ len = h->nitem * Segitemsz;
+ while (len > 0) {
+ n = (Maxblk/Segitemsz) * Segitemsz;
+ n = min(len, n);
+ len -= n;
+ if (slread(&sb, n, a->log))
+ goto out;
+ slencryptp(&sc, sb, h->segp, --idx);
+ if (slwrite(sc, f))
+ goto out;
}
- return 0;
+ if (flushsync(f))
+ goto out;
+ err = 0;
+out:
+ freesl(sc);
+ freesl(sb);
+ return err;
}
static int
cacheupdate(Arch *a, uchar segid[Segidsz])
{
- uchar it[Segitemsz];
- vlong n;
- Cachemeta *m;
+ uchar itm[Segitemsz];
Block b = {0};
+ Cachemeta *m;
+ vlong n;
m = a->cache.meta;
b.seg = ++m->nseg;
if (cputseg(&a->cache, segid, b.seg))
return 1;
- if (fseek(a->log, sizeof(Loghd), SEEK_SET))
+ if (fseek(a->log, sizeof(Loghd), SEEK_SET) == -1)
return 1;
for (n = a->logh->nitem; n > 0; n--) {
- if (fread(it, Segitemsz, 1, a->log) != 1)
+ if (fread(itm, Segitemsz, 1, a->log) != 1)
return 1;
- decitem(it, &b);
- if (cput(&a->cache, it, &b)) {
+ decitem(itm, &b);
+ if (cput(&a->cache, itm, &b)) {
logs("E cannot write to cache");
return 1;
}
- b.off += b.len + (Plnpad - Cippad);
+ b.off += b.len + Cipovh;
}
return 0;
}
@@ -282,44 +286,36 @@ cacheupdate(Arch *a, uchar segid[Segidsz])
int
stashcommit(Arch *a, char *msg, uchar segid[Segidsz])
{
- FILE *segf;
- int flags;
+ FILE *f;
assert(a->log);
- memcpy(segid, a->logh->kpub, Segidsz);
+ memcpy(segid, a->logh->segk, Segidsz);
- flags = O_CREAT|O_EXCL|O_WRONLY;
- segf = fopenat(a->fd, flags, segs(segid));
- if (!segf) {
- logs("W %s already exists", segs(segid));
+ f = fopenat(a->fd, O_CREAT|O_EXCL|O_WRONLY, segs(segid));
+ if (f == 0) {
+ logs("W cannot create %s", segs(segid));
return 1;
}
-
- if (writeseg(a, msg, segf)
- || fflush(segf) == EOF
- || fsync(fileno(segf)) == -1)
+ if (writeseg(a, msg, f))
goto error;
-
- /* update the cache */
if (cacheupdate(a, segid))
goto error;
- /* clear the stash */
fclose(a->log);
fclose(a->data);
a->log = 0;
a->logh = 0;
a->data = 0;
- if (unlinkat(a->fd, "stash/log", 0)
- || unlinkat(a->fd, "stash/data", 0))
- logs("W could not unlink stash files");
+ if (unlinkat(a->fd, "stash/log", 0) == -1
+ || unlinkat(a->fd, "stash/data", 0) == -1)
+ logs("W cannot unlink stash files");
- fclose(segf);
logs("I committed %s", segs(segid));
+ fclose(f);
return 0;
error:
- fclose(segf);
+ fclose(f);
return 1;
}
diff --git a/sdar/util.c b/sdar/util.c
index 84fa830..81b956c 100644
--- a/sdar/util.c
+++ b/sdar/util.c
@@ -95,7 +95,7 @@ fopenat(int afd, int flags, char *path, ...)
va_start(ap, path);
n = vsnprintf(buf, sizeof buf, path, ap);
va_end(ap);
- if (n >= sizeof buf)
+ if (n >= (int)sizeof buf)
return 0;
fd = openat(afd, buf, flags, Permf);
if (fd == -1)
@@ -114,6 +114,12 @@ fopenat(int afd, int flags, char *path, ...)
return f;
}
+int
+flushsync(FILE *f)
+{
+ return fflush(f) == EOF || fsync(fileno(f));
+}
+
void
enc32be(uchar *p, uvlong x)
{
diff --git a/sdar/writer.c b/sdar/write.c
index 44cd81d..501194d 100644
--- a/sdar/writer.c
+++ b/sdar/write.c
@@ -19,29 +19,31 @@ writerinit(Writer *w, flushcb *flush, void *arg)
w->level[1].nent = 0;
}
-/* callers must arrange for Plnpad bytes to be available
- * before the buf pointer */
static int
-flush(Writer *w, uchar *buf, long sz, hmac_t hmac)
+flush(Writer *w, Slice s, hmac_t hmac)
{
assert(key.hmac);
- hmac_blake3(key.hmac, Keysz, buf, sz, hmac);
+ slhmac(s, hmac);
if (!w->flush)
return 0;
- return w->flush(w->arg, hmac, buf, sz);
+ return w->flush(w->arg, hmac, s);
}
static void
-putlevel(uint8_t *ptr, Ilevel *l)
+enclevel(Slice *s, Ilevel *l)
{
Ientry *e;
+ uchar *p;
int i;
- for (i = 0, e = l->ent; i < l->nent; e++, i++) {
- hmaccpy(ptr, e->hmac);
- enc64be(ptr + Hmacsz, e->len);
- ptr += Entrysz;
+ p = s->buf;
+ for (i = 0; i < l->nent; i++) {
+ e = &l->ent[i];
+ hmaccpy(p, e->hmac);
+ enc64be(p + Hmacsz, e->len);
+ p += Entrysz;
}
+ s->len = p - s->buf;
}
static void
@@ -55,14 +57,20 @@ addentry(Ilevel *l, hmac_t hmac, vlong len)
}
int
-getlevel(Ilevel *l, uchar *ptr, long sz)
+declevel(Ilevel *l, Slice s)
{
- if (sz % Entrysz != 0 || sz / Entrysz > Indexsz)
+ uchar *p;
+ vlong n, len;
+
+ p = s.buf;
+ n = s.len;
+ if (n % Entrysz != 0 || n / Entrysz > Indexsz)
return 1;
l->nent = 0;
- for (; sz > 0; sz -= Entrysz) {
- addentry(l, ptr, dec64be(ptr + Hmacsz));
- ptr += Entrysz;
+ for (; n > 0; n -= Entrysz) {
+ len = dec64be(p + Hmacsz);
+ addentry(l, p, len);
+ p += Entrysz;
}
return 0;
}
@@ -70,12 +78,15 @@ getlevel(Ilevel *l, uchar *ptr, long sz)
static int
flushlevel(Writer *w, Ilevel *l, hmac_t hmac)
{
- long sz;
+ Slice s;
+ int err;
assert(l->nent > 0 && l->nent <= Indexsz);
- sz = l->nent * Entrysz;
- putlevel(plain + Plnpad, l);
- return flush(w, plain + Plnpad, sz, hmac);
+ s = newsl();
+ enclevel(&s, l);
+ err = flush(w, s, hmac);
+ freesl(s);
+ return err;
}
static int
@@ -109,9 +120,10 @@ chunkdone(Writer *w, uchar *buf, int sz)
assert(sz <= Maxblk);
- /* we arranged so that there is Plnpad
- * bytes available before buf */
- if (flush(w, buf, sz, hmac))
+ /* we arranged so that there is Bufpad
+ * bytes available before buf, as
+ * required by mksl() */
+ if (flush(w, mksl(buf, sz), hmac))
return 1;
l0 = &w->level[0];
@@ -134,7 +146,7 @@ chunker(Writer *w, int sz)
uint h, msk;
int i, n, l, m, end;
- wbuf = w->buf + Plnpad;
+ wbuf = w->buf + Bufpad;
m = 1ull << (Avglog-1); /* min chunk size */
msk = ((uint)m - 1) << (33 - Avglog);
h = w->rhash;
@@ -183,18 +195,17 @@ chunker(Writer *w, int sz)
}
int
-writer(Writer *w, uchar *buf, vlong sz)
+writer(Writer *w, uchar *b, vlong nb)
{
int n;
- while (sz > 0) {
- n = sizeof w->buf - (Plnpad + w->bpos);
- if (n > sz)
- n = sz;
- memcpy(w->buf + Plnpad + w->bpos, buf, n);
- buf += n;
- sz -= n;
- if (chunker(w, n + w->bpos))
+ while (nb > 0) {
+ n = sizeof w->buf - (Bufpad + w->bpos);
+ n = min(nb, n);
+ memcpy(w->buf + Bufpad + w->bpos, b, n);
+ b += n;
+ nb -= n;
+ if (chunker(w, w->bpos + n))
return 1;
}
return 0;
@@ -205,7 +216,7 @@ writerdone(Writer *w, Addr *a)
{
Ilevel *l;
- if (chunkdone(w, w->buf + Plnpad, w->bpos))
+ if (chunkdone(w, w->buf + Bufpad, w->bpos))
return 1;
l = w->level;