Add function for reading passphrase from terminal

This commit is contained in:
Juhani Krekelä 2021-04-09 01:07:30 +03:00
parent 7bf44017a4
commit 741c0d0bb5
1 changed files with 93 additions and 6 deletions

99
puer.c
View File

@ -1,8 +1,14 @@
#include <assert.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
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++) {