Be more friendly and ask for new passphrases

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët 2020-05-06 19:34:46 +00:00
parent d97f17d742
commit 2dfc2ab17a
2 changed files with 46 additions and 42 deletions

View file

@ -13,7 +13,7 @@ But it does have some interesting features:
- A secret agent that only trusts subprocesses. Not all the processes of the same user!
- Secret names completion is available after calling the secret agent.
- Supports unstored secrets. Derived from some simple keys and a passphrase.
- Supports multiple passphrases. Not super user-friendly but nice to have.
- Supports multiple passphrases. A confirmation is requested for each new passphrase.
- Depends only on the [libhydrogen](https://libhydrogen.org/) library.
- Small, simple and non obfuscated C code. Well, I hope so :)

View file

@ -49,6 +49,7 @@ struct {
char ctx_master[hydro_pwhash_CONTEXTBYTES];
char ctx_secret[hydro_secretbox_CONTEXTBYTES];
char ctx_passwd[hydro_pwhash_CONTEXTBYTES];
int known_key;
} s = {
.pipe = {-1, -1},
.ctx_master = "MASTER",
@ -180,11 +181,27 @@ s_input(unsigned char *buf, size_t size, const char *prompt)
if (buf[i] < ' ')
s_fatal("Invalid input!");
}
hydro_memzero(buf + len, size - len);
return len;
}
static void
s_ask_pass(void *buf, size_t size, const char *prompt)
{
unsigned char pass[128];
size_t len = s_input(pass, sizeof(pass), prompt);
if (!len)
s_exit(0);
int r = hydro_pwhash_deterministic(buf, size,
(char *)pass, len,
s.ctx_master, s.hdr.master,
load64_le(s.hdr.opslimit), 0, 1);
hydro_memzero(pass, sizeof(pass));
if (r) s_oops(__LINE__);
}
static int
s_open_secret(int use_tty)
{
@ -221,43 +238,10 @@ s_open_secret(int use_tty)
if (!use_tty)
s_exit(0);
unsigned char pass[128];
size_t len = s_input(pass, sizeof(pass), "Passphrase: ");
if (!len)
s_exit(0);
int r = hydro_pwhash_deterministic(s.x.key, sizeof(s.x.key),
(char *)pass, len,
s.ctx_master, s.hdr.master,
load64_le(s.hdr.opslimit), 0, 1);
hydro_memzero(pass, sizeof(pass));
if (r)
s_oops(__LINE__);
s_ask_pass(s.x.key, sizeof(s.x.key), "Passphrase: ");
return fd;
}
static void
s_print_keys(int use_tty)
{
int fd = s_open_secret(use_tty);
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
if (hydro_secretbox_decrypt(&s.x.entry,
s.enc, sizeof(s.enc), 0,
s.ctx_secret, s.x.key))
continue;
size_t len = strnlen(s.x.entry.msg, sizeof(s.x.entry.msg));
if (len >= sizeof(s.x.entry.msg))
s_oops(__LINE__);
s_write(1, s.x.entry.msg, len);
s_write(1, "\n", 1);
}
close(fd);
}
static size_t
s_keylen(const char *str)
{
@ -273,6 +257,22 @@ s_keylen(const char *str)
s_fatal("Keys are limited to %u bytes", S_KEYLENMAX);
}
static void
s_print_keys(int use_tty)
{
int fd = s_open_secret(use_tty);
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
if (hydro_secretbox_decrypt(&s.x.entry,
s.enc, sizeof(s.enc), 0,
s.ctx_secret, s.x.key))
continue;
s_write(1, s.x.entry.msg, s_keylen(s.x.entry.msg));
s_write(1, "\n", 1);
}
close(fd);
}
static const char *
s_get_secret(int fd, const char *key, int create)
{
@ -290,6 +290,7 @@ s_get_secret(int fd, const char *key, int create)
s_fatal("seek: %s", strerror(errno));
return &s.x.entry.msg[len + 1];
}
s.known_key = 1;
}
if (!create)
s_fatal("Secret %s not found", key);
@ -388,6 +389,13 @@ s_do(int argc, char **argv, void *data)
int fd = s_open_secret(1);
const char *old = s_get_secret(fd, argv[1], op & s_op_create);
if (!old && !s.known_key) {
char check[sizeof(s.x.key)];
s_ask_pass(check, sizeof(check), "Never used? Retype to confirm: ");
if (!hydro_equal(s.x.key, check, sizeof(check)))
s_fatal("Passphrases don't match!");
}
unsigned char secret[S_ENTRYSIZE];
size_t len = S_PWDGENLEN;
@ -398,7 +406,7 @@ s_do(int argc, char **argv, void *data)
} else {
len = isatty(0) ? s_input(secret, sizeof(secret), "Secret: ")
: s_read(0, secret, sizeof(secret));
if (!len && argc == 3) {
if (!len && old && argc == 3) {
len = load16_le(s.x.entry.slen);
memcpy(secret, old, len);
}
@ -442,7 +450,6 @@ s_pass(int argc, char **argv, void *data)
printf("Usage: %s KEY [SUBKEY...]\n", argv[0]);
return 0;
}
close(s_open_secret(1));
uint8_t buf[hydro_pwhash_MASTERKEYBYTES];
@ -456,10 +463,8 @@ s_pass(int argc, char **argv, void *data)
s.ctx_passwd, key,
load64_le(s.hdr.opslimit), 0, 1);
memcpy(key, buf, sizeof(key));
if (r)
s_oops(__LINE__);
if (r) s_oops(__LINE__);
}
s_normalize_and_show(buf, S_PWDGENLEN);
return 0;
}
@ -627,7 +632,6 @@ s_set_path(void)
if (ret <= 0 || (size_t)ret >= sizeof(s.path))
s_fatal("Invalid path... Check $HOME or $" S_ENV_STORE);
break;
}
}