kee

Offline IOU signer with QR as transport
git clone https://holbrook.no/src/kee
Info | Log | Files | Refs | README | LICENSE

commit f26fe4151792acf8e50364a0cfc249d357784513
parent 5a0db17b237a65fb8f376bddc130634df9ec529c
Author: lash <dev@holbrook.no>
Date:   Thu, 13 Jun 2024 14:24:17 +0100

Implement passphrase hasher in cli, success ledger countersign

Diffstat:
Asrc/cmd/cli.h | 14++++++++++++++
Dsrc/cmd/cmd.h | 1-
Msrc/cmd/sign.c | 66++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/debug.c | 2+-
Msrc/gpg.c | 4+++-
Msrc/gtk/debug.c | 2+-
Msrc/ledger.c | 21+++++++++++++++++++++
Msrc/ledger.h | 2+-
Msrc/settings.c | 1+
Msrc/tests/testutil.c | 2+-
Mtestdata_asn1.py | 15++++++++++++---
11 files changed, 103 insertions(+), 27 deletions(-)

diff --git a/src/cmd/cli.h b/src/cmd/cli.h @@ -0,0 +1,14 @@ +#ifndef KEE_CLI_H_ +#define KEE_CLI_H_ + +#define KEE_CLI_BUFMAX 4096 + +struct kee_cli_t { + char *passphrase; +}; + +void cli_init(struct kee_cli_t *cli); +void cli_set_passphrase(struct kee_cli_t *cli, struct gpg_store *keystore, const char *passphrase); +int cli_exit(struct kee_cli_t *cli, int err); + +#endif // KEE_CLI_H_ diff --git a/src/cmd/cmd.h b/src/cmd/cmd.h @@ -1 +0,0 @@ -#define KEE_CLI_BUFMAX 4096 diff --git a/src/cmd/sign.c b/src/cmd/sign.c @@ -2,6 +2,7 @@ #include <fcntl.h> #include <unistd.h> #include <stdlib.h> +#include <string.h> #include "transport.h" #include "settings.h" @@ -10,32 +11,53 @@ #include "err.h" #include "llog.h" -#include "cmd.h" +#include "cli.h" void debug_log(int lvl, const char *s) { - char *e; + //char *e; //e = llog_new(lvl, (char*)s); fprintf(stderr, "%s\n", s); } -int unlock(struct gpg_store *keystore, struct kee_settings *settings, char *passphrase) { +void cli_init(struct kee_cli_t *cli) { + memset(cli, 0, sizeof(struct kee_cli_t)); + err_init(); +} + +void cli_set_passphrase(struct kee_cli_t *cli, struct gpg_store *keystore, const char *passphrase) { + cli->passphrase = malloc(keystore->passphrase_digest_len); + gpg_store_digest(keystore, cli->passphrase, passphrase); +} + +static void cli_free(struct kee_cli_t *cli) { + if (cli->passphrase) { + free(cli->passphrase); + } +} + +int cli_exit(struct kee_cli_t *cli, int err) { + cli_free(cli); + return err; +} + +char* unlock(struct gpg_store *keystore, struct kee_settings *settings, char *passphrase) { int r; if (passphrase == NULL) { passphrase = getenv("KEE_PASSPHRASE"); } if (passphrase == NULL || strlen(passphrase) == 0) { - return ERR_FAIL; + return NULL; } gpg_store_init(keystore, (const char*)settings->key); r = gpg_store_check(keystore, passphrase); if (r) { - return ERR_FAIL; + return NULL; } - return ERR_OK; + return passphrase; } int main(int argc, char **argv) { @@ -43,6 +65,8 @@ int main(int argc, char **argv) { struct gpg_store keystore; struct kee_ledger_t ledger; struct kee_transport_t trans; + struct kee_cli_t cli; + char *passphrase; char dbg[4096]; char b[KEE_CLI_BUFMAX]; char *p; @@ -51,25 +75,26 @@ int main(int argc, char **argv) { long unsigned int c; int l; - err_init(); + cli_init(&cli); settings_new_from_xdg(&settings); settings_init(&settings); - r = unlock(&keystore, &settings, NULL); - if (r) { + passphrase = unlock(&keystore, &settings, NULL); + if (passphrase == NULL) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "keyunlock fail"); - return 1; + return ERR_FAIL; } + cli_set_passphrase(&cli, &keystore, passphrase); if (argc < 2) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "usage: kee-sign <file>"); - return 1; + return cli_exit(&cli, ERR_FAIL); } f = open(*(argv+1), O_RDONLY); if (f < 0) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "argument is not a file that can be opened"); - return 1; + return cli_exit(&cli, ERR_FAIL); } l = KEE_CLI_BUFMAX; @@ -83,7 +108,7 @@ int main(int argc, char **argv) { l -= c; if (l == 0) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "read buffer overrun"); - return 1; + return cli_exit(&cli, ERR_FAIL); } } close(f); @@ -95,31 +120,36 @@ int main(int argc, char **argv) { r = kee_transport_single(&trans, KEE_TRANSPORT_BASE64, KEE_CMD_IMPORT, 0); if (r) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "transport init fail"); - return ERR_FAIL; + return cli_exit(&cli, ERR_FAIL); } r = kee_transport_write(&trans, b, c); if (r) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "parse transport fail"); - return ERR_FAIL; + return cli_exit(&cli, ERR_FAIL); } c = KEE_CLI_BUFMAX; r = kee_transport_read(&trans, b, &c); if (r) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "unwrap transport fail"); - return ERR_FAIL; + return cli_exit(&cli, ERR_FAIL); } r = kee_ledger_parse_open(&ledger, &keystore, b, c); if (r) { debug_logerr(LLOG_CRITICAL, ERR_FAIL, "not valid ledger data"); - return 1; + return cli_exit(&cli, ERR_FAIL); } sprintf(dbg, "parsed ledger: %s", ledger.content.subject); debug_log(DEBUG_INFO, dbg); - return 0; + r = kee_ledger_sign(&ledger, ledger.last_item, &keystore, cli.passphrase); + if (r) { + debug_logerr(LLOG_CRITICAL, r, "ledger sign fail"); + return cli_exit(&cli, ERR_FAIL); + } + return cli_exit(&cli, 0); } diff --git a/src/debug.c b/src/debug.c @@ -1,6 +1,6 @@ #include "debug.h" -void debug_log(enum debugLevel level, const char *s); +void debug_log(int level, const char *s); int debug_logerr(enum lloglvl_e lvl, int err, char *msg) { char *e; diff --git a/src/gpg.c b/src/gpg.c @@ -16,12 +16,14 @@ #define BUFLEN 1024 * 1024 #ifdef RERR -char *_rerr[5] = { +char *_rerr[7] = { + "", "Crypto backend", "Auth fail", "Unlock fail", "Sign reject", "Resource fail", + "No key found", }; #endif diff --git a/src/gtk/debug.c b/src/gtk/debug.c @@ -5,7 +5,7 @@ #define G_LOG_DOMAIN "Kee" -void debug_log(enum debugLevel level, const char *s) { +void debug_log(int level, const char *s) { int loglevel; switch(level) { diff --git a/src/ledger.c b/src/ledger.c @@ -16,6 +16,13 @@ #include "wire.h" +#ifdef RERR +char *_rerr_ledger[2] = { + "", + "Already signed", +}; +#endif +int _ledger_init = 0; char zero_content[64]; /// \todo consolidate with get_message_data @@ -495,10 +502,24 @@ void kee_ledger_free(struct kee_ledger_t *ledger) { void kee_ledger_init(struct kee_ledger_t *ledger) { memset(ledger, 0, sizeof(struct kee_ledger_t)); +#ifdef RERR + if (_ledger_init) { + return; + } + rerr_register(RERR_PFX_LEDGER, "ledger", _rerr_ledger); + _ledger_init = 1; +#endif } void kee_ledger_item_init(struct kee_ledger_item_t *item) { memset(item, 0, sizeof(struct kee_ledger_item_t)); +#ifdef RERR + if (_ledger_init) { + return; + } + rerr_register(RERR_PFX_LEDGER, "ledger", _rerr_ledger); + _ledger_init = 1; +#endif } int kee_ledger_parse(struct kee_ledger_t *ledger, const char *data, size_t data_len) { diff --git a/src/ledger.h b/src/ledger.h @@ -9,7 +9,7 @@ #include "db.h" #include "digest.h" -#define ERRR_PFX_LEDGER 0x200 +#define RERR_PFX_LEDGER 0x200 /// Ledger state has already been signed #define ERR_ALREADY_SIGNED 0x201 diff --git a/src/settings.c b/src/settings.c @@ -99,6 +99,7 @@ int settings_init(struct kee_settings *z) { } strcpy((char*)z->video_device, ss); + return ERR_OK; } diff --git a/src/tests/testutil.c b/src/tests/testutil.c @@ -10,7 +10,7 @@ #include "db.h" #include "debug.h" -void debug_log(enum debugLevel level, const char *s) { +void debug_log(int level, const char *s) { fprintf(stderr, "%s\n", s); } diff --git a/testdata_asn1.py b/testdata_asn1.py @@ -209,6 +209,8 @@ class LedgerSigner: w.write(pubk.hex()) w.close() + return gk.keygrip + def create_key(self, keyname, outdir=None, pin='1234', alias=None): k = ECC.generate(curve='Ed25519') @@ -221,11 +223,11 @@ class LedgerSigner: self.keypair[keyname] = (pk, pubk) self.pubkey_rindex[pubk] = keyname - self.__write_key(keyname, outdir, pin, alias=alias) + keygrip = self.__write_key(keyname, outdir, pin, alias=alias) self.names[keyname] = fake.name() - return pubk + return (pubk, keygrip,) def sign(self, keyname, msg): @@ -637,6 +639,7 @@ if __name__ == '__main__': items_min_in = os.environ.get('ITEM_MIN', '1') items_max_in = os.environ.get('ITEM_MAX', '20') + mainbob_keygrip = None with env.begin(write=True) as tx: for i in range(int(count_ledgers)): bob_name = 'Bob ' + fake.last_name() @@ -645,6 +648,8 @@ if __name__ == '__main__': if i == 0: alias = 'bob' bob = signer.create_key(bob_name, outdir=data_dir, pin='4321', alias=alias) + if i == 0: + mainbob_keygrip = bob[1] # bob_key = os.path.join(crypto_dir, 'bob.key.bin') # bob_key_sym = os.path.join(crypto_dir_r, 'kee.key') # try: @@ -654,7 +659,8 @@ if __name__ == '__main__': # os.symlink(bob_key, bob_key_sym) c = 2 + random.randint(int(items_min_in), int(items_max_in)) - r = generate_ledger(dbi, data_dir, signer, bob_name, ledger_item_count=c, alice=alice, bob=bob) + + r = generate_ledger(dbi, data_dir, signer, bob_name, ledger_item_count=c, alice=alice[0], bob=bob[0]) v = r.pop(0) @@ -687,6 +693,9 @@ if __name__ == '__main__': except FileNotFoundError: pass os.symlink(bob_key, bob_key_sym) + bob_keygrip_sym = os.path.join(crypto_dir_r, mainbob_keygrip) + os.symlink(bob_key, bob_keygrip_sym) + r = generate_ledger(dbi, data_dir, signer, bob_name, ledger_item_count=1, alice=alice, bob=bob) d = os.path.dirname(__file__)