URI: 
       tRead key/salt and deriv key right from 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 5254f08121341ae91042257b11bd299788f3ebd5
   DIR parent 5bca68cbe7e38dd4c00464515a9755196db4fc8b
  HTML Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon,  3 Jun 2019 15:32:18 +0200
       
       Read key/salt and deriv key right from main()
       
       This allow checking the master password and deriving the key from it
       before storing/showing any password in/from the safe.
       
       Diffstat:
         M safe.c                              |      92 ++++++++++++++++---------------
       
       1 file changed, 49 insertions(+), 43 deletions(-)
       ---
   DIR diff --git a/safe.c b/safe.c
       t@@ -243,13 +243,9 @@ agent(struct safe *s, char *path)
        {
                int cfd, sfd;
        
       -        readpass("password:", &passphrase, &pplen);
       -
                sfd = creatsock(path);
        
                while ((cfd = accept(sfd, NULL, NULL)) > 0) {
       -                xread(cfd, s->salt, sizeof(s->salt), NULL);
       -                deriv((char *)passphrase, s);
                        xwrite(cfd, s->key, sizeof(s->key));
                        close(cfd);
                }
       t@@ -281,48 +277,31 @@ getkey(struct safe *s, char *path)
        }
        
        int
       -genkey(struct safe *s)
       -{
       -        readpass("password:", &passphrase, &pplen);
       -        deriv((char *)passphrase, s);
       -
       -        return 0;
       -}
       -
       -int
       -store_secret(struct safe *s, int fd, char *name)
       +show_secret(struct safe *s, int fd, char *name)
        {
                int sfd, eof, flags = 0;
                ssize_t n;
                uint8_t m[BUFSIZ];
                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);
       +        unsigned long long mlen;
        
       -        mkdir_p(dirname(name), 0700);
       -        sfd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600);
       +        sfd = open(name, O_RDONLY);
                if (sfd < 0)
                        err(1, "%s", name);
        
       -        xwrite(sfd, s->salt, sizeof(s->salt));
       +        xread(sfd, s->salt, sizeof(s->salt), NULL);
       +        xread(sfd, s->h, sizeof(s->h), NULL);
        
                flags = SAFE_INIT;
       -        while ((n = xread(fd, m, sizeof(m), &eof)) > 0) {
       +        while ((n = xread(sfd, c, sizeof(c), &eof)) > 0) {
                        flags |= eof ? SAFE_FINAL : 0;
       -                if (secret_encrypt(s, m, n, c, &clen, flags) < 0) {
       -                        fprintf(stderr, "%s: failed to encrypt password\n", name);
       +
       +                if (secret_decrypt(s, c, n, m, &mlen, flags) < 0) {
                                close(sfd);
                                return -1;
                        }
        
       -                if (flags & SAFE_INIT)
       -                        xwrite(sfd, s->h, sizeof(s->h));
       -
       -                xwrite(sfd, c, clen);
       +                xwrite(fd, m, mlen);
                        flags &= ~(SAFE_INIT);
                }
        
       t@@ -332,33 +311,49 @@ store_secret(struct safe *s, int fd, char *name)
        }
        
        int
       -show_secret(struct safe *s, int fd, char *name)
       +check_master(struct safe *s)
       +{
       +        int r, fd;
       +
       +        fd = open("/dev/null", O_RDONLY);
       +        if (fd < 0)
       +                err(1, "/dev/null");
       +
       +        r = show_secret(s, fd, LOCK);
       +        close(fd);
       +
       +        return r;
       +}
       +
       +int
       +store_secret(struct safe *s, int fd, char *name)
        {
                int sfd, eof, flags = 0;
                ssize_t n;
                uint8_t m[BUFSIZ];
                uint8_t c[BUFSIZ + crypto_secretstream_xchacha20poly1305_ABYTES];
       -        unsigned long long mlen;
       +        unsigned long long clen;
        
       -        sfd = open(name, O_RDONLY);
       +        mkdir_p(dirname(name), 0700);
       +        sfd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600);
                if (sfd < 0)
                        err(1, "%s", name);
        
       -        xread(sfd, s->salt, sizeof(s->salt), NULL);
       -        xread(sfd, s->h, sizeof(s->h), NULL);
       -
       -        genkey(s);
       +        xwrite(sfd, s->salt, sizeof(s->salt));
        
                flags = SAFE_INIT;
       -        while ((n = xread(sfd, c, sizeof(c), &eof)) > 0) {
       +        while ((n = xread(fd, m, sizeof(m), &eof)) > 0) {
                        flags |= eof ? SAFE_FINAL : 0;
       -                if (secret_decrypt(s, c, n, m, &mlen, flags) < 0) {
       -                        fprintf(stderr, "%s: failed to decrypt password\n", name);
       +
       +                if (secret_encrypt(s, m, n, c, &clen, flags) < 0) {
                                close(sfd);
                                return -1;
                        }
        
       -                xwrite(fd, m, mlen);
       +                if (flags & SAFE_INIT)
       +                        xwrite(sfd, s->h, sizeof(s->h));
       +
       +                xwrite(sfd, c, clen);
                        flags &= ~(SAFE_INIT);
                }
        
       t@@ -403,8 +398,19 @@ main(int argc, char *argv[])
                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);
       +        } else {
       +                randombytes_buf(s.salt, sizeof(s.salt));
       +        }
       +
       +        readpass("password:", &passphrase, &pplen);
       +        deriv((char *)passphrase, &s);
       +
       +        if (check_master(&s) < 0) {
       +                fprintf(stderr, "master password incorrect\n");
       +                return -1;
                }
        
                if (dflag)
       t@@ -413,9 +419,9 @@ main(int argc, char *argv[])
                secret = argv[0];
        
                if (aflag) {
       -                store_secret(&s, STDIN_FILENO, secret);
       +                return store_secret(&s, STDIN_FILENO, secret);
                } else {
       -                show_secret(&s, STDOUT_FILENO, secret);
       +                return show_secret(&s, STDOUT_FILENO, secret);
                }
        
                return 0;