URI: 
       tGenerate key within show/store functions rather than main() - 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 df835567ad72b5aeafbe36f3231a956c38bd5a81
   DIR parent 5dab94f82b2ff901e004fb3ef9692e3644208aac
  HTML Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon,  3 Jun 2019 12:23:57 +0200
       
       Generate key within show/store functions rather than main()
       
       Diffstat:
         M safe.c                              |      62 ++++++++++++++++++-------------
       
       1 file changed, 37 insertions(+), 25 deletions(-)
       ---
   DIR diff --git a/safe.c b/safe.c
       t@@ -126,33 +126,36 @@ xwrite(int fd, const void *buf, size_t nbytes)
                return total;
        }
        
       -void
       +int
        secret_encrypt(struct safe *s, uint8_t *m, size_t mlen, uint8_t *c, unsigned long long *clen, int flags)
        {
                int tag = 0;
        
                if (flags & SAFE_INIT)
       -                crypto_secretstream_xchacha20poly1305_init_push(&s->st, s->h, s->key);
       +                if (crypto_secretstream_xchacha20poly1305_init_push(&s->st, s->h, s->key))
       +                        return -1;
        
                if (flags & SAFE_FINAL)
                        tag = crypto_secretstream_xchacha20poly1305_TAG_FINAL;
        
       -        crypto_secretstream_xchacha20poly1305_push(&s->st, c, clen, m, mlen, NULL, 0, tag);
       +        return crypto_secretstream_xchacha20poly1305_push(&s->st, c, clen, m, mlen, NULL, 0, tag);
        }
        
       -void
       +int
        secret_decrypt(struct safe *s, uint8_t *c, size_t clen, uint8_t *m, unsigned long long *mlen, int flags)
        {
                uint8_t tag;
                if (flags & SAFE_INIT)
       -                crypto_secretstream_xchacha20poly1305_init_pull(&s->st, s->h, s->key);
       +                if (crypto_secretstream_xchacha20poly1305_init_pull(&s->st, s->h, s->key))
       +                        return -1;
        
       -        crypto_secretstream_xchacha20poly1305_pull(&s->st, m, mlen, &tag, c, clen, NULL, 0);
       +        if (crypto_secretstream_xchacha20poly1305_pull(&s->st, m, mlen, &tag, c, clen, NULL, 0))
       +                return -1;
        
       -        if (flags & SAFE_FINAL && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
       -                fprintf(stderr, "secret_decrypt: premature EOF detected\n");
       -                exit(1);
       -        }
       +        if (flags & SAFE_FINAL && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL)
       +                return -1;
       +
       +        return 0;
        }
        
        int
       t@@ -280,17 +283,6 @@ getkey(struct safe *s, char *path)
        int
        genkey(struct safe *s)
        {
       -        int fd;
       -
       -        if (secret_exists(LOCK)) {
       -                if ((fd = open(LOCK, O_RDONLY)) < 0)
       -                        err(1, "open %s", LOCK);
       -
       -                xread(fd, s->salt, sizeof(s->salt), NULL);
       -        } else {
       -                randombytes_buf(s->salt, sizeof(s->salt));
       -        }
       -
                readpass("password:", &passphrase, &pplen);
                deriv((char *)passphrase, s);
        
       t@@ -306,6 +298,11 @@ store_secret(struct safe *s, int fd, char *name)
                uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES];
                unsigned long long clen;
        
       +        if (!secret_exists(LOCK))
       +                randombytes_buf(s->salt, sizeof(s->salt));
       +
       +        genkey(s);
       +
                mkdir_p(dirname(name), 0700);
                sfd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
                if (sfd < 0)
       t@@ -316,7 +313,11 @@ store_secret(struct safe *s, int fd, char *name)
                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 (secret_encrypt(s, m, n, c, &clen, flags) < 0) {
       +                        fprintf(stderr, "%s: failed to encrypt password\n", name);
       +                        close(sfd);
       +                        return -1;
       +                }
        
                        if (flags & SAFE_INIT)
                                xwrite(sfd, s->h, sizeof(s->h));
       t@@ -346,10 +347,16 @@ show_secret(struct safe *s, int fd, char *name)
                xread(sfd, s->salt, sizeof(s->salt), NULL);
                xread(sfd, s->h, sizeof(s->h), NULL);
        
       +        genkey(s);
       +
                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);
       +                if (secret_decrypt(s, c, n, m, &mlen, flags) < 0) {
       +                        fprintf(stderr, "%s: failed to decrypt password\n", name);
       +                        close(sfd);
       +                        return -1;
       +                }
        
                        xwrite(fd, m, mlen);
                        flags &= ~(SAFE_INIT);
       t@@ -363,7 +370,7 @@ show_secret(struct safe *s, int fd, char *name)
        int
        main(int argc, char *argv[])
        {
       -        int aflag = 0, dflag = 0;
       +        int fd, aflag = 0, dflag = 0;
                char *secret = NULL, *sockp = NULL, *safe = SAFE;
                struct safe s;
        
       t@@ -393,7 +400,12 @@ main(int argc, char *argv[])
                                err(1, "chdir: %s", safe);
                }
        
       -        genkey(&s);
       +        if (secret_exists(LOCK)) {
       +                if ((fd = open(LOCK, O_RDONLY)) < 0)
       +                        err(1, "%s", LOCK);
       +                xread(fd, s.salt, sizeof(s.salt), NULL);
       +                close(fd);
       +        }
        
                if (dflag)
                        return agent(&s, sockp);