123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896 |
- #include <stdint.h>
- #include <wolfssl/options.h>
- #include <wolfssl/wolfcrypt/settings.h>
- #include <wolfssl/wolfcrypt/ecc.h>
- #include <wolfssl/wolfcrypt/pwdbased.h>
- #include <wolfssl/wolfcrypt/sha512.h>
- #include <wolfssl/wolfcrypt/chacha.h>
- #include "../src/cryptoengine.h"
- #include <fcntl.h>
- #include <err.h>
- #include <termio.h>
- #include <linux/serial.h>
- #include <stdio.h>
- #include <errno.h>
- #include <sys/poll.h>
- #define HOMEPATH_PREFIX "~/.pvault"
- //#define HOMEPATH_PREFIX "/root/.pvault"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define MAX_SVC_NAME_LEN 16
- static char pass_prompt[200] = "";
- static char pass_confirm[200] = "";
- static const char pass_prompt_phrase[] = "Enter your passphrase: ";
- static const char pass_confirm_phrase[] = "Confirm your passphrase : ";
- static const char pass_prompt_svc[] = "Password: ";
- static const char pass_confirm_svc[] = "Confirm Password: ";
- static int sfd = -1;;
- static int pk_fd = -1;
- static struct vault_status Status = { };
- static int get_vault_status(void);
- struct __attribute__((packed)) tofu_packet {
- uint32_t cdc_magic; /* 0x5afeca5e */
- uint16_t cdc_cmd;
- uint16_t cdc_len;
- struct vault_header vh;
- };
- void clearScreen() {
- system("clear");
- }
- void disableEcho() {
- struct termios term;
- tcgetattr(0, &term);
- term.c_lflag &= ~ECHO;
- tcsetattr(0, TCSANOW, &term);
- }
- void enableEcho() {
- struct termios term;
- tcgetattr(0, &term);
- term.c_lflag |= ECHO;
- tcsetattr(0, TCSANOW, &term);
- }
- void printPrompt() {
- printf(pass_prompt);
- }
- static void getPassword(char *password, int size) {
- int i = 0;
- char c;
- while (i < size - 1) {
- c = getchar();
- if (c == '\n') {
- break;
- }
- password[i++] = c;
- if (i >= 99)
- break;
- }
- password[i] = '\0';
- }
- int confirmPassphrase(const char *passphrase) {
- char confirmation[100];
- printf(pass_confirm);
- getPassword(confirmation, sizeof(confirmation));
- return strcmp(passphrase, confirmation) == 0;
- }
- static char passphrase[100];
- static int askpass(void)
- {
- int ret = 0;
- disableEcho();
- printPrompt();
- getPassword(passphrase, sizeof(passphrase));
- printf("\n");
- if (confirmPassphrase(passphrase)) {
- printf("\nConfirmed.\n");
- ret = 1;
- } else {
- printf("These passwords don't match. Please try again.\n");
- }
- enableEcho();
- return ret;
- }
- static int rate_to_constant(int baudrate) {
- #ifdef __MACH__
- #define B(x) case x: return x
- #else
- #define B(x) case x: return B##x
- #endif
- switch(baudrate) {
- B(50); B(75); B(110); B(134); B(150);
- B(200); B(300); B(600); B(1200); B(1800);
- B(2400); B(4800); B(9600); B(19200); B(38400);
- B(57600); B(115200); B(230400); B(460800); B(500000);
- B(576000); B(921600); B(1000000);B(1152000);B(1500000);
- default: return 0;
- }
- #undef B
- }
- /* Open serial port in raw mode, with custom baudrate if necessary */
- static int serial_open(const char *device, int rate)
- {
- struct termios options;
- int fd;
- int speed = 0;
- /* Open and configure serial port */
- if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1)
- return -1;
- speed = rate_to_constant(rate);
- #ifndef __MACH__
- if (speed == 0) {
- /* Custom divisor */
- struct serial_struct serinfo;
- serinfo.reserved_char[0] = 0;
- if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
- return -1;
- serinfo.flags &= ~ASYNC_SPD_MASK;
- serinfo.flags |= ASYNC_SPD_CUST;
- serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate;
- if (serinfo.custom_divisor < 1)
- serinfo.custom_divisor = 1;
- if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0)
- return -1;
- if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
- return -1;
- if (serinfo.custom_divisor * rate != serinfo.baud_base) {
- warnx("actual baudrate is %d / %d = %f",
- serinfo.baud_base, serinfo.custom_divisor,
- (float)serinfo.baud_base / serinfo.custom_divisor);
- }
- }
- #endif
- fcntl(fd, F_SETFL, 0);
- tcgetattr(fd, &options);
- cfsetispeed(&options, speed ?: 460800);
- cfsetospeed(&options, speed ?: 460800);
- cfmakeraw(&options);
- options.c_cflag |= (CLOCAL | CREAD);
- options.c_cflag &= ~CRTSCTS;
- if (tcsetattr(fd, TCSANOW, &options) != 0)
- return -1;
- return fd;
- }
- static int tofu(const char *password)
- {
- int ret = 0, i;
- int outlen = CRYPTO_KEY_SIZE;
- int siglen = PK_SIGNATURE_SIZE;
- uint8_t clr_sig[PK_SIGNATURE_SIZE];
- struct tofu_packet tofu;
- uint8_t Ke[CRYPTO_KEY_SIZE], Sm[CRYPTO_KEY_SIZE];
- uint8_t resp[256];
- char privkey_fname[32];
- uint32_t mgc = 0xffffffff;
- int hash, hash_len;
- uint8_t iv[24];
- uint8_t sig_dec_verify[64];
- struct pollfd pfd;
- uint32_t qxLen = CRYPTO_KEY_SIZE, qyLen = CRYPTO_KEY_SIZE,
- dLen = CRYPTO_KEY_SIZE;
- tofu.cdc_magic = VAULT_MAGIC;
- tofu.cdc_cmd = CDC_TOFU_INIT;
- tofu.cdc_len = sizeof(struct tofu_packet) - 8;
-
- tofu.vh.magic = VAULT_MAGIC;
- tofu.vh.size = sizeof(struct tofu_packet) - 8;
-
- ecc_key ecc;
- ChaCha cha;
- RNG rng;
-
- Sha512 sha;
- /* Initialize Rng (needed for master key + salt + secret */
- wc_InitRng(&rng);
-
- /* Generate ID */
- wc_RNG_GenerateBlock(&rng, (void *)tofu.vh.id, 8);
- sprintf(privkey_fname, "%08x-%08x.der", tofu.vh.id[0], tofu.vh.id[1]);
- printf("ID: %s\n", privkey_fname);
- /* Generate salt */
- wc_RNG_GenerateBlock(&rng, tofu.vh.host_salt, SALT_LEN);
- printf("Salt: ");
- for (i = 0; i < SALT_LEN; i++) {
- printf("%02x", tofu.vh.host_salt[i]);
- }
- printf("\n");
- /* Derive device key (password based) to create encryption key */
- ret = wc_PBKDF2(Ke, password, strlen(password), tofu.vh.host_salt, SALT_LEN, 1000, CRYPTO_KEY_SIZE, WC_SHA512);
- wc_Chacha_SetKey(&cha, Ke, CRYPTO_KEY_SIZE);
- wc_Chacha_SetIV(&cha, tofu.vh.host_seed, 0);
- /* Generate master signing key */
- wc_ecc_init(&ecc);
- wc_ecc_make_key(&rng, CRYPTO_KEY_SIZE, &ecc);
- qxLen = CRYPTO_KEY_SIZE;
- qyLen = CRYPTO_KEY_SIZE;
- wc_ecc_export_public_raw(&ecc, tofu.vh.auth_pubkey, &qxLen, tofu.vh.auth_pubkey + CRYPTO_KEY_SIZE, &qyLen);
- printf("Public signing key %d: ", qxLen + qyLen);
- for (i = 0; i < qxLen + qyLen; i++) {
- printf("%02x", tofu.vh.auth_pubkey[i]);
- }
- printf("\n");
-
- /* Generate key seed */
- wc_RNG_GenerateBlock(&rng, tofu.vh.host_seed, SEED_LEN);
- printf("Seed: ");
- for (i = 0; i < SEED_LEN; i++) {
- printf("%02x", tofu.vh.host_seed[i]);
- }
- printf("\n");
- wc_InitSha512(&sha);
- for (hash = 0; hash < SHA_PAYLOAD_SIZE;) {
- hash_len = WC_SHA512_BLOCK_SIZE;
- if ((SHA_PAYLOAD_SIZE - hash) < hash_len)
- hash_len = SHA_PAYLOAD_SIZE - hash;
- wc_Sha512Update(&sha, ((uint8_t*)&tofu.vh) + hash, hash_len);
- hash += hash_len;
- printf("update %d/%d\n", hash, SHA_PAYLOAD_SIZE);
- }
- wc_Sha512Final(&sha, tofu.vh.digest);
- printf("Digest (%d): ", sizeof(tofu.vh.digest));
- for (i = 0; i < sizeof(tofu.vh.digest); i++) {
- printf("%02x ", tofu.vh.digest[i]);
- if ((i % 16) == 15)
- printf("\n");
- }
- printf("\n");
- wc_Sha512Free(&sha);
- {
- mp_int r, s;
- mp_init(&r); mp_init(&s);
- ret = wc_ecc_sign_hash_ex(tofu.vh.digest, VAULT_DIGEST_SIZE, &rng, &ecc,
- &r, &s);
- mp_to_unsigned_bin(&r, &clr_sig[0]);
- mp_to_unsigned_bin(&s, &clr_sig[CRYPTO_KEY_SIZE]);
- mp_clear(&r);
- mp_clear(&s);
- }
- printf("Signature (%d) returned %d:\n", PK_SIGNATURE_SIZE, ret);
- for (i = 0; i < PK_SIGNATURE_SIZE; i++) {
- printf("%02x ", clr_sig[i]);
- if ((i % 16) == 15)
- printf("\n");
- }
- printf("\n");
- {
- int vr, vres;
- mp_int r, s;
- mp_init(&r); mp_init(&s);
- mp_read_unsigned_bin(&r, &clr_sig[0], CRYPTO_KEY_SIZE);
- mp_read_unsigned_bin(&s, &clr_sig[CRYPTO_KEY_SIZE], CRYPTO_KEY_SIZE);
- vr = wc_ecc_verify_hash_ex(&r, &s, tofu.vh.digest, VAULT_DIGEST_SIZE,
- &vres, &ecc);
- mp_clear(&r);
- mp_clear(&s);
- printf("sanity check verify ret %d res %d\n", vr, vres);
- }
- wc_Chacha_SetIV(&cha, tofu.vh.host_seed, 0);
- wc_Chacha_Process(&cha, tofu.vh.signature, clr_sig, siglen);
- wc_Chacha_SetIV(&cha, tofu.vh.host_seed, 0);
- wc_Chacha_Process(&cha, sig_dec_verify, tofu.vh.signature, siglen);
- if (memcmp(clr_sig, sig_dec_verify, siglen) != 0) {
- printf("Error verifying chacha encryption\n");
- return 4;
- }
- printf("Packet (%d): ", sizeof(tofu));
- for (i = 0; i < sizeof(tofu); i++) {
- printf("%02x ", *(((uint8_t*)(&tofu)) + i));
- if ((i % 16) == 15)
- printf("\n");
- }
- printf("\n");
- pfd.fd = sfd;
- pfd.events = POLLIN;
- for(i = 0; i < 10; i++) {
- char buf[8];
- ret = poll(&pfd, 1, 100);
- if (ret > 0) {
- read(sfd, buf, 8);
- }
- }
- ret = write(sfd, &tofu, sizeof(tofu));
- printf("Sent %d/%d bvtes (tofu) \r\n", ret, sizeof(tofu));
- do {
- ret = read(sfd, &mgc, 4);
- } while (mgc != 0x5afeca5e);
- memcpy (resp, &mgc, 4);
- ret = read(sfd, resp + 4, 64 + 4);
- if (ret >= 4) {
- uint16_t code = *((uint16_t *)(resp + 4));
- uint16_t len = *((uint16_t *)(resp + 6));
- printf("received %d bytes: resp %04x len %04x\n", ret + 4, *((uint16_t *)(resp + 4)), *((uint16_t *)(resp + 6)));
- if (ret > 4) {
- printf("MSG: %s\r\n", resp + 8);
- }
- if (code == CDC_OK) {
- int fd;
- uint8_t privkey_buf[2 * CRYPTO_KEY_SIZE];
- char pkfname[MAX_PATH];
- char *homedir;
- homedir = getenv("HOME");
- if (!homedir || strlen(homedir) == 0) {
- perror("getenv(HOME)");
- exit(1);
- }
- snprintf(pkfname, MAX_PATH - 1, "%s/.pvault/%s", homedir, privkey_fname);
- printf("Saving private key %s\n", privkey_fname);
- fd = open(pkfname, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0) {
- printf("FATAL Error opening private key: %s\n", strerror(errno));
- return 6;
- }
- outlen = 2 * CRYPTO_KEY_SIZE;
- if (wc_ecc_export_private_raw(&ecc, privkey_buf, &qxLen,
- privkey_buf + qxLen, &qyLen,
- privkey_buf + qxLen + qyLen, &dLen) != 0) {
- fprintf(stderr, "Unable to export private key to DER\n");
- exit(2);
- }
- outlen = qxLen + qyLen + dLen;
- printf("Exporting private key (%d bytes)\n", outlen);
- write(fd, privkey_buf, outlen);
- wc_ecc_free(&ecc);
- close(fd);
- }
- }
- return 0;
- }
- static void addservice(struct vault_service *vs, uint8_t *Ke)
- {
- struct vault_service vs_local;
- char gadget_passphrase[64];
- int ret;
- uint8_t Ke_local[CRYPTO_KEY_SIZE];
- uint8_t eccRawKey[CRYPTO_KEY_SIZE * 3];
- uint8_t snd_buffer[sizeof(struct cdc_packet_hdr) + SVC_SIZE];
- struct cdc_packet_hdr *hdr = (struct cdc_packet_hdr *)snd_buffer;
- int i;
- struct pollfd pfd;
- uint32_t mgc = 0;
- int interactive = 0;
- uint32_t slot = 0;
- Sha512 sha;
- ecc_key ecc;
- ChaCha cha;
- RNG rng;
- strcpy(pass_prompt, pass_prompt_svc);
- strcpy(pass_confirm, pass_confirm_svc);
- if (!vs) {
- vs = &vs_local;
- Ke = Ke_local;
- interactive = 1;
- printf("Service name (max 16 char.) : ");
- scanf("%s", vs->name);
- printf("\n");
- printf("Username (empty = none) : ");
- if (scanf("%s", vs->user) <= 0)
- vs->user[0] = '\0';
- getchar();
- while(!askpass()) {
- printf("Press a key to continue...\r\n");
- getchar();
- }
- strcpy((char *)(vs->pass), passphrase);
- }
- vs->flags = SVC_FLAG_ACTIVE;
- vs->reserved = 0;
- if (!Ke) {
- printf("Unspecified key\n");
- return;
- }
- wc_InitSha512(&sha);
- wc_Sha512Update(&sha, (uint8_t *)vs, WC_SHA512_BLOCK_SIZE);
- wc_Sha512Final(&sha, vs->dig);
- printf("\n----- RECAP -----\n");
- printf("Service name: %s\n", vs->name);
- printf("Username: %s\n", vs->user);
- printf("Password: ******\n");
- printf("Sha: ");
- for (i = 0; i < VAULT_DIGEST_SIZE; i++) {
- printf("%02x", vs->dig[i]);
- }
- printf("\n-----------------\n\n");
- if (interactive) {
- printf("Service configured, press a key to send, ctrl+c to abort...\r\n");
- disableEcho();
- printf("Enter gadget passphrase to encrypt and send info: ");
- getPassword(gadget_passphrase, 64);
- enableEcho();
- printf("\n");
- /* Derive device key (password based) to create encryption key */
- ret = wc_PBKDF2(Ke, gadget_passphrase, strlen(gadget_passphrase),
- Status.salt, SALT_LEN, 1000, CRYPTO_KEY_SIZE, WC_SHA512);
- if (ret < 0) {
- printf("Failed to derive password.\n");
- return;
- }
- }
- lseek(pk_fd, SEEK_SET, 0);
- ret = read(pk_fd, eccRawKey, CRYPTO_KEY_SIZE * 3);
- if (ret != CRYPTO_KEY_SIZE * 3) {
- printf("Error reading signing key\n");
- return;
- }
- wc_ecc_init(&ecc);
- if (wc_ecc_import_unsigned(&ecc, eccRawKey, eccRawKey + CRYPTO_KEY_SIZE,
- eccRawKey + 2 * CRYPTO_KEY_SIZE, ECC_SECP256R1) < 0) {
- printf("Failed importing signing key\n");
- return;
- }
- slot = Status.first_avail;
- /* Initialize Rng (needed for sign)*/
- wc_InitRng(&rng);
- printf("Slot is %u\n", slot);
- {
- mp_int r, s;
- mp_init(&r); mp_init(&s);
- ret = wc_ecc_sign_hash_ex(vs->dig, VAULT_DIGEST_SIZE, &rng, &ecc,
- &r, &s);
- mp_to_unsigned_bin(&r, &vs->sig[0]);
- mp_to_unsigned_bin(&s, &vs->sig[CRYPTO_KEY_SIZE]);
- mp_clear(&r);
- mp_clear(&s);
- }
- printf("Signature (%d):\n", PK_SIGNATURE_SIZE);
- for (i = 0; i < PK_SIGNATURE_SIZE; i++) {
- printf("%02x ", vs->sig[i]);
- if ((i % 16) == 15)
- printf("\n");
- }
- printf("\n");
- wc_ecc_free(&ecc);
- /* Copy the part in clear (flags, reserved) */
- memcpy(snd_buffer + sizeof(struct cdc_packet_hdr), vs, SVC_ENC_OFF);
- /* Set Key and IV */
- wc_Chacha_SetKey(&cha, Ke, CRYPTO_KEY_SIZE);
- wc_Chacha_SetIV(&cha, Status.seed, SVC_FLASH_OFFSET + slot * SVC_SIZE);
- wc_Chacha_Process(&cha, snd_buffer + sizeof(struct cdc_packet_hdr) + SVC_ENC_OFF,
- ((uint8_t *)(vs)) + SVC_ENC_OFF, SVC_ENC_SIZE);
- hdr->magic = VAULT_MAGIC;
- hdr->cmd = CDC_ADDSERV;
- hdr->len = SVC_SIZE;
- pfd.fd = sfd;
- pfd.events = POLLIN;
- for (i = 0; i < 10; i++) {
- char buf[8];
- ret = poll(&pfd, 1, 10);
- if (ret > 0) {
- read(sfd, buf, 8);
- }
- }
-
- printf("Packet (%d): ", sizeof(snd_buffer));
- for (i = 0; i < sizeof(snd_buffer); i++) {
- printf("%02x ", snd_buffer[i]);
- if ((i % 16) == 15)
- printf("\n");
- }
- printf("\n");
- printf("Sending svc packet... \n");
- write(sfd, snd_buffer, sizeof(snd_buffer));
- for (i = 0; i < 3; i++) {
- char buf[256];
- ret = poll(&pfd, 1, 5000);
- if (ret > 0) {
- uint16_t code;
- do {
- ret = read(sfd, &mgc, 4);
- } while (mgc != 0x5afeca5e);
- ret = read(sfd, buf, 256);
- code = *((uint16_t *)(buf));
-
- printf("Received response (code %02x, len %d): %s\n",
- code, ret, (code == CDC_FAIL)?(buf + 4):"");
- if ((code == CDC_FAIL) || ((code == CDC_OK) && ret == 4))
- break;
- }
- }
- }
- char* removeQuotes(char* str) {
- int len = strlen(str);
- int i;
- for (i = 0; i < len; i++)
- if (str[i] != '\"')
- break;
- str = str + i;
- len = strlen(str);
- for (i = len -1; i > 0; i--)
- if (str[i] == '\"')
- str[i] = '\0';
- return str;
- }
- static void parseCSV(const char* filename) {
- struct vault_service svc;
- FILE* file = fopen(filename, "r");
- uint8_t cKe[CRYPTO_KEY_SIZE];
- int ret;
- char gadget_passphrase[64 + 1];
- char line[1024];
- int header_line_skipped = 0;
- if (file == NULL) {
- printf("Failed to open the file.\n");
- return;
- }
- printf("Enter gadget passphrase to encrypt and send info: ");
- disableEcho();
- getPassword(gadget_passphrase, 64);
- enableEcho();
- printf("\n");
- /* Derive device key (password based) to create encryption key */
- ret = wc_PBKDF2(cKe, gadget_passphrase, strlen(gadget_passphrase),
- Status.salt, SALT_LEN, 1000, CRYPTO_KEY_SIZE, WC_SHA512);
- if (ret < 0) {
- printf("Failed to derive password.\n");
- return;
- }
- while (fgets(line, sizeof(line), file)) {
- int i;
- // Skip header line
- if (!header_line_skipped) {
- header_line_skipped = 1;
- continue;
- }
- // Parse each line of the CSV
- char* token = strtok(line, ",");
- if (token == NULL) {
- continue;
- }
- // Remove quotes from the fields
- token = removeQuotes(token);
- char* url = token;
- // Strip "https:" if present
- if (strncmp(url, "https:", 6) == 0) {
- url += 6;
- }
-
- // Strip "http:" if present
- if (strncmp(url, "http:", 5) == 0) {
- url += 6;
- }
- // Strip slashes ("/") if present
- while (*url == '/') {
- url++;
- }
- // Strip content after the domain name if present
- char* slash = strchr(url, '/');
- if (slash != NULL) {
- *slash = '\0';
- }
- // Parse the domain from right to left
- char* domainStart = NULL;
- char domain[MAX_SVC_NAME_LEN + 1] = "";
- char *domainDot = strrchr(url, '.');
- if (domainDot != NULL) {
- *domainDot=',';
- domainStart = strrchr(url, '.');
- *domainDot='.';
- }
- if (domainStart == NULL) {
- strncpy(domain, url, MAX_SVC_NAME_LEN);
- domain[strlen(url)] = '\0';
- } else {
- int domainLen = strlen(domainStart + 1);
- strncpy(domain, domainStart + 1, domainLen);
- }
- // Store the extracted domain, user, and pass fields
- memset(&svc, 0, sizeof(svc));
- printf("Domain: %s\n", domain);
- strncpy(svc.name,domain, 16);
- token = strtok(NULL, ",");
- if (token != NULL) {
- token = removeQuotes(token);
- strncpy(svc.user, token, sizeof(svc.user) - 1);
- }
- token = strtok(NULL, ",");
- if (token != NULL) {
- token = removeQuotes(token);
- strncpy(svc.pass, token, sizeof(svc.pass));
- }
- for (i = 0; i < 3; i++) {
- ret = get_vault_status();
- if (ret == 0)
- break;
- }
- if (ret < 0) {
- printf("Adding service: failed.\n");
- getchar();
- return;
- }
- addservice(&svc, cKe);
- }
- fclose(file);
- }
- void printMenu() {
- printf("\n");
- printf("0) Device status\n");
- printf("1) TOFU\n");
- printf("2) Add service\n");
- printf("3) Import passwords from CSV\n");
- printf("q) Quit\n\n");
- }
- char getUserInput() {
- char input;
- printf("Choice: ");
- scanf(" %c", &input);
- getchar(); // Consume the newline character
- return input;
- }
- void processChoice(char choice) {
- char csv_filename[PATH_MAX];
- switch (choice) {
- case '0':
- // Handle option 0 (Device status)
- clearScreen();
- printf("Device status selected.\n");
- break;
- case '1':
- // Handle option 1 (TOFU)
- clearScreen();
- printf("TOFU selected.\n");
- strcpy(pass_prompt, pass_prompt_phrase);
- strcpy(pass_confirm, pass_confirm_phrase);
- memset(passphrase, 0, sizeof(passphrase));
- while(!askpass()) {
- printf("Press a key to continue...\r\n");
- getchar();
- }
- tofu(passphrase);
- break;
- case '2':
- // Handle option 2 (Add service)
- clearScreen();
- printf("Add service selected.\n");
- strcpy(pass_prompt, pass_prompt_phrase);
- strcpy(pass_confirm, pass_confirm_phrase);
- if (Status.state < 0x02) {
- printf("Cannot add service: device not initialized.\n");
- break;
- }
- if (pk_fd < 0) {
- printf("Cannot add service: private key not present for this device.\n");
- break;
- }
- addservice(NULL, NULL);
- break;
- case '3':
- // Handle option 3 (Import CSV)
- clearScreen();
- printf("CSV file: ");
- scanf("%s", csv_filename);
- getchar();
- parseCSV(csv_filename);
- break;
- case 'q':
- case 'Q':
- // Quit the program
- printf("Quitting...\n");
- exit(0);
- default:
- printf("Invalid choice.\n");
- break;
- }
- printf("Press Enter to continue...\n");
- getchar(); // Wait for Enter key
- }
- static int get_vault_status(void)
- {
- uint32_t rcount = 0;
- struct cdc_packet_hdr hdr;
- int ret;
- int i;
- struct pollfd pfd;
- uint8_t rxbuf[sizeof(struct cdc_packet_hdr) + sizeof(struct vault_status)];
- pfd.fd = sfd;
- pfd.events = POLLIN;
- hdr.magic = VAULT_MAGIC;
- hdr.cmd = CDC_STATUS;
- hdr.len = 0;
- for (i = 0; i < 3; i++) {
- ret = write(sfd, &hdr, sizeof(hdr));
- if (ret <= 0)
- return ret;
-
- ret = poll(&pfd, 1, 1000);
- if (ret == 0) {
- printf("Get status: timeout");
- continue;
- }
- if (ret < 0) {
- perror("get_status(): polling device");
- return -1;
- }
- do {
- ret = read(sfd, rxbuf + rcount, sizeof(rxbuf) - rcount);
- if (ret < 0) {
- return -1;
- }
- rcount += ret;
- } while (rcount < sizeof(rxbuf));
- break;
- }
- if (rcount > 0) {
- if (*(uint32_t *)(rxbuf) != VAULT_MAGIC)
- return -2;
- if (*(uint16_t *)(rxbuf + 4) != CDC_STATUS)
- return -3;
- memcpy(&Status, rxbuf + sizeof(struct cdc_packet_hdr), sizeof(Status));
- return 0;
- }
- return -1;
- }
- static const char vstatenames[][32] = {
- "OFF",
- "TOFU",
- "BOOTUP",
- "VERIFY_PASSPHRASE",
- "VERIFY_FAILED",
- "MAIN_MENU",
- "SETTINGS_MENU",
- "SERVICE_LIST"
- };
- int main(int argc, char *argv[])
- {
- clearScreen();
- system("mkdir -p " HOMEPATH_PREFIX);
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s TTY\n", argv[0]);
- return 2;
- }
- sfd = serial_open(argv[1], 115200);
- if (sfd < 0) {
- perror("serial_open");
- if (errno == EACCES) {
- printf("\n\nPerhaps you should review your permission for %s, or 'sudo adduser $YOUR_USER dialout'\r\n", argv[1]);
- }
- return 1;
- }
- while (1) {
- char choice;
- if (get_vault_status() < 0) {
- printf("Not connected\n");
- } else {
- char pkfname[MAX_PATH];
- char *homedir;
- homedir = getenv("HOME");
- if (!homedir || strlen(homedir) == 0) {
- perror("getenv(HOME)");
- exit(1);
- }
- snprintf(pkfname, MAX_PATH - 1, "%s/.pvault/%08x-%08x.der", homedir, Status.id[0], Status.id[1]);
- printf("Device %08x-%08x Connected.\n", Status.id[0], Status.id[1]);
- pk_fd = open(pkfname, O_RDONLY);
- if (pk_fd < 0) {
- perror("open");
- printf(pkfname);
- printf("\n");
- printf("Private key not available.\n");
- } else {
- printf("Private key loaded.\n");
- }
- printf("State: %s - Services: %hu. Spot: %hu\n",
- vstatenames[Status.state], Status.services_active, Status.first_avail);
- }
- printMenu();
- choice = getUserInput();
- processChoice(choice);
- }
- return 0;
- }
|