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");
|