safe

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

commit 5254f08121341ae91042257b11bd299788f3ebd5
parent 5bca68cbe7e38dd4c00464515a9755196db4fc8b
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:
safe.c | 92++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 49 insertions(+), 43 deletions(-)

diff --git a/safe.c b/safe.c @@ -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); } @@ -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); } @@ -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); } @@ -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) @@ -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;