util  Check-in [eb56f79816]

Overview
Comment:add ability to disable key-save mechanism
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: eb56f798162057de83bd7895f0b25138820f1d70fb050a57018d9ac29f5b207d
User & Date: lexi on 2019-08-18 05:12:44
Other Links: manifest | tags
Context
2019-09-06
01:02
fix bug caused by unintuitive behavior of strncmp check-in: a49d93061d user: lexi tags: trunk
2019-08-18
05:12
add ability to disable key-save mechanism check-in: eb56f79816 user: lexi tags: trunk
2019-08-16
03:00
add android support check-in: 8a57f6203c user: lexi tags: trunk
Changes

Modified kpw.d/kpw.c from [de39328fae] to [6b73e83d39].

8
9
10
11
12
13
14


15
16
17
18
19
20
21
...
461
462
463
464
465
466
467

468
469

470
471
472
473
474
475
476
...
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
...
610
611
612
613
614
615
616

617
618
619
620
621
622
623
...
646
647
648
649
650
651
652

653
654
655
656
657
658
659
 *      this by attempting to execute a sequence
 *      of binaries, and then writing the password
 *      to STDIN of the binary that succeeds.
 *  ? generates passwords
 *  → kpw is unlikely to be portable to non-POSIX
 *    systems, but should run fine on Linux as well
 *    as BSDs with getrandom() support.


 *  ! for getrandom() to work with the version of
 *    libc on my android phone, the getrandom() call
 *    had to be converted to use the syscall()
 *    interface. this is unlikely to cause problems,
 *    but should be kept in mind.
 *
 *  TODO prevent pw reads from going off the edge of
................................................................................

enum bad
dbunlock(byte* priv_enc, byte* salt, byte* priv) {
	const size_t priv_sz = sizeof(key_priv);
	byte key [db_privkey_len];

	/* is the private key loaded into memory? */

	int shm = shmget(*((key_t*) salt), sizeof(key_priv), 0);
	if (shm == -1) {

		/* no key in memory - read password from stdin instead */
		password dbpw; size_t pwlen;
		bad e = pwread(true, dbpw, &pwlen,_str("database key: "));
		if (e != ok) return e;

		alert(a_debug, "deriving secret");
		if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
................................................................................
		hexdump(key, sz(key));

		alert(a_debug, "attempting to decrypt private key");
		for (size_t i = 0; i < sz(key); ++i) {
			priv[i] = priv_enc[i] ^ key[i];
		}
		hexdump(priv, sz(key));

	} else {
		/* found a key in memory; loading it into *priv */
		alert(a_debug, "using saved key");
		key_priv* saved = shmat(shm, 0, 0);
		if (saved == (void*)-1)
			return bad_shm;
		hexdump((byte*)saved, sizeof(key_priv));
		memcpy(priv, saved, sizeof(key_priv));
		shmdt(saved);
	}


	return ok;
}

