safe

Password protected secret keeper
git clone git://git.z3bra.org/safe.git
Log | Files | Refs | README | LICENSE

commit 3a6a19326fb0700a02c76683c1d736b3c59b760a
parent 19a78db25e6054e65e787442738bcbf3e4e88398
Author: Willy Goiffon <dev@z3bra.org>
Date:   Fri, 31 May 2019 17:27:33 +0200

Rewrite encrypt/decrypt to handle memory buffers

Diffstat:
safe.c | 122++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 68 insertions(+), 54 deletions(-)

diff --git a/safe.c b/safe.c @@ -21,6 +21,19 @@ #define SOCKET "agent" #define SAFE ".secrets" +struct safe { + crypto_secretstream_xchacha20poly1305_state st; + uint8_t h[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; + + uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + uint8_t salt[crypto_pwhash_SALTBYTES]; +}; + +enum { + SAFE_INIT = 1 << 1, + SAFE_FINAL = 1 << 2, +}; + uint8_t *passphrase; size_t pplen; char *argv0; @@ -112,52 +125,31 @@ xwrite(int fd, const void *buf, size_t nbytes) } void -encrypt_stream(int ifd, int ofd, uint8_t *key) +secret_encrypt(struct safe *s, uint8_t *m, size_t mlen, uint8_t *c, unsigned long long *clen, int flags) { - int eof; - uint8_t tag; - ssize_t n; - uint8_t m[BUFSIZ]; - uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES]; - uint8_t h[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; - crypto_secretstream_xchacha20poly1305_state st; - unsigned long long len; + int tag = 0; - crypto_secretstream_xchacha20poly1305_init_push(&st, h, key); - xwrite(ofd, h, sizeof(h)); + if (flags & SAFE_INIT) + crypto_secretstream_xchacha20poly1305_init_push(&s->st, s->h, s->key); - while ((n = xread(ifd, m, sizeof(m), &eof)) > 0) { - tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; - crypto_secretstream_xchacha20poly1305_push(&st, c, &len, m, n, NULL, 0, tag); - xwrite(ofd, c, len); - } + if (flags & SAFE_FINAL) + tag = crypto_secretstream_xchacha20poly1305_TAG_FINAL; + + crypto_secretstream_xchacha20poly1305_push(&s->st, c, clen, m, mlen, NULL, 0, tag); } void -decrypt_stream(int ifd, int ofd, uint8_t *key) +secret_decrypt(struct safe *s, uint8_t *c, size_t clen, uint8_t *m, unsigned long long *mlen, int flags) { - int eof; uint8_t tag; - ssize_t n; - uint8_t m[BUFSIZ]; - uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES]; - uint8_t h[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; - crypto_secretstream_xchacha20poly1305_state st; - unsigned long long len; + if (flags & SAFE_INIT) + crypto_secretstream_xchacha20poly1305_init_pull(&s->st, s->h, s->key); - xread(ifd, h, sizeof(h), NULL); - if (crypto_secretstream_xchacha20poly1305_init_pull(&st, h, key)) { - fprintf(stderr, "decrypt_stream: incomplete header\n"); - exit(1); - } + crypto_secretstream_xchacha20poly1305_pull(&s->st, m, mlen, &tag, c, clen, NULL, 0); - while ((n = xread(ifd, c, sizeof(c), &eof)) > 0) { - crypto_secretstream_xchacha20poly1305_pull(&st, m, &len, &tag, c, n, NULL, 0); - if (eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) { - fprintf(stderr, "decrypt_stream: premature EOF\n"); - exit(1); - } - xwrite(ofd, m, len); + if (flags & SAFE_FINAL && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) { + fprintf(stderr, "secret_decrypt: premature EOF detected\n"); + exit(1); } } @@ -231,17 +223,16 @@ int agent(char *path) { int cfd, sfd; - uint8_t salt[crypto_pwhash_SALTBYTES]; - uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + struct safe s; readpass("password:", &passphrase, &pplen); sfd = creatsock(path); while ((cfd = accept(sfd, NULL, NULL)) > 0) { - xread(cfd, salt, sizeof(salt), NULL); - deriv((char *)passphrase, salt, key, sizeof(key)); - xwrite(cfd, key, sizeof(key)); + xread(cfd, s.salt, sizeof(s.salt), NULL); + deriv((char *)passphrase, s.salt, s.key, sizeof(s.key)); + xwrite(cfd, s.key, sizeof(s.key)); close(cfd); } @@ -283,21 +274,33 @@ genkey(uint8_t *key, size_t ks, uint8_t *salt) int store_secret(int fd, char *name) { - int sfd; - uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; - uint8_t salt[crypto_pwhash_SALTBYTES]; + int sfd, eof, flags = 0; + ssize_t n; + struct safe s; + uint8_t m[BUFSIZ]; + uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES]; + unsigned long long clen; mkdir_p(dirname(name), 0700); sfd = open(name, O_WRONLY | O_CREAT, 0600); if (sfd < 0) err(1, "open %s", name); - randombytes_buf(salt, sizeof(salt)); - xwrite(sfd, salt, sizeof(salt)); + memset(s.salt, 0, sizeof(s.salt)); - genkey(key, sizeof(key), salt); + xwrite(sfd, s.salt, sizeof(s.salt)); + genkey(s.key, sizeof(s.key), s.salt); + + flags = SAFE_INIT; + while ((n = xread(fd, m, sizeof(m), &eof)) > 0) { + flags |= eof ? SAFE_FINAL : 0; + secret_encrypt(&s, m, n, c, &clen, flags); + if (flags & SAFE_INIT) + xwrite(sfd, s.h, sizeof(s.h)); + xwrite(sfd, c, clen); + flags &= ~(SAFE_INIT); + } - encrypt_stream(fd, sfd, key); close(sfd); return 0; @@ -306,19 +309,30 @@ store_secret(int fd, char *name) int show_secret(int fd, char *name) { - int sfd; - uint8_t key[crypto_secretstream_xchacha20poly1305_KEYBYTES]; - uint8_t salt[crypto_pwhash_SALTBYTES]; + int sfd, eof, flags = 0; + ssize_t n; + struct safe s; + uint8_t m[BUFSIZ]; + uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES]; + unsigned long long mlen; sfd = open(name, O_RDONLY); if (sfd < 0) err(1, "open %s", name); - xread(sfd, salt, sizeof(salt), NULL); + xread(sfd, s.salt, sizeof(s.salt), NULL); + genkey(s.key, sizeof(s.key), s.salt); - genkey(key, sizeof(key), salt); + xread(sfd, s.h, sizeof(s.h), NULL); + + flags = SAFE_INIT; + while ((n = xread(sfd, c, sizeof(c), &eof)) > 0) { + flags |= eof ? SAFE_FINAL : 0; + secret_decrypt(&s, c, n, m, &mlen, flags); + xwrite(fd, m, mlen); + flags &= ~(SAFE_INIT); + } - decrypt_stream(sfd, fd, key); close(sfd); return 0;