Differences From
Artifact [7a6fbd2214]:
80 80 typedef enum {
81 81 tbl_ok = ok, tbl_error = fail
82 82 } tbl_error_type;
83 83 typedef unsigned char tbl_word_type;
84 84 #include "clib/tbl.c"
85 85
86 86 #include "opt.inc"
87 +
88 +typedef uint8_t key_priv [db_privkey_len];
89 +typedef uint8_t key_pub [db_pubkey_len];
90 +typedef uint8_t db_sz;
91 +typedef uint8_t byte;
87 92
88 93 #define str_ucase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
89 94 #define str_lcase "abcdefghijklmnopqrstuvwxyz"
90 95 #define str_num "0123456789"
91 96 const char* reftbl = str_num str_ucase str_lcase;
92 97 const char* reftbl_lcase = str_num str_lcase;
93 98
................................................................................
224 229 }
225 230
226 231 buf[len] = '\n';
227 232
228 233 return ok;
229 234 }
230 235
231 -struct entry {
232 - pstr account;
233 - pstr pw;
234 -};
236 +void
237 +bytedump(byte* bytes, size_t sz) {
238 + for (size_t i = 0; i < sz; ++i) {
239 + char tpl[] ="\x1b[35m \x1b[m";
240 + char* c = tpl + 5;
241 + *c = bytes[i];
242 + if (*c < ' ' || *c > '~') *c='.', write(2, tpl, sz(tpl));
243 + else write(2, c, 1);
244 + }
245 +}
246 +
247 +void
248 +hexdump(byte* bytes, size_t sz) {
249 + if(!_g_debug_msgs) return;
250 + alert(a_debug, "printing hex dump");
251 + byte* st = bytes;
252 + write(2, _str("\t\x1b[94m"));
253 + for (size_t i = 0; i < sz; ++i) {
254 + char hex[5] = " ";
255 + kitoa(16, bytes[i], hex, hex + 2, NULL, true);
256 + write(2, hex, 4);
257 + if(!((i+1)%8)) {
258 + write(2, _str("\x1b[;1m│\x1b[m "));
259 + bytedump(st, 8);
260 + write(2, "\n\t\x1b[94m", (i == sz - 1 ? 1 : 7));
261 + st += 8;
262 + } else if (i == sz - 1) {
263 + write(2, _str("\x1b[;1m│\x1b[m "));
264 + bytedump(st, (bytes + sz) - st);
265 + write(2, _str("\n\x1b[m"));
266 + }
267 + }
268 +}
269 +
270 +struct dbrecord { pstr acct; pstr pw; };
271 +
272 +enum bad
273 +dbtell(int db, db_sz* ciphlen, db_sz* plainlen){
274 + if (read(db, ciphlen, 1) != 1)
275 + return fail;
276 + *plainlen = *ciphlen - crypto_box_SEALBYTES;
277 + return ok;
278 +}
279 +
280 +enum bad
281 +dbnext(int db, struct dbrecord* rec, db_sz acctlen,
282 + byte* pub, byte* priv,
283 + byte ciphertext[static acctlen],
284 + byte plaintext[static acctlen - crypto_box_SEALBYTES]) {
285 + db_sz plaintext_sz = acctlen - crypto_box_SEALBYTES;
286 +
287 + if (read(db, ciphertext, acctlen) != acctlen)
288 + return bad_db_corrupt;
289 + alert(a_debug, "scanned record");
290 + hexdump(ciphertext, acctlen);
291 +
292 + if(crypto_box_seal_open(plaintext, ciphertext, acctlen, pub, priv) != 0)
293 + return bad_db_corrupt;
294 +
295 + alert(a_debug, "record deciphered");
296 + hexdump(plaintext, plaintext_sz);
297 +
298 + db_sz record_name_len = plaintext[0],
299 + record_pw_len = plaintext[record_name_len + 1];
300 +
301 + rec -> acct.len = record_name_len;
302 + rec -> acct.ptr = plaintext + 1;
303 + rec -> pw.len = record_pw_len;
304 + rec -> pw.ptr = plaintext + record_name_len + 2;
305 +
306 + return ok;
307 +}
308 +
309 +enum bad
310 +dbappend(struct dbrecord rec) {
311 + return ok;
312 +}
235 313
236 314 enum term_clear {term_clear_line,
237 315 term_clear_screen};
238 316
239 317 void term_clear(int tty, enum term_clear behavior) {
240 318 switch(behavior) {
241 319 case term_clear_line: write(tty,"\r\x1b[2K",5); break;
242 320 case term_clear_screen: write(tty,"\r\x1b[3J",5); break;
243 321 }
244 322 }
245 323 void term_bell(int tty) {
246 324 write(tty,"\a",1);
247 325 }
248 -
326 +#include<stdio.h>
249 327 typedef char password[kpw_db_pw_max + 1];
250 328 bad pwread(bool obscure, char* dest, size_t* out_len, const char* prompt, const size_t plen) {
251 329 if (isatty(0)) {
252 330 int tty = 1;
253 331 if (!isatty(tty)) tty = open("/dev/tty", O_WRONLY);
254 332 if (tty == -1) return bad_insane;
255 333
................................................................................
309 387
310 388 if (tty != 1) close(tty);
311 389 } else {
312 390 alert(a_warn, "reading pw from standard input");
313 391 ssize_t ct = read(0, dest, kpw_db_pw_max);
314 392 dest[ct] = 0;
315 393 }
394 + return ok;
316 395 }
317 396
318 397 int
319 398 dbopen(int flags) {
320 399 const char* dbpath = getenv("kpw_db");
321 400 int db;
322 401 if (dbpath == NULL) {
................................................................................
344 423 } else {
345 424 db = open(dbpath, flags, 0600);
346 425 }
347 426
348 427 return db;
349 428 }
350 429
351 -void bytedump(uint8_t* bytes, size_t sz) {
352 - for (size_t i = 0; i < sz; ++i) {
353 - char tpl[] ="\x1b[35m \x1b[m";
354 - char* c = tpl + 5;
355 - *c = bytes[i];
356 - if (*c < ' ' || *c > '~') *c='.', write(2, tpl, sz(tpl));
357 - else write(2, c, 1);
358 - }
359 -}
360 -
361 -void hexdump(uint8_t* bytes, size_t sz) {
362 - if(!_g_debug_msgs) return;
363 - alert(a_debug, "printing hex dump");
364 - uint8_t* st = bytes;
365 - for (size_t i = 0; i < sz; ++i) {
366 - char hex[5] = " ";
367 - kitoa(16, bytes[i], hex, hex + 2, NULL, true);
368 - write(2, hex, 4);
369 - if(!((i+1)%8)) {
370 - write(2, _str("│ "));
371 - bytedump(st, 8);
372 - write(2, "\n", 1);
373 - st += 8;
374 - } else if (i == sz - 1) {
375 - write(2, _str("│ "));
376 - bytedump(st, (bytes + sz) - st);
377 - write(2, "\n", 1);
378 - }
379 - }
430 +enum bad
431 +dbheader_load (int db, byte* salt, byte* salt_enc, byte* pub, byte* priv_enc) {
432 + const size_t salt_sz = crypto_pwhash_SALTBYTES,
433 + salt_enc_sz = crypto_box_SEALBYTES + salt_sz,
434 + pub_sz = sizeof(key_pub),
435 + priv_sz = sizeof(key_priv);
436 +
437 + alert(a_debug, "loading public key");
438 + ssize_t sr = read(db, pub, pub_sz);
439 + if (sr != pub_sz) return bad_db_corrupt;
440 + hexdump(pub, pub_sz);
441 +
442 + alert(a_debug, "loading password salt");
443 + sr = read(db, salt, salt_sz);
444 + if (sr != salt_sz) return bad_db_corrupt;
445 + hexdump(salt, salt_sz);
446 +
447 + alert(a_debug, "loading encrypted private key");
448 + read(db, priv_enc, priv_sz);
449 + hexdump(priv_enc, priv_sz);
450 +
451 + alert(a_debug, "loading verification hash");
452 + read(db, salt_enc, salt_enc_sz);
453 + hexdump(salt_enc, salt_enc_sz);
454 +
455 + return ok;
380 456 }
381 457
382 458 enum bad
383 -dbdecrypt(int db, uint8_t* pubkey, uint8_t* privkey) {
459 +dbunlock(byte* priv_enc, byte* salt, byte* priv) {
460 + const size_t priv_sz = sizeof(key_priv);
461 + byte key [db_privkey_len];
462 +
384 463 password dbpw; size_t pwlen;
385 464 bad e = pwread(true, dbpw, &pwlen,_str("database key: "));
386 -
387 - uint8_t salt [crypto_pwhash_SALTBYTES],
388 - key [db_privkey_len],
389 - priv_enc [db_privkey_len],
390 - priv [db_privkey_len],
391 - pub [db_pubkey_len];
392 - uint8_t salt_enc [crypto_box_SEALBYTES + sz(salt)],
393 - salt_dec [sz(salt)];
394 -
395 - alert(a_debug, "loading public key");
396 - ssize_t sr = read(db, pub, sz(pub));
397 - if (sr != sz(pub)) return bad_db_corrupt;
398 - hexdump(pub, sz(pub));
399 -
400 - alert(a_debug, "loading password salt");
401 - sr = read(db, salt, sz(salt));
402 - if (sr != sz(salt)) return bad_db_corrupt;
403 - hexdump(salt, sz(salt));
465 + if (e != ok) return e;
404 466
405 467 alert(a_debug, "deriving secret");
406 468 if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
407 469 crypto_pwhash_OPSLIMIT_INTERACTIVE,
408 470 crypto_pwhash_MEMLIMIT_INTERACTIVE,
409 471 crypto_pwhash_ALG_DEFAULT) != 0) {
410 472 return bad_mem;
411 473 }
412 474 hexdump(key, sz(key));
413 475
414 - alert(a_debug, "loading encrypted private key");
415 - read(db, priv_enc, sz(priv_enc));
416 - hexdump(priv_enc, sz(priv_enc));
417 -
418 - alert(a_debug, "decrypting private key");
476 + alert(a_debug, "attempting to decrypt private key");
419 477 for (size_t i = 0; i < sz(key); ++i) {
420 478 priv[i] = priv_enc[i] ^ key[i];
421 479 }
422 - hexdump(priv, sz(priv));
480 + hexdump(priv, sz(key));
423 481
424 - alert(a_debug, "loading verification hash");
425 - read(db, salt_enc, sz(salt_enc));
426 - hexdump(salt_enc, sz(salt_enc));
482 + return ok;
483 +}
484 +
485 +enum bad
486 +dbverify(byte* salt, byte* salt_enc, byte* pub, byte* priv) {
487 + byte salt_dec [crypto_pwhash_SALTBYTES];
427 488
428 489 alert(a_debug, "decrypting verification hash");
429 490 int r = crypto_box_seal_open(salt_dec, salt_enc,
430 - sz(salt_enc), pub, priv);
491 + sz(salt_dec) + crypto_box_SEALBYTES, pub, priv);
431 492 if (r != 0) return bad_pw;
432 493 hexdump(salt_dec, sz(salt_dec));
433 494
434 - if (memcmp(salt,salt_dec,sz(salt)) != 0) return bad_db_corrupt;
495 + if (memcmp(salt,salt_dec,sz(salt_dec)) != 0) return bad_db_corrupt;
496 + else return ok;
497 +}
498 +
499 +enum bad
500 +dbdecrypt(int db, byte* pubkey, byte* privkey) {
501 + byte salt [crypto_pwhash_SALTBYTES],
502 + priv_enc [db_privkey_len],
503 + priv [db_privkey_len],
504 + pub [db_pubkey_len];
505 + byte salt_enc [crypto_box_SEALBYTES + sz(salt)];
506 + bad e;
507 +
508 + if ((e = dbheader_load(db, salt, salt_enc, pub, priv_enc)) != ok)
509 + return e;
510 + if ((e = dbunlock(priv_enc, salt, priv)) != ok)
511 + return e;
512 + if ((e = dbverify(salt, salt_enc, pub, priv)) != ok)
513 + return e;
435 514
436 515 /* TODO refactor to avoid unnecessary memcpy */
437 516 memcpy(privkey, priv, sz(priv));
438 517 memcpy(pubkey, pub, sz(pub));
439 518
440 519 return ok;
441 520 }
442 521
443 -#include<stdio.h>
444 -void bright(int fd, const char* str, size_t len) {
522 +void
523 +bright(int fd, const char* str, size_t len) {
445 524 if (_g_term_type[fd] >= ansi_term) write(fd, _str("\x1b[1m"));
446 525 write(fd, str, len);
447 526 if (_g_term_type[fd] >= ansi_term) write(fd, _str("\x1b[21m"));
448 527 }
528 +
529 +void*
530 +transcribe(void* dest, void* src, size_t sz) {
531 + memcpy(dest, src, sz); return dest + sz;
532 +}
533 +
534 +enum bad
535 +emit_usage(const char* text) {
536 + say("\x1b[1musage:\x1b[m ");
537 + write(2, _g_binary_name, strlen(_g_binary_name));
538 + if (text == NULL) {
539 + write(2, kpw_optstr, sz(kpw_optstr));
540 + write(2, kpw_usage, sz(kpw_usage));
541 + } else write(2, text, strlen(text));
542 + return bad_usage;
543 +}
449 544
450 545 int
451 546 kpw(int argc, const char** argv) {
452 547 if (argc == 0) return bad_insane;
453 548 _g_binary_name = argv[0];
454 549
455 550 enum genmode
456 551 mode = lower;
457 - enum {usage,getpw,addpw,delpw,lspw,genpw,
458 - chpw,keyin,logout,createdb,rekeydb}
552 + enum {usage,getpw,addpw,delpw,lspw,genpw,regen,
553 + chpw,keyin,logout,createdb,rekeydb,help}
459 554 op = getpw;
460 555
461 556 const char* params[3];
462 557 uint8_t param = 0;
463 558
464 559 bool print = false,
465 560 clobber = false,
................................................................................
490 585 }
491 586 } else {
492 587 if (param > sz(params)) return bad_syntax;
493 588 params[param++] = *arg;
494 589 }
495 590 }
496 591
497 - if (op == getpw && param == 0) {
498 - size_t namelen = strlen(argv[0]);
499 - say("\x1b[1musage:\x1b[m ");
500 - write(2, argv[0], namelen);
501 - write(2, kpw_optstr, sz(kpw_optstr));
502 - write(2, kpw_usage, sz(kpw_usage));
503 - return bad_usage;
504 - }
592 + if (op == getpw && param == 0) return emit_usage(NULL);
505 593
506 594 if (sodium_init() < 0)
507 595 return bad_lib_sodium_init;
508 596
509 597 switch(op) {
510 598
511 - case genpw: /* kpw -g[lmu] <acct> [<len>] */
512 - case addpw: { /* kpw -a <acct> [<pw>] */
599 + case genpw:
600 + case addpw: {
601 + if (param == 0) return emit_usage(
602 + op == addpw ? " -a[p] <account> [<pw>]\n" :
603 + /* genpw */" -g[lmup] <account> [<pw len>]\n");
604 +
513 605 if (param > 2 || param < 1) return bad_syntax;
514 606 const char* acct = params[0],
515 607 * prm = (param == 2 ? params[1] : NULL);
516 608
517 609 alert(a_debug, "opening database");
518 610 int db = dbopen(O_RDWR);
519 611 if (db == -1) return bad_db_load;
520 612 alert(a_debug, "reading in public key");
521 - uint8_t key [db_pubkey_len];
613 + byte key [db_pubkey_len];
522 614 ssize_t e = read(db, key, sz(key));
523 615 if(e < sz(key)) return bad_db_corrupt;
524 616
525 617 lseek(db, 0, SEEK_END);
526 618 bool tty_in = isatty(0),
527 619 tty_out = isatty(1);
528 620
................................................................................
563 655 write(1, pw, len);
564 656 if(tty_out) write(1, "\n", 1);
565 657 }
566 658 pwlen = len;
567 659 }
568 660 if (copy_pw) copy(pw, pwlen);
569 661 alert(a_debug, "encoding database entry");
570 - uint8_t acctlen = strlen(acct);
571 - uint8_t plaintext[1 + acctlen +
572 - 1 + pwlen];
662 + db_sz acctlen = strlen(acct);
663 + byte plaintext[1 + acctlen +
664 + 1 + pwlen];
573 665 plaintext[0] = acctlen;
574 666 strncpy(plaintext + 1, acct, acctlen);
575 667 plaintext[1 + acctlen] = pwlen;
576 668 strncpy(plaintext + acctlen + 2, pw, pwlen);
577 669 hexdump(plaintext, sz(plaintext));
578 670
579 671 alert(a_debug, "enciphering database entry");
580 672
581 - uint8_t ciphertext[sz(plaintext) + crypto_box_SEALBYTES];
673 + byte ciphertext[sz(plaintext) + crypto_box_SEALBYTES];
582 674 crypto_box_seal(ciphertext, plaintext, sz(plaintext), key);
583 675 hexdump(ciphertext, sz(ciphertext));
584 676
585 677 alert(a_debug, "writing ciphertext to db");
586 - uint8_t ciphertext_len = sz(ciphertext);
678 + db_sz ciphertext_len = sz(ciphertext);
587 679 write(db, &ciphertext_len, 1);
588 680 write(db, &ciphertext, ciphertext_len);
589 681
590 682 close(db);
591 683 break;
592 684 }
593 685
594 686 case delpw:{ /* kpw -d <acct> */
687 + if (param == 0) return emit_usage(" -d <account>\n");
688 + if (param != 1) return bad_syntax;
689 + const char* target = params[0];
690 + bad e;
691 +
692 + int db = dbopen(O_RDWR);
693 + if (db == -1) return bad_db_load;
694 +
695 + const size_t dbsz = lseek(db, 0, SEEK_END);
696 + lseek(db, 0, SEEK_SET);
697 +
698 + key_pub pub;
699 + key_priv priv, priv_enc;
700 +
701 + byte salt [crypto_pwhash_SALTBYTES],
702 + salt_enc [crypto_box_SEALBYTES + sz(salt)];
703 +
704 + if ((e = dbheader_load(db, salt, salt_enc, pub, priv_enc)) != ok)
705 + return e;
706 + if ((e = dbunlock(priv_enc, salt, priv)) != ok)
707 + return e;
708 + if ((e = dbverify(salt, salt_enc, pub, priv)) != ok)
709 + return e;
710 +
711 + byte newdb [dbsz];
712 + byte* cursor = newdb;
713 +
714 + /* header is unchanged, so we copy it back out as is */
715 + cursor = transcribe(cursor, pub, sz(pub));
716 + cursor = transcribe(cursor, salt, sz(salt));
717 + cursor = transcribe(cursor, priv_enc, sz(priv_enc));
718 + cursor = transcribe(cursor, salt_enc, sz(salt_enc));
719 +
720 + /* now we iterate through each record, decrypting them
721 + * with the keys we've obtained to compare the name
722 + * against the `target` specified by the user. all
723 + * records that do not match are written back to newdb,
724 + * while records that match are skipped. */
725 + db_sz ctlen, ptlen; bool found = false; size_t scanned = 0;
726 + while((e = dbtell(db, &ctlen, &ptlen)) == ok) {
727 + ++ scanned;
728 + /* dbtell gives us the length of the buffers we
729 + * need to allocate, allowing us to keep all the
730 + * work on the stack and avoiding any malloc bs */
731 + byte ctbuf [ctlen],
732 + ptbuf [ptlen];
733 + struct dbrecord rec;
734 +
735 + bad d;
736 + if((d = dbnext(db, &rec, ctlen,
737 + pub, priv, ctbuf, ptbuf)) != ok) return d;
738 +
739 + if(strncmp(target, rec.acct.ptr, rec.acct.len) == 0) {
740 + /* found a matching record; do not copy it */
741 + alert(a_debug, "found record to delete");
742 + found = true;
743 + } else {
744 + /* not our target, copy it into the buffer */
745 + cursor = transcribe(cursor, &ctlen, sizeof(db_sz));
746 + cursor = transcribe(cursor, ctbuf, sz(ctbuf));
747 + }
748 +
749 + } if (e != fail) return e;
750 + if (scanned == 0) return bad_db_empty;
751 + if (!found) return bad_index;
752 + /* newdb should now be an image of the database without
753 + * the offending record. we can now copy it back out to
754 + * disk, truncating the file to start from scratch. */
755 + alert(a_debug, "writing modified db back out to disk");
756 + ftruncate(db,0);
757 + lseek(db, 0, SEEK_SET);
758 + write(db, newdb, cursor-newdb);
759 +
760 + /* we're done here, time to close up shop */
761 + close(db);
762 +
595 763 break;
596 764 }
597 765
598 766 case getpw: /* kpw <acct> */
599 767 case lspw: { /* kpw -t[p] [<prefix>] */
600 - alert(a_debug, "opening database for reading");
601 - int db = dbopen(O_RDONLY);
602 - if (db == -1) return bad_db_load;
603 -
604 768 const char* target;
605 769 if (param == 1) target = params[0];
606 770 else if (param == 0) target = NULL;
607 771 else return bad_syntax;
608 772
609 - uint8_t priv [db_privkey_len],
610 - pub [db_pubkey_len];
773 + alert(a_debug, "opening database for reading");
774 + int db = dbopen(O_RDONLY);
775 + if (db == -1) return bad_db_load;
776 +
777 + key_pub pub;
778 + key_priv priv;
611 779
612 780 /* try to decrypt db */ {
613 781 bad e = dbdecrypt(db,pub,priv);
614 782 if (e != ok) return e;
615 783 /* TODO allow multiple tries */
616 784 }
617 785
618 - /* cursor should now be positioned
619 - * on first record */
786 + /* cursor should be positioned on first
787 + * record if we've made it this far */
620 788 alert(a_debug, "beginning to scan records");
621 - read_rec: {
622 - uint8_t acctlen;
623 - if (read(db, &acctlen, 1) != 1)
624 - goto done_reading;
625 - uint8_t ciphertext[acctlen];
626 - if (read(db, &ciphertext, acctlen) != acctlen)
627 - return bad_db_corrupt;
628 - alert(a_debug, "scanned record");
629 - hexdump(ciphertext, sz(ciphertext));
630 -
631 - uint8_t plaintext[sz(ciphertext) - crypto_box_SEALBYTES];
632 - if(crypto_box_seal_open(plaintext, ciphertext, sz(ciphertext), pub, priv) != 0)
633 - return bad_db_corrupt;
634 -
635 - alert(a_debug, "record deciphered");
636 - hexdump(plaintext, sz(plaintext));
637 -
638 - uint8_t record_name_len = plaintext[0],
639 - record_pw_len = plaintext[record_name_len + 1];
640 -
641 - pstr record_name = {record_name_len, plaintext + 1},
642 - record_pw = {record_pw_len,
643 - plaintext + record_name_len + 2};
789 + struct dbrecord rec;
790 + bool found = (op == lspw);
791 + enum bad result;
792 + db_sz ciphlen, plainlen;
793 + size_t scanned = 0;
794 + while ((result = dbtell(db, &ciphlen, &plainlen)) == ok) {
795 + ++ scanned;
796 + byte ctbuf[ciphlen], ptbuf[plainlen];
797 + if ((result = dbnext(db, &rec, ciphlen,
798 + pub, priv,
799 + ctbuf, ptbuf)) != ok)
800 + break;
644 801
645 802 if(op == lspw) {
646 - bright(1, record_name.ptr, record_name.len);
803 + bright(1, rec.acct.ptr, rec.acct.len);
647 804 if (print || !isatty(1)) {
648 805 write(1, ": ", 2);
649 - write(1, record_pw.ptr, record_pw.len);
806 + write(1, rec.pw.ptr, rec.pw.len);
650 807 }
651 808 write(1, "\n", 1);
652 809 } else if (op == getpw) {
653 - if (strncmp(record_name.ptr,target,record_name.len) == 0) {
810 + if (strncmp(rec.acct.ptr,target,rec.acct.len) == 0) {
654 811 if (print || _g_term_type[1] == plain_term) {
655 - write(1, record_pw.ptr, record_pw.len);
812 + write(1, rec.pw.ptr, rec.pw.len);
656 813 if(_g_term_type[1] > plain_term)
657 814 write(1, "\n", 1);
658 815 }
659 816
660 817 if (_g_term_type[1] > plain_term) {
661 - if (copy_pw) copy(record_pw.ptr, record_pw.len);
818 + if (copy_pw) copy(rec.pw.ptr, rec.pw.len);
662 819 }
663 - goto done_reading;
820 + found = true;
821 + break;
664 822 }
665 823 }
666 -
667 - goto read_rec;
668 824 }
669 - return bad_index;
670 -
671 - done_reading: break;
825 + if (scanned == 0) return bad_db_empty;
826 + if (result != fail) return result;
827 + else if (!found) return bad_index;
828 +
829 + break;
672 830 }
673 831
674 832 case createdb: { /* kpw -C [<db>] */
675 833 alert(a_debug, "creating new database");
676 834 if (clobber)
677 835 alert(a_warn, "will clobber any existing database");
678 836 /* before we open our new file, we need to generate
679 837 * our keypairs. the private key will be encrypted
680 838 * with a blake2 hash of a user-supplied passphrase
681 839 * and stored in the database after the unencrypted
682 840 * public key.
683 841 */
684 - uint8_t pub [db_pubkey_len],
685 - priv[db_privkey_len];
686 - uint8_t priv_enc[sz(priv)];
842 + byte pub [db_pubkey_len],
843 + priv[db_privkey_len];
844 + byte priv_enc[sz(priv)];
687 845
688 846 alert(a_debug, "generating keypair");
689 847 crypto_box_keypair(pub, priv);
690 848
691 849 /* kpw works very differently compared to
692 850 * most password managers. it uses public-key
693 851 * encryption so that new passwords can be saved
................................................................................
707 865 e = pwread(!print, dbpw_conf, NULL, _str("- confirm: "));
708 866 if (e != ok) return e;
709 867
710 868 if(strcmp(dbpw,dbpw_conf) != 0)
711 869 return bad_pw_match;
712 870 }
713 871
714 - uint8_t salt[crypto_pwhash_SALTBYTES],
715 - key[db_privkey_len];
716 - uint8_t salt_enc[crypto_box_SEALBYTES + sz(salt)];
872 + byte salt [crypto_pwhash_SALTBYTES],
873 + key[db_privkey_len];
874 + byte salt_enc[crypto_box_SEALBYTES + sz(salt)];
717 875
718 876 alert(a_debug, "generating salt");
719 877 if (syscall(SYS_getrandom, salt, sz(salt), 0) == -1)
720 878 return bad_entropy;
721 879 hexdump(salt, sz(salt));
722 880
723 881 alert(a_debug, "hashing database keyphrase");