enum bad
dbverify(byte* salt, byte* salt_enc, byte* pub, byte* priv) {
	byte salt_dec [crypto_pwhash_SALTBYTES];
................................................................................

	if (op == getpw && param == 0) return emit_usage(NULL);

	if (sodium_init() < 0) 
		return bad_lib_sodium_init;

	switch(op) {

		case logout:
		case keyin: {
			if (param != 0) return bad_syntax;

			int db = dbopen(O_RDONLY);
			key_pub  pub;
			key_priv priv, priv_enc;
................................................................................
				int shm = shmget(ipck, sizeof(key_priv), 0);
				if (shm == -1) return bad_no_shm;
				shmctl(shm, IPC_RMID, NULL);
			}

			return ok;
		}

 
		case genpw:   
		case addpw: {
			if (param == 0) return emit_usage(
					op == addpw ? " -a[p] <account> [<pw>]\n"       :
					   /* genpw */" -g[lmusp] <account> [<pw len>]\n");








>
>







 







>


>







 







>










>







 







>







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
 *      this by attempting to execute a sequence
 *      of binaries, and then writing the password
 *      to STDIN of the binary that succeeds.
 *  ? generates passwords
 *  → kpw is unlikely to be portable to non-POSIX
 *    systems, but should run fine on Linux as well
 *    as BSDs with getrandom() support.
 *  → kpw has the following dependencies:
 *    - libsodium
 *  ! for getrandom() to work with the version of
 *    libc on my android phone, the getrandom() call
 *    had to be converted to use the syscall()
 *    interface. this is unlikely to cause problems,
 *    but should be kept in mind.
 *
 *  TODO prevent pw reads from going off the edge of
................................................................................

enum bad
dbunlock(byte* priv_enc, byte* salt, byte* priv) {
	const size_t priv_sz = sizeof(key_priv);
	byte key [db_privkey_len];

	/* is the private key loaded into memory? */
#ifdef _SAVEKEY
	int shm = shmget(*((key_t*) salt), sizeof(key_priv), 0);
	if (shm == -1) {
#endif
		/* no key in memory - read password from stdin instead */
		password dbpw; size_t pwlen;
		bad e = pwread(true, dbpw, &pwlen,_str("database key: "));
		if (e != ok) return e;

		alert(a_debug, "deriving secret");
		if(crypto_pwhash(key, sz(key), dbpw, pwlen, salt,
................................................................................
		hexdump(key, sz(key));

		alert(a_debug, "attempting to decrypt private key");
		for (size_t i = 0; i < sz(key); ++i) {
			priv[i] = priv_enc[i] ^ key[i];
		}
		hexdump(priv, sz(key));
#ifdef _SAVEKEY
	} else {
		/* found a key in memory; loading it into *priv */
		alert(a_debug, "using saved key");
		key_priv* saved = shmat(shm, 0, 0);
		if (saved == (void*)-1)
			return bad_shm;
		hexdump((byte*)saved, sizeof(key_priv));
		memcpy(priv, saved, sizeof(key_priv));
		shmdt(saved);
	}
#endif

	return ok;
}

enum bad
dbverify(byte* salt, byte* salt_enc, byte* pub, byte* priv) {
	byte salt_dec [crypto_pwhash_SALTBYTES];
................................................................................

	if (op == getpw && param == 0) return emit_usage(NULL);

	if (sodium_init() < 0) 
		return bad_lib_sodium_init;

	switch(op) {
#		ifdef _SAVEKEY
		case logout:
		case keyin: {
			if (param != 0) return bad_syntax;

			int db = dbopen(O_RDONLY);
			key_pub  pub;
			key_priv priv, priv_enc;
................................................................................
				int shm = shmget(ipck, sizeof(key_priv), 0);
				if (shm == -1) return bad_no_shm;
				shmctl(shm, IPC_RMID, NULL);
			}

			return ok;
		}
#		endif
 
		case genpw:   
		case addpw: {
			if (param == 0) return emit_usage(
					op == addpw ? " -a[p] <account> [<pw>]\n"       :
					   /* genpw */" -g[lmusp] <account> [<pw len>]\n");

Modified kpw.d/makefile from [e4660982d8] to [0ee772709b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
include ../makerules

cdeps = compose.c iaia.c tbl.c
cpaths = $(cdeps:%=$(root)/clib/%)

$(root)/kpw: kpw.c opt.inc err.inc $(cpaths)
	$(cc) -I$(root) $< -lsodium $(l-shmem) -o $@ $(flags) $(cc-post)

tab = cat $< | awk -v emit=$1 -F'\t+' -f $<.awk >> $@

opt.inc: optab optab.awk
	:>$@
	$(call tab,cond)
	$(call tab,enum)






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
include ../makerules

cdeps = compose.c iaia.c tbl.c
cpaths = $(cdeps:%=$(root)/clib/%)

$(root)/kpw: kpw.c opt.inc err.inc $(cpaths)
	$(cc) -I$(root) $< -lsodium -o $@ $(flags) $(cc-post)

tab = cat $< | awk -v emit=$1 -F'\t+' -f $<.awk >> $@

opt.inc: optab optab.awk
	:>$@
	$(call tab,cond)
	$(call tab,enum)

Modified kpw.d/optab from [a42323bd02] to [0522a14fe6].

8
9
10
11
12
13
14
15
16
17
18
19
20
21
d	del			op = delpw				delete password from the database
c	chg			op = chpw				change password in the database
r	regen		op = regen				generate new password for existing account
l	lower		mode = lower			generate lowercase password
m	mix			mode = mix				generate mix-case password
u	upper		mode = upper			generate uppercase password
s	stupid-mode	mode = stupid			circumvent dumb pw restrictions
k	install-key	op = keyin				install database key in session memory
o	logout		op = logout				delete db key from session memory
n	no-copy		copy_pw = false			print password instead of copying to clipboard	_CLIPBOARD
p	print-pw	print = true			display passwords onscreen
q	quiet		_g_alert_quiet = true	hide non-fatal reports
v	verbose		_g_debug_msgs = true	display debug reports
h	help		op = help				display help text







|
|





8
9
10
11
12
13
14
15
16
17
18
19
20
21
d	del			op = delpw				delete password from the database
c	chg			op = chpw				change password in the database
r	regen		op = regen				generate new password for existing account
l	lower		mode = lower			generate lowercase password
m	mix			mode = mix				generate mix-case password
u	upper		mode = upper			generate uppercase password
s	stupid-mode	mode = stupid			circumvent dumb pw restrictions
k	install-key	op = keyin				install database key in session memory			_SAVEKEY
o	logout		op = logout				delete db key from session memory				_SAVEKEY
n	no-copy		copy_pw = false			print password instead of copying to clipboard	_CLIPBOARD
p	print-pw	print = true			display passwords onscreen
q	quiet		_g_alert_quiet = true	hide non-fatal reports
v	verbose		_g_debug_msgs = true	display debug reports
h	help		op = help				display help text