commit 2ad29d8bf07bc72234ed66c66317fe0ef7678507
parent 3819d0382a8016c55f467305555f7f88b1bda1f1
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Mon, 15 Mar 2021 22:29:31 -0500
we have password adding!
Diffstat:
A | npwm.c | | | 137 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | util.c | | | 25 | +++++++++++++++++++++++++ |
A | util.h | | | 7 | +++++++ |
3 files changed, 169 insertions(+), 0 deletions(-)
diff --git a/npwm.c b/npwm.c
@@ -0,0 +1,137 @@
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/random.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "chacha20.h"
+#include "pkcs5_pbkdf2.h"
+#include "util.h"
+
+#define PASSWORD_MAX_LEN 512
+#define PASSPHRASE_MAX_LEN 512
+#define KEY_LEN 32
+#define NONCE_LEN 12
+#define SALT_LEN 8
+#define ROUNDS 2000
+
+char *valid;
+int len;
+
+int
+isvalid(char c)
+{
+ int len;
+ if (strcmp(valid, "print") == 0)
+ return isprint(c);
+ else if (strcmp(valid, "alnum") == 0)
+ return isalnum(c);
+ else {
+ /* TODO validate valid */
+ for (int i = 0; i < strlen(valid); i++) {
+ if (c == valid[i])
+ return 1;
+ }
+
+ return 0;
+ }
+}
+
+int
+gen(char *buf)
+{
+ int i = 0;
+ char c;
+ while (i < len) {
+ getrandom(&c, 1, 0);
+
+ if (isvalid(c)) {
+ buf[i] = c;
+ i++;
+ }
+ }
+}
+
+int
+getpassphrase(char *buf)
+{
+ struct termios old, new;
+ char *c;
+ fputs("Passphrase: ", stderr);
+
+ if (isatty(STDIN_FILENO)) {
+ if (tcgetattr(STDIN_FILENO, &old) == -1)
+ return -1;
+ new = old;
+ new.c_lflag &= ~(ICANON | ECHO);
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &new) == -1)
+ return -1;
+ }
+
+ if (fgets(buf, PASSPHRASE_MAX_LEN, stdin) == NULL)
+ return -1;
+
+ if (isatty(STDIN_FILENO)) {
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &old) == -1)
+ return -1;
+
+ putchar('\n');
+ }
+ if ((c = strchr(buf, '\n')) == NULL)
+ die("passphrase too long");
+
+ c = '\0';
+}
+
+int main(int argc, char *argv[]) {
+ char password[PASSWORD_MAX_LEN];
+ char passphrase[PASSPHRASE_MAX_LEN];
+ char key[KEY_LEN];
+ char nonce[NONCE_LEN];
+ char salt[SALT_LEN];
+ int vlen;
+
+ if (argc == 2 && strcmp(argv[1], "-g") == 0) {
+ if (getpassphrase(passphrase) == -1)
+ die("failed to read password");
+
+ if (getrandom(salt, SALT_LEN, 0) < SALT_LEN)
+ die("failed to generate salt");
+
+ if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, SALT_LEN, key,
+ KEY_LEN, ROUNDS) == -1)
+ die("key derivation failed");
+
+ if (getrandom(nonce, NONCE_LEN, 0) < NONCE_LEN)
+ die("failed to generate nonce");
+
+ errno = 0;
+ len = strtol(getenv("NPWM_LENGTH"), NULL, 10);
+ if (errno || len <= 0 || len > PASSWORD_MAX_LEN)
+ die("invalid value for NPWM_LENGTH:");
+
+ if ((valid = getenv("NPWM_VALID")) == NULL)
+ valid = "print";
+
+ if ((vlen = strlen(valid)) > 0x7F - 0x20)
+ die("NPWM_VALID should not contain duplicate or non-printable characters");
+
+ for (int i = 0; i < vlen; i++) {
+ if (!isprint(valid[i]))
+ die("NPWM_VALID may not contain non-printable characters");
+
+ for (int j = 0; j < i; j++)
+ if (valid[i] == valid[j])
+ die("NPWM_VALID may not contain duplicate characters");
+ }
+
+ memset(password, 0, PASSWORD_MAX_LEN);
+ gen(password);
+
+ br_chacha20_ct_run(key, nonce, 0, password, len);
+ }
+}
diff --git a/util.c b/util.c
@@ -0,0 +1,25 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void
+die(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ } else {
+ fputc('\n', stderr);
+ }
+
+ exit(1);
+}
diff --git a/util.h b/util.h
@@ -0,0 +1,7 @@
+/* See LICENSE file for copyright and license details. */
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
+
+void die(const char *fmt, ...);