commit 8a228e775f432e750b8a54f49881c97608ba644e
parent 802d1a2be68a8f417cbedb0e86f424309495adad
Author: lash <dev@holbrook.no>
Date: Thu, 25 Apr 2024 21:56:58 +0100
WIP very close to store refactor and complete sign and serialize verify tests
Diffstat:
11 files changed, 617 insertions(+), 233 deletions(-)
diff --git a/src/err.h b/src/err.h
@@ -27,6 +27,8 @@ enum keeError {
ERR_NOKEY,
/// Crypto authentication fail
ERR_KEYFAIL,
+ ///
+ ERR_ALREADY_SIGNED,
};
#endif // _KEE_ERR_H
diff --git a/src/gpg.c b/src/gpg.c
@@ -3,6 +3,8 @@
#include <stdio.h>
#include <stddef.h>
#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
#include "err.h"
#include "debug.h"
@@ -157,6 +159,45 @@ int decrypt(char *outdata, const char *ciphertext, size_t ciphertext_len, const
return ERR_OK;
}
+static int key_apply_public(struct gpg_store *gpg, gcry_sexp_t key) {
+ char *p;
+ size_t c;
+ gcry_sexp_t pubkey;
+
+ pubkey = gcry_sexp_find_token(key, "public-key", 10);
+ if (pubkey == NULL) {
+ return 1;
+ }
+ pubkey = gcry_sexp_find_token(pubkey, "q", 1);
+ if (pubkey == NULL) {
+ return 1;
+ }
+ c = PUBKEY_LENGTH;
+ p = (char*)gcry_sexp_nth_data(pubkey, 1, &c);
+ if (p == NULL) {
+ return 1;
+ }
+ memcpy(gpg->public_key, p, PUBKEY_LENGTH);
+ return 0;
+}
+
+static char *key_filename(struct gpg_store *gpg, char *path) {
+ int r;
+ char *p;
+ size_t c;
+
+ strcpy((char*)path, gpg->path);
+ p = (char*)path + strlen((char*)path);
+
+ c = 41;
+ r = bin_to_hex((unsigned char*)gpg->fingerprint, 20, (unsigned char*)p, &c);
+ if (r) {
+ return NULL;
+ }
+
+ return path;
+}
+
static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len) {
gcry_error_t e;
@@ -168,24 +209,20 @@ static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len
return ERR_OK;
}
-static int key_from_path(gcry_sexp_t *key, const char *p, const char *passphrase) {
+static int key_from_file(gcry_sexp_t *key, const char *path, const char *passphrase) {
+ char *p;
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");
+ f = fopen(path, "r");
if (f == NULL) {
return ERR_NOKEY;
}
- free(fullpath);
/// \todo length must be in the ciphertext
//c = fread(&l, sizeof(int), 1, f);
@@ -208,45 +245,99 @@ static int key_from_path(gcry_sexp_t *key, const char *p, const char *passphrase
return ERR_NOKEY;
}
//r = key_from_data(key, (char*)outdata, l);
- r = key_from_data(key, (char*)(outdata+sizeof(int)), (size_t)(*((int*)outdata)));
+ c = (size_t)(*((int*)outdata));
+ p = (char*)(outdata+sizeof(int));
+ r = key_from_data(key, p, c);
free(outdata);
return r;
}
+static int key_create(struct gpg_store *gpg, gcry_sexp_t *key) {
+ int r;
+ char *p;
+ const char *sexp_quick = "(genkey(ecc(flags eddsa)(curve Ed25519)))";
+ //char *pv;
+ gcry_sexp_t in;
+ gcry_error_t e;
+
+ 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;
+ }
+ p = (char*)gcry_pk_get_keygrip(*key, (unsigned char*)gpg->fingerprint);
+ if (p == NULL) {
+ return ERR_KEYFAIL;
+ }
+
+ r = key_apply_public(gpg, *key);
+ if (r) {
+ return ERR_KEYFAIL;
+ }
+
+ return 0;
+}
+
/**
* \todo consistent endianness for key length in persistent storage (fwrite)
- * \todo implement MAC
+ et* \todo implement MAC
* \todo test new data length location (part of ciphertext)
+ * \todo doc must have enough in path for path + fingerprint hex
+ *
*/
-static int key_create_file(gcry_sexp_t *key, const char *p, const char *passphrase) {
+static int key_create_file(struct gpg_store *gpg, gcry_sexp_t *key, const char *passphrase) {
+ char *p;
int r;
int kl;
char v[BUFLEN];
int i;
int l;
size_t c;
+ size_t m;
FILE *f;
char nonce[CHACHA20_NONCE_LENGTH_BYTES];
+ char path[1024];
- r = gpg_key_create(key);
+ r = key_create(gpg, key);
if (r) {
return ERR_KEYFAIL;
}
- kl = gcry_sexp_sprint(*key, GCRYSEXP_FMT_CANON, v+sizeof(int), BUFLEN);
- memcpy(v, &kl, sizeof(int));
+ kl = gcry_sexp_sprint(*key, GCRYSEXP_FMT_CANON, NULL, 0);
+ m = (size_t)kl;
+ p = (char*)v + sizeof(int);
+ c = 0;
+ while (m > 0) {
+ kl = gcry_sexp_sprint(*key, GCRYSEXP_FMT_CANON, p, BUFLEN-m);
+ m -= (size_t)(kl + 1);
+ p += kl;
+ c += kl;
+ }
+ memcpy(v, &c, sizeof(int));
- c = get_padsize(kl, ENCRYPT_BLOCKSIZE);
+ m = c;
+ c = get_padsize(m, ENCRYPT_BLOCKSIZE);
/// \todo malloc
char ciphertext[c];
gcry_create_nonce(nonce, CHACHA20_NONCE_LENGTH_BYTES);
- r = encryptb(ciphertext, c, v, kl, passphrase, nonce);
+ r = encryptb(ciphertext, c, v, m+sizeof(int), passphrase, nonce);
if (r) {
return ERR_KEYFAIL;
}
- f = fopen(p, "w");
+
+ p = key_filename(gpg, path);
+ if (p == NULL) {
+ return ERR_KEYFAIL;
+ }
+
+ f = fopen((char*)path, "w");
if (f == NULL) {
return ERR_KEYFAIL;
}
@@ -275,26 +366,87 @@ static int key_create_file(gcry_sexp_t *key, const char *p, const char *passphra
}
-int gpg_key_create(gcry_sexp_t *key) {
- const char *sexp_quick = "(genkey(ecc(flags eddsa)(curve Ed25519)))";
- //char *pv;
- gcry_sexp_t in;
- gcry_error_t e;
+int gpg_key_create(struct gpg_store *gpg, const char *passphrase) {
+ size_t c;
+ char *p;
+ int r;
+ gcry_sexp_t key;
+ char key_path[1024];
+ char link_path[1024];
- 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;
+ r = key_create_file(gpg, &key, passphrase);
+ if (r) {
+ return ERR_KEYFAIL;
}
- e = gcry_pk_genkey(key, in);
- if (e) {
- printf("error gen: %s\n", gcry_strerror(e));
- return (int)e;
+
+ p = key_filename(gpg, key_path);
+ if (p == NULL) {
+ return ERR_KEYFAIL;
}
- return 0;
+
+ strcpy(link_path, gpg->path);
+ c = strlen(link_path);
+ strcpy(link_path + c, "kee.key");
+
+ r = unlink(link_path);
+ if (r == -1 && errno != ENOENT) {
+ return ERR_KEYFAIL;
+ }
+
+ r = symlink(key_path, link_path);
+ if (r) {
+ return ERR_KEYFAIL;
+ }
+ return ERR_OK;
+}
+
+int gpg_key_load(struct gpg_store *gpg, const char *passphrase, enum gpg_find_mode_e mode, void *criteria) {
+ int r;
+ size_t c;
+ char *p;
+ char path[1024];
+
+ switch(mode) {
+ case KEE_GPG_FIND_MAIN:
+ strcpy(path, gpg->path);
+ p = path + strlen(path);
+ strcpy(p, "kee.key");
+ r = key_from_file(gpg->k, path, passphrase);
+ if (r) {
+ return ERR_FAIL;
+ }
+ break;
+ case KEE_GPG_FIND_FINGERPRINT:
+ strcpy(path, gpg->path);
+ p = path + strlen(path);
+ c = 41;
+ r = bin_to_hex((const unsigned char*)criteria, FINGERPRINT_LENGTH, (unsigned char*)p, &c);
+ if (r) {
+ return ERR_FAIL;
+ }
+ r = key_from_file(gpg->k, path, passphrase);
+ if (r) {
+ return ERR_FAIL;
+ }
+ break;
+ default:
+ return ERR_FAIL;
+ }
+
+ p = (char*)gcry_pk_get_keygrip(*gpg->k, (unsigned char*)gpg->fingerprint);
+ if (p == NULL) {
+ return ERR_KEYFAIL;
+ }
+
+ r = key_apply_public(gpg, *gpg->k);
+ if (r) {
+ return ERR_FAIL;
+ }
+
+ return ERR_OK;
}
-int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) {
+static int gpg_sign_sexp(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) {
gcry_error_t e;
gcry_sexp_t data;
size_t err_offset;
@@ -316,6 +468,7 @@ int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v) {
return 0;
}
+
int gpg_verify(gcry_sexp_t *sig, gcry_sexp_t *key, const char *v) {
gcry_error_t e;
gcry_sexp_t data;
@@ -354,9 +507,18 @@ int gpg_store_digest(struct gpg_store *gpg, char *out, const char *in) {
/// \todo handle path length limit
void gpg_store_init(struct gpg_store *gpg, const char *path) {
+ char *p;
+ size_t c;
+ memset(gpg, 0, sizeof(struct gpg_store));
gpg->passphrase_digest_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
- strcpy(gpg->path, path);
+ strcpy(gpg->path, path);
+ c = strlen(gpg->path);
+ p = gpg->path+c;
+ if (*p != '/') {
+ *p = '/';
+ *(p+1) = 0;
+ }
}
int gpg_store_check(struct gpg_store *gpg, const char *passphrase) {
@@ -364,7 +526,6 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase) {
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;
@@ -386,9 +547,9 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase) {
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);
+ //r = key_from_file(&k, p.c_str(), passphrase_hash);
+ //r = key_from_file(&k, p, passphrase_hash);
+ r = key_from_file(&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());
@@ -400,7 +561,7 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase) {
char pp[2048];
//sprintf(pp, "%s/key.bin", p.c_str());
sprintf(pp, "%s/key.bin", p);
- r = key_create_file(&k, pp, passphrase_hash);
+ r = key_create_file(gpg, &k, passphrase_hash);
if (r != ERR_OK) {
return r;
}
@@ -420,6 +581,132 @@ int gpg_store_check(struct gpg_store *gpg, const char *passphrase) {
sprintf(pp, "found key %s in %s", (unsigned char*)gpg->fingerprint, p);
debug_log(DEBUG_INFO, pp);
}
- r = gpg_sign(&o, &k, sign_test);
- return r;
+ //r = gpg_sign(&o, &k, sign_test);
+ //return r;
+ return ERR_OK;
+}
+
+int gpg_store_sign(struct gpg_store *gpg, char *data, size_t data_len, const char *passphrase) {
+ return gpg_store_sign_with(gpg, data, data_len, passphrase, NULL);
+}
+
+int gpg_store_sign_with(struct gpg_store *gpg, char *data, size_t data_len, const char *passphrase, const char *fingerprint) {
+ int r;
+ size_t c;
+ gcry_sexp_t key;
+ gcry_sexp_t pnt;
+ gcry_sexp_t msg;
+ gcry_sexp_t sig;
+ gcry_error_t e;
+ char *p;
+
+ r = calculate_digest_algo(data, data_len, gpg->last_data, GCRY_MD_SHA512);
+ if (r) {
+ return 1;
+ }
+
+ gpg->k = &key;
+ if (fingerprint == NULL) {
+ r = gpg_key_load(gpg, passphrase, KEE_GPG_FIND_MAIN, NULL);
+ } else {
+ r = gpg_key_load(gpg, passphrase, KEE_GPG_FIND_FINGERPRINT, fingerprint);
+ }
+ if (r) {
+ return 1;
+ }
+
+ c = 0;
+ e = gcry_sexp_build(&msg, &c, "(data(flags eddsa)(hash-algo sha512)(value %b))", 64, gpg->last_data);
+ if (e != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ e = gcry_pk_sign(&sig, msg, *gpg->k);
+ if (e != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ // retrieve r and write it
+ pnt = NULL;
+ pnt = gcry_sexp_find_token(sig, "r", 1);
+ if (pnt == NULL) {
+ return 1;
+ }
+ c = POINT_LENGTH;
+ p = gcry_sexp_nth_data(pnt, 1, &c);
+ if (p == NULL) {
+ return 1;
+ }
+ memcpy(gpg->last_signature, p, c);
+
+ // retrieve s and write it
+ pnt = NULL;
+ pnt = gcry_sexp_find_token(sig, "s", 1);
+ if (pnt == NULL) {
+ return 1;
+ }
+ c = POINT_LENGTH;
+ p = gcry_sexp_nth_data(pnt, 1, &c);
+ if (p == NULL) {
+ return 1;
+ }
+ memcpy(gpg->last_signature + POINT_LENGTH, p, c);
+
+ gcry_sexp_release(*gpg->k);
+ gpg->k = NULL;
+
+ return 0;
+}
+
+int gpg_store_verify(const char *sig_bytes, const char *digest, const char *pubkey_bytes) {
+ gcry_mpi_t sig_r;
+ gcry_mpi_t sig_s;
+ size_t c;
+ gcry_error_t err;
+ gcry_sexp_t sig;
+ gcry_sexp_t msg;
+ gcry_sexp_t pubkey;
+
+ c = 0;
+ err = gcry_sexp_build(&pubkey, &c, "(key-data(public-key(ecc(curve Ed25519)(q %b))))", PUBKEY_LENGTH, pubkey_bytes);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ c = 0;
+ err = gcry_mpi_scan(&sig_r, GCRYMPI_FMT_STD, sig_bytes, POINT_LENGTH, &c);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+ if (c != 32) {
+ return 1;
+ }
+
+ c = 0;
+ err = gcry_mpi_scan(&sig_s, GCRYMPI_FMT_STD, sig_bytes + POINT_LENGTH, POINT_LENGTH, &c);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+ if (c != 32) {
+ return 1;
+ }
+
+ c = 0;
+ err = gcry_sexp_build(&sig, &c, "(sig-val(eddsa(r %m)(s %m)))", sig_r, sig_s);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ c = 0;
+ err = gcry_sexp_build(&msg, &c, "(data(flags eddsa)(hash-algo sha512)(value %b))", DIGEST_LENGTH, digest);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ err = gcry_pk_verify(sig, msg, pubkey);
+ if (err != GPG_ERR_NO_ERROR) {
+ return 1;
+ }
+
+ return 0;
}
diff --git a/src/gpg.h b/src/gpg.h
@@ -9,16 +9,28 @@
#define CHACHA20_KEY_LENGTH_BYTES 32
#define CHACHA20_NONCE_LENGTH_BYTES 12
#define PUBKEY_LENGTH 32
+#define FINGERPRINT_LENGTH 20
+#define SIGNATURE_LENGTH 64
+#define DIGEST_LENGTH 64
+#define POINT_LENGTH 32
#ifndef ENCRYPT_BLOCKSIZE
#define ENCRYPT_BLOCKSIZE 4096
#endif
+enum gpg_find_mode_e {
+ KEE_GPG_FIND_MAIN,
+ KEE_GPG_FIND_FINGERPRINT,
+};
struct gpg_store {
+ gcry_sexp_t *k;
size_t passphrase_digest_len;
- char fingerprint[40];
+ char fingerprint[FINGERPRINT_LENGTH];
+ char public_key[PUBKEY_LENGTH];
char path[1024];
+ char last_signature[SIGNATURE_LENGTH];
+ char last_data[DIGEST_LENGTH];
};
/**
@@ -89,7 +101,12 @@ 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);
-int gpg_key_create(gcry_sexp_t *key);
-int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v);
+//int gpg_key_create(gcry_sexp_t *key);
+int gpg_key_create(struct gpg_store *gpg, const char *passphrase);
+//int gpg_sign(gcry_sexp_t *out, gcry_sexp_t *key, const char *v);
+int gpg_key_load(struct gpg_store *gpg, const char *passphrase, enum gpg_find_mode_e mode, void *criteria);
+int gpg_store_sign(struct gpg_store *gpg, char *data, size_t data_len, const char *passphrase);
+int gpg_store_sign_with(struct gpg_store *gpg, char *data, size_t data_len, const char *passphrase, const char *fingerprint);
+int gpg_store_verify(const char *sig_bytes, const char *digest, const char *pubkey_bytes);
#endif
diff --git a/src/gtk/kee-entry-item.c b/src/gtk/kee-entry-item.c
@@ -31,6 +31,7 @@ struct _KeeEntryItem {
G_DEFINE_TYPE(KeeEntryItem, kee_entry_item, GTK_TYPE_BOX);
+
static void kee_entry_item_dispose(GObject *o) {
}
@@ -74,3 +75,31 @@ void kee_entry_item_apply_list_item_widget(KeeEntryItem *o) {
gtk_box_append(GTK_BOX(o), widget);
return;
}
+
+
+void kee_entry_item_apply_edit_widget(GtkBox *box, struct kee_entry_item_form_t *form, int first) {
+ GtkWidget *widget;
+
+ if (first) {
+ widget = gtk_label_new("Initial credit");
+ } else {
+ widget = gtk_label_new("Credit change");
+ }
+ gtk_box_append(box, widget);
+ widget = gtk_entry_new();
+ form->alice_credit_delta = GTK_ENTRY(widget);
+ gtk_entry_set_input_purpose(form->alice_credit_delta, GTK_INPUT_PURPOSE_NUMBER);
+ gtk_box_append(box, widget);
+
+ if (first) {
+ widget = gtk_label_new("Initial collateral");
+ } else {
+ widget = gtk_label_new("Collateral change");
+ }
+ gtk_box_append(box, widget);
+ widget = gtk_entry_new();
+ form->alice_collateral_delta = GTK_ENTRY(widget);
+ gtk_entry_set_input_purpose(form->alice_collateral_delta, GTK_INPUT_PURPOSE_NAME);
+ gtk_box_append(box, widget);
+
+}
diff --git a/src/gtk/kee-entry-item.h b/src/gtk/kee-entry-item.h
@@ -10,6 +10,14 @@
G_BEGIN_DECLS
+
+struct kee_entry_item_form_t {
+ GtkEntry *alice_credit_delta;
+ GtkEntry *alice_collateral_delta;
+ GtkEntry *bob_credit_delta;
+ GtkEntry *bob_collateral_delta;
+};
+
enum KEE_ENTRY_ITEM_PROPS {
KEE_P_ENTRY_ITEM_ALICE_CREDIT_DELTA = 1,
KEE_P_ENTRY_ITEM_BOB_CREDIT_DELTA,
@@ -27,6 +35,7 @@ void kee_entry_item_handle_bind(GtkListItemFactory *o, GtkListItem *item);
void kee_entry_item_set_resolver(KeeEntryItem *o, struct Cadiz *resolver);
int kee_entry_item_deserialize(KeeEntryItem *o, const char *data, size_t data_len);
void kee_entry_item_apply_list_item_widget(KeeEntryItem *o);
+void kee_entry_item_apply_edit_widget(GtkBox *box, struct kee_entry_item_form_t *form, int first);
G_END_DECLS
diff --git a/src/gtk/kee-entry.c b/src/gtk/kee-entry.c
@@ -45,6 +45,7 @@ struct kee_entry_form_t {
GtkEntry *uoa;
GtkEntry *uoa_decimals;
GtkEntry *passphrase;
+ struct kee_entry_item_form_t item_form;
};
/// \todo factor out separate struct for listitem
@@ -69,23 +70,40 @@ struct _KeeEntry {
G_DEFINE_TYPE(KeeEntry, kee_entry, GTK_TYPE_BOX);
static void kee_entry_handle_add(GtkButton *butt, KeeEntry *o) {
+ struct kee_ledger_item_t *item;
GtkEntryBuffer *buf;
char *b;
+ size_t c;
buf = gtk_entry_get_buffer(o->form->uoa);
b = (char*)gtk_entry_buffer_get_text(buf);
strcpy(o->ledger.uoa, b);
- buf = gtk_entry_get_buffer(o->form->uoa);
+ buf = gtk_entry_get_buffer(o->form->uoa_decimals);
b = (char*)gtk_entry_buffer_get_text(buf);
o->ledger.uoa_decimals = (char)atoi(b);
- buf = gtk_entry_get_buffer(o->form->uoa);
- if (gtk_entry_buffer_get_length(buf) != PUBKEY_LENGTH * 2) {
+ item = kee_ledger_add_item(&o->ledger);
+ item->initiator = ALICE;
+
+ buf = gtk_entry_get_buffer(o->form->item_form.alice_credit_delta);
+ b = (char*)gtk_entry_buffer_get_text(buf);
+ item->alice_credit_delta = atoi(b);
+
+ buf = gtk_entry_get_buffer(o->form->item_form.alice_collateral_delta);
+ b = (char*)gtk_entry_buffer_get_text(buf);
+ item->alice_collateral_delta = atoi(b);
+
+ buf = gtk_entry_get_buffer(o->form->bob_pubkey);
+ b = (char*)gtk_entry_buffer_get_text(buf);
+ c = hex2bin(b, (unsigned char*)o->ledger.pubkey_bob);
+ if (c == 0) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "invalid counterparty public key data");
+ return;
+ } else if (c != PUBKEY_LENGTH) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "wrong size for counterparty public key");
return;
}
- memcpy(o->ledger.pubkey_bob, o->form->bob_pubkey, PUBKEY_LENGTH);
o->state |= ENTRYSTATE_LOAD;
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "adding ledger entry");
@@ -219,6 +237,8 @@ static void kee_entry_setup_edit_widget(KeeEntry *o) {
gtk_entry_set_max_length(o->form->uoa_decimals, 2);
gtk_box_append(GTK_BOX(o->edit), widget);
+ kee_entry_item_apply_edit_widget(GTK_BOX(o->edit), &o->form->item_form, 1);
+
/// \todo DRY - kee-key.c
widget = gtk_label_new("private key passphrase");
gtk_box_append(GTK_BOX(o->edit), widget);
@@ -290,6 +310,7 @@ static void kee_entry_init_list_widget(KeeEntry *o) {
sel = gtk_single_selection_new(G_LIST_MODEL(model));
view = gtk_list_view_new(GTK_SELECTION_MODEL(sel), GTK_LIST_ITEM_FACTORY(factory));
gtk_box_append(GTK_BOX(o->display), GTK_WIDGET(view));
+
}
int kee_entry_deserialize(KeeEntry *o, const char *data, size_t data_len) {
diff --git a/src/ledger.c b/src/ledger.c
@@ -139,35 +139,40 @@ static int verify_item(struct kee_ledger_t *ledger, asn1_node item, const char *
return 1;
}
- c = 0;
- err = gcry_mpi_scan(&sr, GCRYMPI_FMT_STD, sig_data, 32, &c);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
- return 1;
- }
-
- c = 0;
- err = gcry_mpi_scan(&ss, GCRYMPI_FMT_STD, sig_data+32, 32, &c);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
+ r = gpg_store_verify(sig_data, p, pubkey_last_data);
+ if (r) {
return 1;
}
- c = 0;
- err = gcry_sexp_build(&sig, &c, "(sig-val(eddsa(r %m)(s %m)))", sr, ss);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
+// c = 0;
+// err = gcry_mpi_scan(&sr, GCRYMPI_FMT_STD, sig_data, 32, &c);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
+// if (c != 32) {
+// return 1;
+// }
+//
+// c = 0;
+// err = gcry_mpi_scan(&ss, GCRYMPI_FMT_STD, sig_data+32, 32, &c);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
+// if (c != 32) {
+// return 1;
+// }
- c = 0;
- err = gcry_sexp_build(&msg, &c, "(data(flags eddsa)(hash-algo sha512)(value %b))", 64, p);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
+// c = 0;
+// err = gcry_sexp_build(&sig, &c, "(sig-val(eddsa(r %m)(s %m)))", sr, ss);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
+//
+// c = 0;
+// err = gcry_sexp_build(&msg, &c, "(data(flags eddsa)(hash-algo sha512)(value %b))", 64, p);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
/// \todo "string too long" error when build same string as can "new" - bug in gcrypt?
// c = 0;
@@ -176,22 +181,22 @@ static int verify_item(struct kee_ledger_t *ledger, asn1_node item, const char *
// return 1;
// }
- strcpy(pubkey_sexp_data, "(8:key-data(10:public-key(3:ecc(5:curve7:Ed25519)(1:q32:");
- c = strlen(pubkey_sexp_data);
- memcpy(pubkey_sexp_data + c, pubkey_last_data, 32);
- strcpy(pubkey_sexp_data + c + 32, "))))");
-
- pubkey_sexp_len = c + 32 + 4;
- c = 0;
- err = gcry_sexp_new(&pubkey, pubkey_sexp_data, pubkey_sexp_len, 1);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
+// strcpy(pubkey_sexp_data, "(8:key-data(10:public-key(3:ecc(5:curve7:Ed25519)(1:q32:");
+// c = strlen(pubkey_sexp_data);
+// memcpy(pubkey_sexp_data + c, pubkey_last_data, 32);
+// strcpy(pubkey_sexp_data + c + 32, "))))");
+//
+// pubkey_sexp_len = c + 32 + 4;
+// c = 0;
+// err = gcry_sexp_new(&pubkey, pubkey_sexp_data, pubkey_sexp_len, 1);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
- err = gcry_pk_verify(sig, msg, pubkey);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
+// err = gcry_pk_verify(sig, msg, pubkey);
+// if (err != GPG_ERR_NO_ERROR) {
+// return 1;
+// }
return 0;
}
@@ -216,13 +221,22 @@ void kee_ledger_reset_cache(struct kee_ledger_t *ledger) {
}
}
+struct kee_ledger_item_t *kee_ledger_add_item(struct kee_ledger_t *ledger) {
+ struct kee_ledger_item_t *prev;
+
+ prev = ledger->last_item;
+ ledger->last_item = calloc(sizeof(struct kee_ledger_item_t), 1);
+ ledger->last_item->prev_item = prev;
+
+ return ledger->last_item;
+}
+
struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, const char *data, size_t data_len) {
int r;
int c;
char err[1024];
asn1_node root;
asn1_node item;
- struct kee_ledger_item_t *prev;
struct kee_ledger_item_t *cur;
int *credit_delta;
int *collateral_delta;
@@ -231,10 +245,7 @@ struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, con
char tmp[64];
int v;
- prev = ledger->last_item;
- ledger->last_item = calloc(sizeof(struct kee_ledger_item_t), 1);
- cur = ledger->last_item;
- cur->prev_item = prev;
+ cur = kee_ledger_add_item(ledger);
memset(&root, 0, sizeof(root));
memset(&item, 0, sizeof(item));
@@ -608,3 +619,70 @@ int kee_ledger_item_serialize(struct kee_ledger_item_t *item, char *out, size_t
return 0;
}
+
+static int kee_ledger_digest(struct kee_ledger_t *ledger, char *out, size_t out_len) {
+ int r;
+ char out_data[1024];
+
+ r = kee_ledger_serialize(ledger, out_data, &out_len);
+ if (r) {
+ return r;
+ }
+
+ r = calculate_digest_algo(out_data, out_len, out, GCRY_MD_SHA512);
+ if (r) {
+ return ERR_FAIL;
+ }
+
+ return ERR_OK;
+}
+
+//int kee_ledger_sign(struct kee_ledger_t *ledger, char *out, size_t *out_len) {
+// char *p;
+// kee_ledger_item_t *item;
+// char *signature_request;
+// size_t c
+// size_t l;
+// enum kee_item_serialize_mode_e mode;
+//
+// p = out;
+// c = *out_len;
+// l = *out_len;
+// *out_len = 0;
+//
+// item = ledger->last_item;
+//
+// if (item->initiator == BOB) {
+// mode = KEE_LEDGER_ITEM_SERIALIZE_RESPONSE;
+// } else {
+// signature_request = item->alice_signature;
+// }
+//
+// if (memcmp(signature_request, zero_content, 64)) {
+// return ERR_ALREADY_SIGNED;
+// }
+//
+// r = kee_ledger_digest(ledger, p, &c);
+// if (r) {
+// return ERR_FAIL;
+// }
+// p = out + c;
+// l -= c;
+// c = l;
+//
+// r = kee_ledger_serialize(ledger, p, &c);
+// if (r) {
+// return ERR_FAIL;
+// }
+// p = out + c;
+// l -= c;
+// c = l;
+//
+// r = kee_ledger_item_serialize(ledger, p, &c, KEE_LEDGER_ITEM_SERIALIZE_REQUEST);
+// if (r) {
+// return ERR_FAIL;
+// }
+//
+//
+// return ERR_OK;
+//}
diff --git a/src/ledger.h b/src/ledger.h
@@ -51,6 +51,7 @@ struct kee_ledger_t {
};
struct kee_ledger_item_t *kee_ledger_parse_item(struct kee_ledger_t *ledger, const char *data, size_t data_len);
+struct kee_ledger_item_t *kee_ledger_add_item(struct kee_ledger_t *ledger);
int kee_ledger_parse(struct kee_ledger_t *ledger, const char *data, size_t data_len);
int kee_ledger_serialize(struct kee_ledger_t *ledger, char *out, size_t *out_len);
void kee_ledger_init(struct kee_ledger_t *ledger);
diff --git a/src/tests/ledger.c b/src/tests/ledger.c
@@ -3,11 +3,11 @@
#include "ledger.h"
#include "hex.h"
-const char *test_ledger_data = "30818e0c035553440201020420c042f26197b312fef5def17e8c7f978c3219f74981f8430cd3bd57116014d33904201613476c3986b1317fbd831a07665210a1c271f1d88a04e8aa804bb032b44f6b04403aba8490187f543270b48e770bb272021f8fdb22f584080fc9d4d02553f4504624122d99ffc9254cdb8a2ef3826e47f60e1e7b5ec28b635fbba1141e3f486aad";
+const char *test_ledger_data = "30818e0c035553440201020420c67ee54f93d63d00f4b8c9a7e1c11b39657b55c525704bb32e15ec85bc140d140420adcaf6474132ac36e97d3dbee693d3b186cd8399d402dc505073069c46b5bd780440878102c19c032fd0d06f6b054a01e969b823ccfe7d5ba37a37beef3e64feb5f9b38e1a0f7413b781a4626b884f89bb3052f662692c53578453dc7c7d911d8609";
-const char *test_item_data_a = "3082011d044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020817c7aecdfb6a9cbd020212d8020219600440c333b18dfa822c3ce875de07d54d932ed631aaa7f996153a120bda81e2f0717f4f5e67547019bcd8af0ba6ecba95313bbdc5e43385670d67c24ef76879514ad6044010b17b8c2bc18d7c040f8a4927d20714b78f48f6c3be23867f0ba4aac96b61081f86157942620852c2a47d12a3fb066604018d4228908cf5b0c29568fd67bf0c0101ff0440d6ea4b6501aa6c87cc67bc3297a999a53d8d756873656a0ad68ce9a3b5f9be3d974acf17f4d54d27f9ecf8e854fed32b6c672fa1378142f8898ebd9d68a8540f00";
+const char *test_item_data_a = "3082011d044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020817c94f8dec0e485d0202150e0202107a04404919455218d5bfb6ae9f0de9af37c23c140f976d4a0cb8652fc6897e6f043bc454021128b8daa18eb36c28687cfc33c3e1aa9b4e37059822ae14a0cefd1087a704409bd071c737b9342ab87de3f3e43ccba508366d09b28a6e331f1255d5668b211694fe011c78b6bba376590a5dae47e2ff880facad68e9ab4fca15309c00a6bd0a0101ff04402a3eac6ff818857883fb26d052fb17f2384f9fdb60f5bbae7d849bf621dfc65e68c2b82359b6c54b041732f11919ab0c1ae1a68504870c872f30cc74f9b9ae0400";
-const char *test_item_data_b = "3082011d0440534f94460b11203ec7272d5e5ec67c7d5c2669d0db4b732ce987f7f9a94e6a00d34622d466a1839feedc4e0b690af900baa631ce4cafd67305f5b9c0f8f8faaa020817c7aecdfb94675e02021d4a02020cd0044035c13f852ed6a20385959560c61e780dafebffa44d1e96f9293db1e75bf32b7cee53f3e96beeaeeebdf49e4467727f101b35a3e4a536c8545ec84b2880ce9b0d04403107700183297208a870aa15dcf1ca5da4b59adbc9388eceeb1a859259cd1b0ad7510c67b92a51fc9fc60b1cf7657976b99839ef7bd26134a4d5fed4cf2b820d0101ff044083ba7fd4d08541dee2a3f13189194454d429440fe7799d5e8536d2e18e6a5006487746b68f16fb2534a23372814bce45455e6269d187741217e505ff6f73d70a01";
+const char *test_item_data_b = "3082011d0440c2b795d9d3183bcc9d6ae1ae2960c302d7364a04996013dd9f31be628c46d2ee87b0cba51db67cd851a64dba04cc3e191dd48e7d7f3e063b0c850fd7b9b82218020817c94f8dec3e67aa02020ce20202049504401f78629f3015afa72f443005fc6711f7a7e2e20072eac86c98874c1dbe42095de3408d5711fb8fca56428461139992e8ff0452dc2092d2ba6ddb9658607f90ac0440d5d6cd6d905d0eb104ff3ab825cfc1be27f69a5377a3c84c33b3c5a0e6902e2af74d9024db58e1b90375be316e687a928edb881f8b6b3795682c20e533f9ed040101ff04409e8ffbbd5684b75aed7bf42a044914ea5813b1fccd9645462664317fa92dd9766c9ede39ea381e9648ef88bad220d0808660be63c94bf9954cf00daddad1150e01";
int main() {
diff --git a/src/tests/sign.c b/src/tests/sign.c
@@ -1,4 +1,6 @@
#include <gcrypt.h>
+#include <stdlib.h>
+#include <fcntl.h>
#include "ledger.h"
#include "gpg.h"
@@ -7,24 +9,18 @@
const char *content_test = "Subject: foo\n\nsome content\n";
const char *content_test_item = "Subject: bar\n\nsome other content\n";
-int main() {
+/// \todo split up function
+int test_sign() {
int r;
- size_t c;
gcry_sexp_t alice;
- gcry_sexp_t alice_pub;
gcry_sexp_t bob;
- gcry_sexp_t bob_pub;
- gcry_sexp_t tmp;
- gcry_sexp_t sig;
- gcry_sexp_t msg;
- gcry_mpi_t sr;
- gcry_mpi_t ss;
- gcry_error_t err;
+ char alice_fingerprint[20];
char *p;
char *out;
size_t out_len;
char *out_item;
size_t out_item_len;
+ struct gpg_store gpg;
struct kee_ledger_t ledger;
struct kee_ledger_item_t item;
struct kee_ledger_item_t *item_parsed;
@@ -32,6 +28,7 @@ int main() {
struct kee_content_t content_item;
char item_sum[64];
const char *version;
+ char path[1024];
version = gcry_check_version(NULL);
if (version == 0x0) {
@@ -40,46 +37,30 @@ int main() {
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
- r = gpg_key_create(&alice);
- if (r) {
- return 1;
- }
- r = gpg_key_create(&bob);
- if (r) {
+ strcpy(path, "/tmp/keetest_key_XXXXXX");
+ p = mkdtemp(path);
+ if (p == NULL) {
return 1;
}
kee_ledger_init(&ledger);
- tmp = gcry_sexp_find_token(alice, "public-key", 10);
- if (tmp == NULL) {
- return 1;
- }
- tmp = gcry_sexp_find_token(tmp, "q", 1);
- if (tmp == NULL) {
- return 1;
- }
- out_len = 32;
- out = gcry_sexp_nth_data(tmp, 1, &out_len);
- if (tmp == NULL) {
+ gpg_store_init(&gpg, p);
+ gpg.k = &alice;
+ r = gpg_key_create(&gpg, "1234"); // alice
+ if (r) {
return 1;
}
- memcpy(ledger.pubkey_alice, out, 32);
+ memcpy(ledger.pubkey_alice, gpg.public_key, PUBKEY_LENGTH);
+ memcpy(alice_fingerprint, gpg.fingerprint, FINGERPRINT_LENGTH);
- tmp = gcry_sexp_find_token(bob, "public-key", 10);
- if (tmp == NULL) {
- return 1;
- }
- tmp = gcry_sexp_find_token(tmp, "q", 1);
- if (tmp == NULL) {
- return 1;
- }
- out_len = 32;
- out = gcry_sexp_nth_data(tmp, 1, &out_len);
- if (tmp == NULL) {
+ gpg_store_init(&gpg, p);
+ gpg.k = &bob;
+ r = gpg_key_create(&gpg, "1234"); // bob
+ if (r) {
return 1;
}
- memcpy(ledger.pubkey_bob, out, 32);
+ memcpy(ledger.pubkey_bob, gpg.public_key, PUBKEY_LENGTH);
strcpy(ledger.uoa, "USD");
ledger.uoa_decimals = 2;
@@ -92,7 +73,6 @@ int main() {
if (r) {
return 1;
}
-
r = calculate_digest_algo(content_test, strlen(content_test), content.key, GCRY_MD_SHA512);
if (r) {
return 1;
@@ -105,7 +85,7 @@ int main() {
return 1;
}
- r = calculate_digest_algo(out, out_len, ledger.digest, GCRY_MD_SHA512);
+ r = calculate_digest_algo(out, out_len, ledger.digest, GCRY_MD_SHA512);
if (r) {
return 1;
}
@@ -122,7 +102,7 @@ int main() {
item.initiator = BOB;
item.response = 1;
- r = calculate_digest_algo(content_test, strlen(content_test_item), content_item.key, GCRY_MD_SHA512);
+ r = calculate_digest_algo(content_test_item, strlen(content_test_item), content_item.key, GCRY_MD_SHA512);
if (r) {
return 1;
}
@@ -130,6 +110,10 @@ int main() {
if (r) {
return 1;
}
+ r = calculate_digest_algo(content_test_item, strlen(content_test_item), content_item.key, GCRY_MD_SHA512);
+ if (r) {
+ return 1;
+ }
out_item_len = 4096;
out_item = malloc(out_item_len);
@@ -141,58 +125,15 @@ int main() {
if (r) {
return 1;
}
- r = gpg_sign(&sig, &bob, item_sum);
+ r = gpg_store_sign(&gpg, out_item, out_item_len, "1234");
if (r) {
return 1;
}
- c = 0;
- bob_pub = gcry_sexp_find_token(bob, "public-key", 10);
- if (bob_pub == NULL) {
- return 1;
- }
- err = gcry_sexp_build(&bob_pub, &c, "(key-data%S)", bob_pub);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- r = gpg_verify(&sig, &bob, item_sum);
+ r = gpg_store_verify(gpg.last_signature, item_sum, ledger.pubkey_bob);
if (r) {
return 1;
}
-
- tmp = gcry_sexp_find_token(sig, "r", 1);
- if (tmp == NULL) {
- return 1;
- }
- sr = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD);
- if (sr == NULL) {
- return 1;
- }
- tmp = gcry_sexp_find_token(sig, "s", 1);
- if (tmp == NULL) {
- return 1;
- }
- ss = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD);
- if (ss == NULL) {
- return 1;
- }
- c = 0;
- err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, sr);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
- return 1;
- }
- memcpy(item.bob_signature, item_sum, 32);
- c = 0;
- err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, ss);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
- return 1;
- }
- memcpy(item.bob_signature+32, item_sum, 32);
+ memcpy(item.bob_signature, gpg.last_signature, SIGNATURE_LENGTH);
out_item_len = 4096;
r = kee_ledger_item_serialize(&item, out_item, &out_item_len, KEE_LEDGER_ITEM_SERIALIZE_RESPONSE);
@@ -203,59 +144,16 @@ int main() {
if (r) {
return 1;
}
- r = gpg_sign(&sig, &alice, item_sum);
+ gpg.k = &alice;
+ r = gpg_store_sign_with(&gpg, out_item, out_item_len, "1234", alice_fingerprint);
if (r) {
return 1;
}
- c = 0;
- alice_pub = gcry_sexp_find_token(alice, "public-key", 10);
- if (alice_pub == NULL) {
- return 1;
- }
- err = gcry_sexp_build(&alice_pub, &c, "(key-data%S)", alice_pub);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- r = gpg_verify(&sig, &alice, item_sum);
+ r = gpg_store_verify(gpg.last_signature, item_sum, ledger.pubkey_alice);
if (r) {
return 1;
}
- tmp = NULL;
- tmp = gcry_sexp_find_token(sig, "r", 1);
- if (tmp == NULL) {
- return 1;
- }
- sr = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD);
- if (sr == NULL) {
- return 1;
- }
- tmp = NULL;
- tmp = gcry_sexp_find_token(sig, "s", 1);
- if (tmp == NULL) {
- return 1;
- }
- ss = gcry_sexp_nth_mpi(tmp, 1, GCRYMPI_FMT_STD);
- if (ss == NULL) {
- return 1;
- }
- c = 0;
- err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, sr);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
- return 1;
- }
- memcpy(item.alice_signature, item_sum, 32);
- c = 0;
- err = gcry_mpi_print(GCRYMPI_FMT_STD, item_sum, 32, &c, ss);
- if (err != GPG_ERR_NO_ERROR) {
- return 1;
- }
- if (c != 32) {
- return 1;
- }
- memcpy(item.alice_signature+32, item_sum, 32);
+ memcpy(item.alice_signature, gpg.last_signature, SIGNATURE_LENGTH);
out_item_len = 4096;
r = kee_ledger_item_serialize(&item, out_item, &out_item_len, KEE_LEDGER_ITEM_SERIALIZE_FINAL);
@@ -268,7 +166,6 @@ int main() {
if (item_parsed == NULL) {
return 1;
}
- tmp = NULL;
free(out_item);
free(out);
@@ -278,3 +175,46 @@ int main() {
return 0;
}
+
+int test_create() {
+ char *p;
+ int r;
+ struct gpg_store gpg;
+ char path[1024];
+ gcry_sexp_t key;
+
+ strcpy(path, "/tmp/keetest_key_XXXXXX");
+ p = mkdtemp(path);
+ if (p == NULL) {
+ return 1;
+ }
+ gpg_store_init(&gpg, p)
+ ;
+ r = gpg_key_create(&gpg, "1234");
+ if (r) {
+ return 1;
+ }
+
+ memset(&gpg, 0, sizeof(struct gpg_store));
+ gpg_store_init(&gpg, p);
+ gpg.k = &key;
+ r = gpg_key_load(&gpg, "1234", KEE_GPG_FIND_MAIN, NULL);
+ if (r) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int main() {
+ int r;
+ r = test_create();
+ if (r) {
+ return 1;
+ }
+ r = test_sign();
+ if (r) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/testdata_asn1.py b/testdata_asn1.py
@@ -457,8 +457,8 @@ if __name__ == '__main__':
keys = ['alice']
alice_key = os.path.join(crypto_dir, 'alice.key.bin')
- os.unlink('key.bin')
- os.symlink(alice_key, 'key.bin')
+ os.unlink('kee.key')
+ os.symlink(alice_key, 'kee.key')
count_ledgers = os.environ.get('COUNT', '1')