Differences From
Artifact [f4297483ea]:
339 339 } else {
340 340 printf("path is %s", dbpath);
341 341 db = open(dbpath, flags, 0600);
342 342 }
343 343
344 344 return db;
345 345 }
346 +
347 +void bytedump(uint8_t* bytes, size_t sz) {
348 + for (size_t i = 0; i < sz; ++i) {
349 + char tpl[] ="\x1b[35m \x1b[m";
350 + char* c = tpl + 5;
351 + *c = bytes[i];
352 + if (*c < ' ' || *c > '~') *c='.', write(2, tpl, sz(tpl));
353 + else write(2, c, 1);
354 + }
355 +}
356 +void hexdump(uint8_t* bytes, size_t sz) {
357 + if(!_g_debug_msgs) return;
358 + alert(a_debug, "printing hex dump");
359 + uint8_t* st = bytes;
360 + for (size_t i = 0; i < sz; ++i) {
361 + char hex[5] = " ";
362 + kitoa(16, bytes[i], hex, hex + 2, NULL, true);
363 + write(2, hex, 4);
364 + if(!((i+1)%8)) {
365 + write(2, _str("│ "));
366 + bytedump(st, 8);
367 + write(2, "\n", 1);
368 + st += 8;
369 + } else if (i == sz - 1) {
370 + write(2, _str("│ "));
371 + bytedump(st, (bytes + sz) - st);
372 + write(2, "\n", 1);
373 + }
374 + }
375 +}
346 376
347 377 int
348 378 kpw(int argc, const char** argv) {
349 379 if (argc == 0) return bad_insane;
350 380 _g_binary_name = argv[0];
351 381
352 382 enum genmode
................................................................................
454 484 alert(a_debug, "converting length parameter to integer");
455 485 bad e = katoi(10, prm, &len);
456 486 if (e != ok) return bad_num;
457 487 } else alert(a_debug, "using default password length"),
458 488 len = default_pw_len;
459 489
460 490 alert(a_debug, "generating new password");
461 - mkpw(mode, pw, len);
491 + if (mkpw(mode, pw, len) == bad_entropy) return bad_entropy;
462 492 if (print || !tty_out) {
463 493 write(1, pw, len);
464 494 if(tty_out) write(1, "\n", 1);
465 495 }
466 496 pwlen = len;
467 497 }
468 498 if (copy_pw) copy(pw, pwlen);
469 - alert(a_debug, "enciphering password");
499 + alert(a_debug, "encoding database entry");
500 + uint8_t acctlen = strlen(acct);
501 + uint8_t plaintext[1 + acctlen +
502 + 1 + pwlen];
503 + plaintext[0] = acctlen;
504 + strncpy(plaintext + 1, acct, acctlen);
505 + plaintext[1 + acctlen] = pwlen;
506 + strncpy(plaintext + acctlen + 2, pw, pwlen);
507 + hexdump(plaintext, sz(plaintext));
470 508
509 + alert(a_debug, "enciphering database entry");
510 +
511 + uint8_t ciphertext[sz(plaintext) + crypto_box_SEALBYTES];
512 + crypto_box_seal(ciphertext, plaintext, sz(plaintext), key);
513 + hexdump(ciphertext, sz(ciphertext));
514 +
515 + alert(a_debug, "writing ciphertext to db");
516 + uint8_t ciphertext_len = sz(ciphertext);
517 + write(db, &ciphertext_len, 1);
518 + write(db, &ciphertext, ciphertext_len);
519 +
520 + close(db);
471 521 break;
472 522 }
473 523
474 524 case delpw:{ /* kpw -d <acct> */
475 525 break;
476 526 }
477 527
478 528 case lspw: { /* kpw -t[p] [<prefix>] */
529 + alert(a_debug, "opening database for reading");
530 + int db = dbopen(O_RDONLY);
531 + if (db == -1) return bad_db_load;
532 + password dbpw; size_t pwlen;
533 + bad e = pwread(!print, dbpw, &pwlen,_str("database key: "));
534 +
535 + uint8_t salt [crypto_pwhash_SALTBYTES],
536 + key [db_privkey_len],
537 + priv_enc [db_privkey_len],
538 + priv [db_privkey_len],
539 + pub [db_pubkey_len];
540 + uint8_t salt_enc [crypto_box_SEALBYTES + sz(salt)],
541 + salt_dec [sz(salt)];
542 + bzero(salt_dec, sz(salt_dec));
543 +
544 + alert(a_debug, "loading public key");
545 + ssize_t sr = read(db, pub, sz(pub));
546 + if (sr != sz(pub)) return bad_db_corrupt;
547 + hexdump(pub, sz(pub));
548 +
549 + alert(a_debug, "loading password salt");
550 + sr = read(db, salt, sz(salt));
551 + if (sr != sz(salt)) return bad_db_corrupt;
552 + hexdump(salt, sz(salt));
553 +
554 + alert(a_debug, "deriving secret");
555 + if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
556 + crypto_pwhash_OPSLIMIT_INTERACTIVE,
557 + crypto_pwhash_MEMLIMIT_INTERACTIVE,
558 + crypto_pwhash_ALG_DEFAULT) != 0) {
559 + return bad_mem;
560 + }
561 + hexdump(key, sz(key));
562 +
563 + alert(a_debug, "loading encrypted private key");
564 + read(db, priv_enc, sz(priv_enc));
565 + hexdump(priv_enc, sz(priv_enc));
566 +
567 + alert(a_debug, "decrypting private key");
568 + for (size_t i = 0; i < sz(key); ++i) {
569 + priv[i] = priv_enc[i] ^ key[i];
570 + }
571 + hexdump(priv, sz(priv));
572 +
573 + alert(a_debug, "loading verification hash");
574 + read(db, salt_enc, sz(salt_enc));
575 + hexdump(salt_enc, sz(salt_enc));
576 +
577 + alert(a_debug, "decrypting verification hash");
578 + hexdump(pub, sz(pub));
579 + hexdump(priv, sz(priv));
580 + printf("sz salt_enc = %zu\n / crypto_box bytes = %zu", sz(salt_enc), crypto_box_SEALBYTES);
581 + int r = crypto_box_seal_open(salt_dec, salt_enc,
582 + sz(salt_enc), pub, priv);
583 + printf("result code: %d\n",r);
584 + hexdump(salt_dec, sz(salt_dec));
479 585 break;
480 586 }
481 587
482 588 case createdb: { /* kpw -C [<db>] */
483 589 alert(a_debug, "creating new database");
484 590 if (clobber)
485 591 alert(a_warn, "will clobber any existing database");
................................................................................
504 610 * prompt the user for a secret passphrase with
505 611 * which to encrypt the private key with.
506 612 */
507 613
508 614 alert(a_notice, "database keypair generated, encrypting");
509 615 password dbpw;
510 616 size_t pwlen;
511 - bad e = pwread(!print, dbpw, &pwlen, _str("- database passphrase: "));
617 + bad e = pwread(!print, dbpw, &pwlen, _str("- new database key: "));
512 618 if (e != ok) return e;
513 619 if (!print && isatty(0)) {
514 620 password dbpw_conf;
515 621 e = pwread(!print, dbpw_conf, NULL, _str("- confirm: "));
516 622 if (e != ok) return e;
517 623
518 624 if(strcmp(dbpw,dbpw_conf) != 0)
................................................................................
519 625 return bad_pw_match;
520 626 }
521 627
522 628 uint8_t salt[crypto_pwhash_SALTBYTES],
523 629 key[db_privkey_len];
524 630 uint8_t salt_enc[crypto_box_SEALBYTES + sz(salt)];
525 631
632 + alert(a_debug, "generating salt");
526 633 if (syscall(SYS_getrandom, salt, sz(salt), 0) == -1)
527 634 return bad_entropy;
635 + hexdump(salt, sz(salt));
528 636
637 + alert(a_debug, "hashing database keyphrase");
529 638 if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
530 639 crypto_pwhash_OPSLIMIT_INTERACTIVE,
531 640 crypto_pwhash_MEMLIMIT_INTERACTIVE,
532 641 crypto_pwhash_ALG_DEFAULT) != 0) {
533 642 return bad_mem;
534 643 }
535 644
645 + alert(a_debug, "encrypting private key");
646 + hexdump(priv, sz(priv));
536 647 for (size_t i = 0; i < sz(key); ++i) {
537 648 priv_enc[i] = priv[i] ^ key[i];
538 649 }
650 + alert(a_debug, "private key encrypted");
651 + hexdump(priv_enc, sz(priv_enc));
539 652
653 + alert(a_debug, "encrypting salt");
540 654 crypto_box_seal(salt_enc, salt, sz(salt), priv);
655 + hexdump(salt_enc, sz(salt_enc));
541 656
542 657 /* we have everything we need. now we create the
543 658 * file, failing if it already exists so as not
544 659 * to clobber anyone's passwords.
545 660 */
661 + alert(a_debug, "creating new database on disk");
546 662 int db;
547 663 const int flags = O_CREAT | O_WRONLY |
548 664 (clobber ? O_TRUNC : O_EXCL);
549 665 if(param == 0)
550 666 db = dbopen(flags);
551 667 else if (param == 1)
552 668 db = open(params[0], flags, 0600);
................................................................................
554 670
555 671 if (db == -1) return bad_db_create;
556 672
557 673 /* the file is safely created; all that's left to
558 674 * do is write out the header and then we can call
559 675 * it a day.
560 676 */
677 + alert(a_debug, "writing public key");
678 + hexdump(pub, sz(pub));
679 +
561 680 write(db, pub, sz(pub));
562 681 write(db, salt, sz(salt));
563 682 write(db, priv_enc, sz(priv_enc));
564 683 write(db, salt_enc, sz(salt_enc));
565 684 close(db);
566 685
567 686 alert(a_debug, "database created");
568 687 break;
569 688 }
570 689 }
571 690
572 -
573 -
574 - /* char buf[len+1]; */
575 - /* *buf = 0; */
576 - /* mkpw(mode,buf,len); */
577 - /* write(1, buf, len + 1); */
578 -
579 691 # ifdef _CLIPBOARD
580 692 if (copy_pw) {
581 693 /* copy(buf,len); */
582 694 }
583 695 # endif
584 696
585 697 return ok;