From 741c0d0bb5e2e656000771681b4adf10e3cfb798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Fri, 9 Apr 2021 01:07:30 +0300 Subject: [PATCH] Add function for reading passphrase from terminal --- puer.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/puer.c b/puer.c index d4fffd8..f2b3f21 100644 --- a/puer.c +++ b/puer.c @@ -1,8 +1,14 @@ #include +#include +#include #include #include +#include #include -#include +#include +#include +#include +#include void xxtea128(uint32_t const key[4], uint32_t block[4]) { // Encryption half of the XXTEA algorithm, with block size limited @@ -427,11 +433,93 @@ bool ccm_decrypt(unsigned char key[16], uint32_t messageindex, unsigned char mes return true; } +size_t passphrase_prompt(unsigned char *passphrase, size_t size, const char *prompt) { + // Read from controlling TTY, even if stdion has been redirected + int tty = open("/dev/tty", O_RDWR); + if (tty == -1) { + perror("Failed to open controlling tty"); + exit(1); + } + + if (write(tty, prompt, strlen(prompt)) == -1) { + perror("Failed to write to terminal"); + exit(1); + } + + // Turn off echo + struct termios saved; + if (tcgetattr(tty, &saved) != 0) { + perror("tcgetattr"); + exit(1); + } + struct termios altered; + altered = saved; + altered.c_lflag &= ~ECHO; + if (tcsetattr(tty, TCSANOW, &altered) != 0) { + perror("tcsetattr"); + exit(1); + } + + // Read until newline + size_t index = 0; + for (;;) { + if (index >= size) { + fprintf(stderr, "Passphrase too long, maximum size is %zu bytes\n", size - 1); + // Clean any line buffer + char tmp; + for (;;) { + if (read(tty, &tmp, 1) <= 0) { + break; + } + if (tmp == '\n') { + break; + } + } + tcsetattr(tty, TCSANOW, &saved); + exit(1); + } + + ssize_t bytes_read = read(tty, &passphrase[index], size - index); + if (bytes_read == -1) { + perror("Failed to read passphrase"); + tcsetattr(tty, TCSANOW, &saved); + exit(1); + } else if (bytes_read == 0) { + fprintf(stderr, "Unexpected EOF\n"); + tcsetattr(tty, TCSANOW, &saved); + exit(1); + } + + index += bytes_read; + if (passphrase[index-1] == '\n') { + // Got end of line + break; + } + } + + // Write a newline (since the user's is not visible) and restore + // terminal settings + if (write(tty, "\n", 1) == -1) { + perror("Failed to write to terminal"); + exit(1); + } + tcsetattr(tty, TCSANOW, &saved); + close(tty); + + return index - 1; +} + int main(void) { - unsigned char key[16] = {0}; - unsigned char salt[32] = "seasaltrocksalt seasaltrocksalt"; - unsigned char passphrase[] = "a quick brown fox jumps over the lazy dog"; - kdf(key, salt, passphrase, sizeof(passphrase) - 1); + unsigned char salt[32]; + if (getentropy(salt, 32) != 0) { + perror("getentropy"); + } + + unsigned char passphrase[128] = {0}; + size_t passphrase_len = passphrase_prompt(passphrase, sizeof(passphrase), "passphrase: "); + + unsigned char key[16]; + kdf(key, salt, passphrase, passphrase_len); for (size_t i = 0; i < 16; i++) { printf("%02hhx ", key[i]); } @@ -455,7 +543,6 @@ int main(void) { } printf("\n"); - bool auth = ccm_decrypt(key, 25, buf, strlen(message), &buf[48]); printf("auth %s\n", auth ? "succeeded" : "failed"); for (size_t i = 0; i < sizeof(buf); i++) {