kee

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

commit f0e15c95a339726d2f4dfdca54fb2c04a846ee85
parent 06367d473ea3d86800bacb605d488701570441f0
Author: lash <dev@holbrook.no>
Date:   Fri,  5 Apr 2024 08:57:34 +0100

Implement gpg store and key unlocking

Diffstat:
Dsrc/context.c | 22----------------------
Dsrc/context.h | 20--------------------
Msrc/err.h | 7++++++-
Asrc/gpg.c | 395+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/gpg.h | 99+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Asrc/gtk/context.c | 23+++++++++++++++++++++++
Asrc/gtk/context.h | 24++++++++++++++++++++++++
Msrc/gtk/kee-key.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/gtk/kee-key.h | 6++++++
Msrc/gtk/main.c | 10++++++----
Msrc/gtk/ui.c | 9+++++----
Msrc/gtk/ui.h | 8++++----
Msrc/settings.c | 5+++++
Msrc/settings.h | 3+++
14 files changed, 601 insertions(+), 105 deletions(-)

diff --git a/src/context.c b/src/context.c @@ -1,22 +0,0 @@ -#include <string.h> - -#include "context.h" -#include "settings.h" -#include "camera.h" -#include "err.h" - - -int kee_context_new(struct kee_context *ctx, struct kee_settings *settings) { - memset(ctx, 0, sizeof(struct kee_context)); - ctx->state = 1; - ctx->settings = settings; - - return ERR_OK; -} - -int kee_context_state(struct kee_context *ctx) { - return ctx->state; -} - -void kee_context_free(struct kee_context *ctx) { -} diff --git a/src/context.h b/src/context.h @@ -1,20 +0,0 @@ -#ifndef _KEE_CONTEXT -#define _KEE_CONTEXT - -#include "settings.h" -#include "db.h" -#include "camera.h" - -struct kee_context { - void *front; - struct kee_settings *settings; - struct kee_camera_devices camera_devices; - struct db_ctx db; - int state; -}; - -int kee_context_new(struct kee_context *ctx, struct kee_settings *settings); -int kee_context_state(struct kee_context *ctx); -void kee_context_free(struct kee_context *ctx); - -#endif // _KEE_CONTEXT diff --git a/src/err.h b/src/err.h @@ -21,7 +21,12 @@ enum keeError { ERR_INPUT_DUP, /// Last input changes entry that already exists in storage, but was not allowed ERR_INPUT_PROTECT, - + /// Crypto backend unavailable + ERR_NOCRYPTO, + /// Crypto resource fail + ERR_NOKEY, + /// Crypto authentication fail + ERR_KEYFAIL, }; #endif // _KEE_ERR_H diff --git a/src/gpg.c b/src/gpg.c @@ -0,0 +1,395 @@ +#include <gcrypt.h> +#include <string.h> +#include <stdio.h> +#include <stddef.h> +#include <errno.h> + +#include "err.h" +#include "debug.h" +#include "gpg.h" +#include "hex.h" +#include "digest.h" + +#define BUFLEN 1024 * 1024 + + +//const char *gpgVersion = nullptr; +const char *gpgVersion = NULL; + + +size_t get_padsize(size_t insize, size_t blocksize) { + size_t c; + size_t l; + size_t m; + + c = insize + 1; + l = c / blocksize; + m = c % blocksize; + if (m) { + l++; + } + return l * blocksize; +} + +static void padb(char *data, size_t outsize, size_t insize) { + gcry_randomize(data + insize, outsize - insize, GCRY_STRONG_RANDOM); +} + +//void pad(char *indata_raw, size_t outsize, std::string indata) { +static void pad(char *indata_raw, size_t outsize, const char *indata) { //std::string indata) { + int l; + + //strcpy(indata_raw, indata.c_str()); + strcpy(indata_raw, indata); + //l = indata.length() + 1; + l = strlen(indata) + 1; + padb(indata_raw, outsize, l); +} + +static int create_handle(gcry_cipher_hd_t *h, const char *key, const char *nonce) { + gcry_error_t e; + + e = gcry_cipher_open(h, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_POLY1305, GCRY_CIPHER_SECURE); + if (e) { + return ERR_NOCRYPTO; + } + e = gcry_cipher_setkey(*h, key, CHACHA20_KEY_LENGTH_BYTES); + if (e) { + return ERR_NOCRYPTO; + } + e = gcry_cipher_setiv(*h, nonce, CHACHA20_NONCE_LENGTH_BYTES); + if (e) { + return ERR_NOCRYPTO; + } + return ERR_OK; +} + + +static void free_handle(gcry_cipher_hd_t *h) { + gcry_cipher_close(*h); +} + +int encryptb (char *ciphertext, size_t ciphertext_len, const char *indata, size_t indata_len, const char *key, const char *nonce) { + int r; + gcry_cipher_hd_t h; + gcry_error_t e; + char indata_raw[ciphertext_len]; + + r = create_handle(&h, key, nonce); + if (r) { + return r; + } + memcpy(indata_raw, indata, indata_len); + padb(indata_raw, ciphertext_len, indata_len); + e = gcry_cipher_encrypt(h, (unsigned char*)ciphertext, ciphertext_len, (const unsigned char*)indata_raw, ciphertext_len); + if (e) { + return ERR_NOCRYPTO; + } + + free_handle(&h); + + return ERR_OK; +} + +//int encrypt(char *ciphertext, size_t ciphertext_len, std::string indata, const char *key, const char *nonce) { +int encrypt(char *ciphertext, size_t ciphertext_len, const char *indata, const char *key, const char *nonce) { + int r; + gcry_cipher_hd_t h; + gcry_error_t e; + char indata_raw[ciphertext_len]; + + r = create_handle(&h, key, nonce); + if (r) { + return r; + } + + pad(indata_raw, ciphertext_len, indata); + e = gcry_cipher_encrypt(h, (unsigned char*)ciphertext, ciphertext_len, (const unsigned char*)indata_raw, ciphertext_len); + if (e) { + return ERR_NOCRYPTO; + } + + free_handle(&h); + + return ERR_OK; +} + +int decryptb(char *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce) { + int r; + gcry_cipher_hd_t h; + gcry_error_t e; + + r = create_handle(&h, key, nonce); + if (r) { + return r; + } + + e = gcry_cipher_decrypt(h, outdata, ciphertext_len, ciphertext, ciphertext_len); + if (e) { + return ERR_NOCRYPTO; + } + + free_handle(&h); + + return ERR_OK; + +} + +//int decrypt(std::string *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce) { +int decrypt(char *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce) { + int r; + gcry_cipher_hd_t h; + gcry_error_t e; + char outdata_raw[ciphertext_len] = {}; + + outdata_raw[0] = 0; + r = create_handle(&h, key, nonce); + if (r) { + return r; + } + + e = gcry_cipher_decrypt(h, outdata_raw, ciphertext_len, ciphertext, ciphertext_len); + if (e) { + return ERR_NOCRYPTO; + } + //outdata->assign(outdata_raw); + strcpy(outdata, outdata_raw); + + free_handle(&h); + + return ERR_OK; +} + +static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len) { + gcry_error_t e; + + e = gcry_sexp_new(key, indata, indata_len, 1); + if (e != GPG_ERR_NO_ERROR) { + //debug_log(DEBUG_DEBUG, indata); + return ERR_KEYFAIL; + } + return ERR_OK; +} + +static int key_from_path(gcry_sexp_t *key, const char *p, const char *passphrase) { + int l; + int r; + char v[BUFLEN]; + size_t c; + size_t i; + FILE *f; + char *fullpath; + char nonce[CHACHA20_NONCE_LENGTH_BYTES]; + void *outdata; + + fullpath = (char*)malloc(strlen(p) + 8); + sprintf(fullpath, "%s/%s", p, "key.bin"); + + f = fopen(fullpath, "r"); + if (f == NULL) { + return ERR_NOKEY; + } + free(fullpath); + + c = fread(&l, sizeof(int), 1, f); + c = fread(nonce, CHACHA20_NONCE_LENGTH_BYTES, 1, f); + i = 0; + c = 1; + while (c != 0 && i < BUFLEN) { + c = fread(v+i, 1024, 1, f); + c *= 1024; + i += c; + } + if (i == 0) { + return ERR_NOKEY; + } + fclose(f); + + outdata = malloc(i); + r = decryptb((char*)outdata, v, i, passphrase, nonce); + if (r) { + return ERR_NOKEY; + } + r = key_from_data(key, (char*)outdata, l); + free(outdata); + return r; +} + +/** + * \todo consistent endianness for key length in persistent storage (fwrite) + */ +static int key_create(gcry_sexp_t *key, const char *p, const char *passphrase) { + int r; + FILE *f; + const char *sexp_quick = "(genkey(ecc(curve Ed25519)))"; + //char *pv; + int i; + int l; + int kl; + size_t c; + gcry_sexp_t in; + gcry_error_t e; + char v[BUFLEN]; + char nonce[CHACHA20_NONCE_LENGTH_BYTES]; + + + e = gcry_sexp_new(&in, (const void*)sexp_quick, strlen(sexp_quick), 0); + if (e) { + printf("error sexp: %s\n", gcry_strerror(e)); + return (int)e; + } + e = gcry_pk_genkey(key, in); + if (e) { + printf("error gen: %s\n", gcry_strerror(e)); + return (int)e; + } + kl = gcry_sexp_sprint(*key, GCRYSEXP_FMT_CANON, v, BUFLEN); + + c = get_padsize(kl, ENCRYPT_BLOCKSIZE); + char ciphertext[c]; + + gcry_create_nonce(nonce, CHACHA20_NONCE_LENGTH_BYTES); + r = encryptb(ciphertext, c, v, kl, passphrase, nonce); + if (r) { + return ERR_KEYFAIL; + } + + f = fopen(p, "w"); + if (f == NULL) { + return ERR_KEYFAIL; + } + l = c; + c = fwrite(&kl, sizeof(int), 1, f); + if (c != 1) { + fclose(f); + return ERR_KEYFAIL; + } + c = fwrite(nonce, CHACHA20_NONCE_LENGTH_BYTES, 1, f); + if (c != 1) { + fclose(f); + return ERR_KEYFAIL; + } + i = 0; + c = 1; + while (c != 0 && l > 0) { + c = fwrite(ciphertext+i, 1024, 1, f); + c *= 1024; + i += c; + l -= c; + } + fclose(f); + + return ERR_OK; +} + +static int sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) { + gcry_error_t e; + gcry_sexp_t data; + char in[BUFLEN]; + + sprintf(in, "(data(flags eddsa(hash-algo sha512(value %s))))", v); + gcry_sexp_new(&data, in, strlen(in), 0); + e = gcry_pk_sign(out, data, *key); + if (e) { + sprintf(in, "error sign: %s\n", gcry_strerror(e)); + debug_log(DEBUG_ERROR, in); + return ERR_KEYFAIL; + } + return 0; +} + +//char *GpgStore::get_fingerprint() { +// return m_fingerprint; +//} +char *gpg_store_get_fingerprint(struct gpg_store *gpg) { + return gpg->fingerprint; +} + + +//int GpgStore::digest(char *out, std::string in) { +int gpg_store_digest(struct gpg_store *gpg, char *out, const char *in) { + const char *s; + size_t l; + + //l = in.length(); + l = strlen(in); + s = in; //.c_str(); + return calculate_digest(s, l, out); //, m_passphrase_digest_len); +} + +//GpgStore::GpgStore() { +// m_passphrase_digest_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256); +//} +/// \todo handle path length limit +void gpg_store_init(struct gpg_store *gpg, const char *path) { + gpg->passphrase_digest_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256); + strcpy(gpg->path, path); + +} + +//int GpgStore::check(std::string p, std::string passphrase) { +//int gpg_store_check(struct gpg_store *gpg, const char *p, const char *passphrase) { +int gpg_store_check(struct gpg_store *gpg, const char *passphrase) { + int r; + const char *v; + char d[1024]; + gcry_sexp_t k; + gcry_sexp_t o; + char *p; + unsigned char fingerprint[20] = { 0x00 }; + size_t fingerprint_len = 41; + //char passphrase_hash[m_passphrase_digest_len]; + char passphrase_hash[gpg->passphrase_digest_len]; + + p = gpg->path; + + //digest(passphrase_hash, passphrase); + gpg_store_digest(gpg, passphrase_hash, passphrase); + + if (gpgVersion == NULL) { + v = gcry_check_version(GPG_MIN_VERSION); + //if (v == nullptr) { + if (v == NULL) { + return ERR_NOCRYPTO; + } + } + gpgVersion = v; + sprintf(d, "Using gpg version: %s", gpgVersion); + debug_log(DEBUG_INFO, d); + //r = key_from_path(&k, p.c_str(), passphrase_hash); + //r = key_from_path(&k, p, passphrase_hash); + r = key_from_path(&k, gpg->path, passphrase_hash); + if (r == ERR_KEYFAIL) { + char pp[2048]; + //sprintf(pp, "could not decrypt key in %s/key.bin", p.c_str()); + sprintf(pp, "could not decrypt key in %s/key.bin", p); + debug_log(DEBUG_CRITICAL, pp); + return 1; + } + if (r != ERR_OK) { + char pp[2048]; + //sprintf(pp, "%s/key.bin", p.c_str()); + sprintf(pp, "%s/key.bin", p); + r = key_create(&k, pp, passphrase_hash); + if (r != ERR_OK) { + return r; + } + gcry_pk_get_keygrip(k, fingerprint); + //bin_to_hex(fingerprint, 20, (unsigned char*)m_fingerprint, &fingerprint_len); + bin_to_hex(fingerprint, 20, (unsigned char*)gpg->fingerprint, &fingerprint_len); + char ppp[4096]; + //sprintf(ppp, "created key %s from %s", m_fingerprint, pp); + sprintf(ppp, "created key %s from %s", gpg->fingerprint, pp); + debug_log(DEBUG_INFO, ppp); + } else { + gcry_pk_get_keygrip(k, fingerprint); + //bin_to_hex(fingerprint, 20, (unsigned char*)m_fingerprint, &fingerprint_len); + bin_to_hex(fingerprint, 20, (unsigned char*)gpg->fingerprint, &fingerprint_len); + char pp[4096]; + //sprintf(pp, "found key %s in %s", (unsigned char*)m_fingerprint, p.c_str()); + sprintf(pp, "found key %s in %s", (unsigned char*)gpg->fingerprint, p); + debug_log(DEBUG_INFO, pp); + } + r = sign(&o, &k, "foo"); + return r; +} diff --git a/src/gpg.h b/src/gpg.h @@ -1,6 +1,7 @@ #ifndef _KEE_GPG_H #define _KEE_GPG_H -#include <string> + +//#include <string> #include <stddef.h> #define GPG_MIN_VERSION "1.10.2" @@ -11,6 +12,12 @@ #define ENCRYPT_BLOCKSIZE 4096 #endif +struct gpg_store { + size_t passphrase_digest_len; + char fingerprint[40]; + char path[1024]; +}; + /** * * \brief Encrypt the given string data with the provided encryption key and nonce. @@ -18,7 +25,8 @@ * \sa encryptb * */ -int encrypt(char *ciphertext, size_t ciphertext_len, std::string indata, const char *key, const char *nonce); +//int encrypt(char *ciphertext, size_t ciphertext_len, std::string indata, const char *key, const char *nonce); +int encrypt(char *ciphertext, size_t ciphertext_len, const char *indata, const char *key, const char *nonce); /** * @@ -44,7 +52,8 @@ int encryptb (char *ciphertext, size_t ciphertext_len, const char *indata, size_ * \sa decryptb * */ -int decrypt(std::string *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce); +//int decrypt(std::string *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce); +int decrypt(char *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce); /** * @@ -74,44 +83,50 @@ int decryptb(char *outdata, const char *ciphertext, size_t ciphertext_len, const */ size_t get_padsize(size_t insize, size_t blocksize); -/** - * - * \brief Interface to the encrypted key storage for both identity public key and the key used for encryption of the identity public key. - * - */ -class GpgStore { - public: - /// Sets correct context values for underlying \c gcrypt operations. - GpgStore(); - /** - * - * Attempts to decrypt the identity public key with the given passphrase. - * - * If no public key exists, one will be created and encrypted using the passphrase. - * - * \param p path to key store - * \param passphrase passphrase for public key encryption - * \return 0 if successful, any other value indicates an error - * - */ - int check(std::string p, std::string passphrase); - /** - * - * Returns the fingerprint of the identity public key. - * - * \return 160-bit fingerprint value - */ - char *get_fingerprint(); - - private: - /// calculates sha256 digest for the given string value, using secure memory - int digest(char *out, std::string in); - //const char *m_version; - //char *m_seckey; - /// cached fingerprint value, in string format with zero terminator - char m_fingerprint[41]; - /// cached digest length of sha256 - unsigned int m_passphrase_digest_len; -}; +void gpg_store_init(struct gpg_store *gpg, const char *path); +int gpg_store_check(struct gpg_store *gpg, const char *passphrase); +int gpg_store_digest(struct gpg_store *gpg, char *out, const char *in); +char *gpg_store_get_fingerprint(struct gpg_store *gpg); +// +///** +// * +// * \brief Interface to the encrypted key storage for both identity public key and the key used for encryption of the identity public key. +// * +// */ +//class GpgStore { +// +// public: +// /// Sets correct context values for underlying \c gcrypt operations. +// GpgStore(); +// /** +// * +// * Attempts to decrypt the identity public key with the given passphrase. +// * +// * If no public key exists, one will be created and encrypted using the passphrase. +// * +// * \param p path to key store +// * \param passphrase passphrase for public key encryption +// * \return 0 if successful, any other value indicates an error +// * +// */ +// int check(std::string p, std::string passphrase); +// /** +// * +// * Returns the fingerprint of the identity public key. +// * +// * \return 160-bit fingerprint value +// */ +// char *get_fingerprint(); +// +// private: +// /// calculates sha256 digest for the given string value, using secure memory +// int digest(char *out, std::string in); +// //const char *m_version; +// //char *m_seckey; +// /// cached fingerprint value, in string format with zero terminator +// char m_fingerprint[41]; +// /// cached digest length of sha256 +// unsigned int m_passphrase_digest_len; +//}; #endif diff --git a/src/gtk/context.c b/src/gtk/context.c @@ -0,0 +1,23 @@ +#include <string.h> + +#include "context.h" +#include "settings.h" +#include "camera.h" +#include "err.h" +#include "gpg.h" + + +int kee_context_new(struct kee_context *ctx, struct kee_settings *settings) { + memset(ctx, 0, sizeof(struct kee_context)); + ctx->state = 1; + ctx->settings = settings; + + return ERR_OK; +} + +int kee_context_state(struct kee_context *ctx) { + return ctx->state; +} + +void kee_context_free(struct kee_context *ctx) { +} diff --git a/src/gtk/context.h b/src/gtk/context.h @@ -0,0 +1,24 @@ +#ifndef _KEE_CONTEXT +#define _KEE_CONTEXT + +#include "settings.h" +#include "db.h" +#include "camera.h" +#include "gpg.h" +#include "kee-entry-store.h" + + +struct kee_context { + void *front; + struct kee_settings *settings; + struct kee_camera_devices camera_devices; + struct db_ctx db; + KeeEntryStore *entry_store; + int state; +}; + +int kee_context_new(struct kee_context *ctx, struct kee_settings *settings); +int kee_context_state(struct kee_context *ctx); +void kee_context_free(struct kee_context *ctx); + +#endif // _KEE_CONTEXT diff --git a/src/gtk/kee-key.c b/src/gtk/kee-key.c @@ -2,6 +2,9 @@ #include <gtk/gtk.h> #include "kee-key.h" +#include "gpg.h" +#include "err.h" + typedef struct { } KeeKeyPrivate; @@ -12,13 +15,40 @@ struct _KeeKEyClass { struct _KeeKey { GtkWidget parent; + struct gpg_store gpg; }; G_DEFINE_TYPE(KeeKey, kee_key, GTK_TYPE_BOX); -//static GParamSpec *kee_props[KEE_N_IMPORT_PROPS] = {NULL,}; +static GParamSpec *kee_props[KEE_N_KEY_PROPS] = {NULL,}; static guint kee_sigs[KEE_N_KEY_SIGS] = {0,}; +static void kee_key_set_property(GObject *oo, guint property_id, const GValue *value, GParamSpec *pspec) { + KeeKey *o = KEE_KEY(oo); + gchar *s; + + switch((enum KEE_KEY_PROPS)property_id) { + case KEE_P_KEY_STORE_PATH: + s = g_value_get_string(value); + gpg_store_init(&o->gpg, (char*)s); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(oo, property_id, pspec); + } +} + +static void kee_key_get_property(GObject *oo, guint property_id, GValue *value, GParamSpec *pspec) { + KeeKey *o = KEE_KEY(oo); + + switch((enum KEE_KEY_PROPS)property_id) { + case KEE_P_KEY_STORE: + g_value_set_pointer(value, &o->gpg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(oo, property_id, pspec); + } +} + static void kee_key_class_init(KeeKeyClass *kls) { GObjectClass *o = G_OBJECT_CLASS(kls); @@ -32,32 +62,61 @@ static void kee_key_class_init(KeeKeyClass *kls) { G_TYPE_NONE, 0, NULL); + + o->set_property = kee_key_set_property; + o->get_property = kee_key_get_property; + + kee_props[KEE_P_KEY_STORE_PATH] = g_param_spec_string( + "keystore_path", + "Keystore path", + "GPG keystore interface path initializer", + ".", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE); + + + kee_props[KEE_P_KEY_STORE] = g_param_spec_pointer( + "keystore", + "Keystore", + "GPG keystore interface", + G_PARAM_READABLE); + + g_object_class_install_properties(o, KEE_N_KEY_PROPS, kee_props); } static void kee_key_init(KeeKey *o) { } -static void kee_key_handle_unlock_click(GtkWidget *button, GObject *o) { +static void kee_key_handle_unlock_click(GtkWidget *button, KeeKey *o) { + int r; GtkEntryBuffer *buf; - //const char *passphrase; + struct gpg_store *gpg; + GValue v = G_VALUE_INIT; + char passphrase[1024]; - buf = g_object_get_data(o, "passphrase"); - //passphrase = gtk_entry_buffer_get_text(buf); + g_value_init(&v, G_TYPE_POINTER); + buf = g_object_get_data(G_OBJECT(o), "passphrase"); + strcpy(passphrase, gtk_entry_buffer_get_text(buf)); g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "click"); - //kee_uicontext_unlock(uctx); + g_object_get_property(G_OBJECT(o), "keystore", &v); + gpg = g_value_get_pointer(&v); + if (r) { + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "wrong passphrase"); + return; + } + g_signal_emit(o, kee_sigs[KEE_S_KEY_UNLOCKED], 0); gtk_entry_buffer_delete_text(buf, 0, gtk_entry_buffer_get_length(buf)); } -KeeKey* kee_key_new() { +KeeKey* kee_key_new(const char *key_path) { KeeKey *o; GtkWidget *entry; GtkWidget *button; GtkEntryBuffer *buf; - o = g_object_new(KEE_TYPE_KEY, "orientation", GTK_ORIENTATION_VERTICAL, NULL); + o = g_object_new(KEE_TYPE_KEY, "keystore_path", key_path, "orientation", GTK_ORIENTATION_VERTICAL, NULL); entry = gtk_entry_new(); gtk_box_append(GTK_BOX(o), entry); diff --git a/src/gtk/kee-key.h b/src/gtk/kee-key.h @@ -9,6 +9,12 @@ G_BEGIN_DECLS #define KEE_TYPE_KEY kee_key_get_type() G_DECLARE_FINAL_TYPE(KeeKey, kee_key, KEE, KEY, GtkBox) +enum KEE_KEY_PROPS { + KEE_P_KEY_STORE_PATH = 1, + KEE_P_KEY_STORE, + KEE_N_KEY_PROPS, +}; + enum KEE_KEY_SIGS { KEE_S_KEY_UNLOCKED, KEE_N_KEY_SIGS, diff --git a/src/gtk/main.c b/src/gtk/main.c @@ -19,9 +19,10 @@ static void startup(GtkApplication *app, struct kee_context *ctx) { // kee_uicontext_scaninit(uctx); } -static void activate(GtkApplication *app, KeeEntryStore *store) { //struct kee_context *ctx) { - //ui_build(app, ctx); - ui_build(app, store); +//static void activate(GtkApplication *app, KeeEntryStore *store) { //struct kee_context *ctx) { +static void activate(GtkApplication *app, struct kee_context *ctx) { + //ui_build(app, store); + ui_build(app, ctx); } static void deactivate(GtkApplication *app, gpointer user_data) { @@ -51,9 +52,10 @@ int main(int argc, char **argv) { db_connect(&ctx.db, "./testdata_mdb"); store = kee_entry_store_new(&ctx.db); kee_entry_store_set_resolve(store, "./testdata_resource"); + ctx.entry_store = store; g_signal_connect (gapp, "startup", G_CALLBACK (startup), &ctx); - g_signal_connect (gapp, "activate", G_CALLBACK (activate), store); + g_signal_connect (gapp, "activate", G_CALLBACK (activate), &ctx); g_signal_connect (gapp, "shutdown", G_CALLBACK (deactivate), NULL); //g_signal_connect (uctx, "state", G_CALLBACK(state_log), NULL); diff --git a/src/gtk/ui.c b/src/gtk/ui.c @@ -46,19 +46,20 @@ static void ui_handle_unlock(GtkWidget *widget, KeeMenu *menu) { //} -//void ui_build(GtkApplication *app, struct kee_context *ctx) { -void ui_build(GtkApplication *app, KeeEntryStore *store) { +void ui_build(GtkApplication *app, struct kee_context *ctx) { GtkWidget *widget; KeeMenu *win; KeeImport *import; + struct kee_settings *settings; win = kee_menu_new(app); - widget = GTK_WIDGET(kee_key_new()); + settings = ctx->settings; + widget = GTK_WIDGET(kee_key_new(settings_get(settings, SETTINGS_KEY))); kee_menu_add(win, "unlock", widget); g_signal_connect (widget, "unlock", G_CALLBACK(ui_handle_unlock), win); - widget = kee_entry_list_new(G_LIST_MODEL(store), win); + widget = kee_entry_list_new(G_LIST_MODEL(ctx->entry_store), win); kee_menu_add(win, "view", widget); kee_menu_next(win, "view"); diff --git a/src/gtk/ui.h b/src/gtk/ui.h @@ -2,12 +2,12 @@ #define _UI_H #include <gtk/gtk.h> -//#include "context.h" -#include "kee-entry-store.h" +#include "context.h" +//#include "kee-entry-store.h" //void ui_build(GtkApplication *app, KeeUicontext *uctx); -//void ui_build(GtkApplication *app, struct kee_context *ctx); -void ui_build(GtkApplication *app, KeeEntryStore *store); +void ui_build(GtkApplication *app, struct kee_context *ctx); +//void ui_build(GtkApplication *app, KeeEntryStore *store); #endif // _UI_H diff --git a/src/settings.c b/src/settings.c @@ -25,6 +25,8 @@ int settings_new_from_xdg(struct kee_settings *z) { memset(z, 0, sizeof(struct kee_settings)); + z->key = (unsigned char*)"."; + z->data = malloc(KEE_SETTINGS_CAP); p = z->data; p += KEE_SETTINGS_ITEM_CAP; @@ -78,6 +80,9 @@ unsigned char *settings_get(struct kee_settings *z, enum SettingsType typ) { case SETTINGS_RUN: return z->run; break; + case SETTINGS_KEY: + return z->key; + break; case SETTINGS_LOCKTIME: return z->locktime; break; diff --git a/src/settings.h b/src/settings.h @@ -9,6 +9,7 @@ struct kee_settings { unsigned char *data; unsigned char *run; + unsigned char *key; unsigned char *locktime; unsigned char *video_device; }; @@ -22,6 +23,8 @@ enum SettingsType { SETTINGS_DATA = 0x01, /// Runtime directory SETTINGS_RUN = 0x02, + /// GPG keys directory + SETTINGS_KEY = 0x04, /// Milliseconds a key will stay unlocked since last application use. SETTINGS_LOCKTIME = 0x10, /// Default video device to use