URI: 
       tRewrite encrypt/decrypt to handle memory buffers - safe - password protected secret keeper
  HTML git clone git://git.z3bra.org/safe.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 3a6a19326fb0700a02c76683c1d736b3c59b760a
   DIR parent 19a78db25e6054e65e787442738bcbf3e4e88398
  HTML Author: Willy Goiffon <dev@z3bra.org>
       Date:   Fri, 31 May 2019 17:27:33 +0200
       
       Rewrite encrypt/decrypt to handle memory buffers
       
       Diffstat:
         M safe.c                              |     122 +++++++++++++++++--------------
       
       1 file changed, 68 insertions(+), 54 deletions(-)
       ---
   DIR diff --git a/safe.c b/safe.c
       t@@ -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;
       t@@ -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);
                }
        }
        
       t@@ -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);
                }
        
       t@@ -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;
       t@@ -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;