kee

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

commit a329ade72aff32f4af6595eb1f9fbe55ed4524c8
parent 1385f473d54dbf7a28aaaf111f1f4096d93107ed
Author: lash <dev@holbrook.no>
Date:   Sat,  4 May 2024 09:55:04 +0100

Add initiator detection to use for ledger import

Diffstat:
Msrc/gpg.c | 16+---------------
Msrc/ledger.c | 104++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/ledger.h | 17++++++++---------
Msrc/tests/ledger.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/tests/testutil.c | 38+++++++++++++++++++++++++++++++++++---
Msrc/tests/testutil.h | 1+
6 files changed, 170 insertions(+), 65 deletions(-)

diff --git a/src/gpg.c b/src/gpg.c @@ -284,8 +284,6 @@ static int key_create(struct gpg_store *gpg, gcry_sexp_t *key) { /** * \todo consistent endianness for key length in persistent storage (fwrite) - et* \todo implement MAC - * \todo test new data length location (part of ciphertext) * \todo doc must have enough in path for path + fingerprint hex * */ @@ -325,14 +323,6 @@ static int key_create_file(struct gpg_store *gpg, gcry_sexp_t *key, const char * m = c; c = get_padsize(m, ENCRYPT_BLOCKSIZE); - /// \todo malloc -// -// l = c; -// c = fwrite(&kl, sizeof(int), 1, f); -// if (c != 1) { -// fclose(f); -// return ERR_KEYFAIL; -// } gcry_create_nonce(nonce, CHACHA20_NONCE_LENGTH_BYTES); r = encryptb(ciphertext, c, v, m+sizeof(int), passphrase, nonce); if (r) { @@ -349,11 +339,7 @@ static int key_create_file(struct gpg_store *gpg, gcry_sexp_t *key, const char * 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); diff --git a/src/ledger.c b/src/ledger.c @@ -70,13 +70,6 @@ static char *get_message_asn(struct kee_ledger_t *ledger, asn1_node item, char * return NULL; } -// c = 64; -// r = asn1_read_value(item, "signatureResponse", sig, (int*)&c); -// if (r != ASN1_SUCCESS) { -// printf("%d (%s) %s\n", r, err, asn1_strerror(r)); -// return NULL; -// } - if (mode == KEE_LEDGER_STATE_FINAL) { r = asn1_copy_node(root, "Kee.KeeEntry.signatureResponse", item, "signatureResponse"); if (r != ASN1_SUCCESS) { @@ -693,7 +686,7 @@ int kee_ledger_item_serialize(struct kee_ledger_item_t *item, char *out, size_t } c = 5; - if (item->response) { + if (item->response && mode > KEE_LEDGER_STATE_REQUEST) { response_s = "TRUE"; } else { response_s = "FALSE"; @@ -1022,7 +1015,13 @@ static struct kee_ledger_item_t* get_item_by_idx(struct kee_ledger_t *ledger, in return item; } -static void get_authentication_params(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, char **pubkey_request, char **sig_request, char **pubkey_response, char **sig_response) { +static int get_authentication_params(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, char **pubkey_request, char **sig_request, char **pubkey_response, char **sig_response, enum kee_initiator_e initiator) { + if (item->initiator == NOONE) { + item->initiator = initiator; + } + if (item->initiator == NOONE) { + return ERR_FAIL; + } if (item->initiator == BOB) { *pubkey_request = ledger->pubkey_bob; *pubkey_response = ledger->pubkey_alice; @@ -1040,13 +1039,33 @@ static void get_authentication_params(struct kee_ledger_t *ledger, struct kee_le if (!memcmp(*sig_response, zero_content, SIGNATURE_LENGTH)) { *sig_response = NULL; } + return ERR_OK; } -// idx shows which item in ledger execution terminated -int kee_ledger_verify(struct kee_ledger_t *ledger, int *idx) { +static int verify_item(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, enum kee_ledger_state_e mode, const char *sig, const char *pubkey) { int r; char b[1024]; size_t c; + + c = 960; + r = kee_ledger_item_serialize(item, ((char*)b)+DIGEST_LENGTH, &c, mode); + if (r) { + return ERR_FAIL; + } + r = kee_ledger_digest(ledger, b); + if (r) { + return ERR_FAIL; + } + r = verify_item_data(ledger, b, c + DIGEST_LENGTH, sig, pubkey); + if (r) { + return ERR_FAIL; + } + return ERR_OK; +} + +// idx shows which item in ledger execution terminated +int kee_ledger_verify(struct kee_ledger_t *ledger, int *idx) { + int r; struct kee_ledger_item_t *item; char *pubkey_request; char *pubkey_response; @@ -1059,41 +1078,38 @@ int kee_ledger_verify(struct kee_ledger_t *ledger, int *idx) { return ERR_FAIL; } + r = 0; while (1) { - get_authentication_params(ledger, item, &pubkey_request, &sig_request, &pubkey_response, &sig_response); + r = get_authentication_params(ledger, item, &pubkey_request, &sig_request, &pubkey_response, &sig_response, NOONE); + if (r) { + return ERR_FAIL; + } if (sig_response == NULL) { if (*idx > 0) { return ERR_FAIL; } } else { - c = 960; - r = kee_ledger_item_serialize(item, ((char*)b)+DIGEST_LENGTH, &c, KEE_LEDGER_STATE_RESPONSE); - if (r) { - return ERR_FAIL; - } - r = kee_ledger_digest(ledger, b); - if (r) { - return ERR_FAIL; - } - r = verify_item_data(ledger, b, c + DIGEST_LENGTH, sig_response, pubkey_response); - if (r) { - return ERR_FAIL; - } + r = verify_item(ledger, item, KEE_LEDGER_STATE_RESPONSE, sig_response, pubkey_response); } + if (sig_request != NULL) { - c = 960; - r = kee_ledger_item_serialize(item, ((char*)b)+DIGEST_LENGTH, &c, KEE_LEDGER_STATE_REQUEST); - if (r) { - return ERR_FAIL; - } - r = kee_ledger_digest(ledger, b); - if (r) { - return ERR_FAIL; - } - r = verify_item_data(ledger, b, c + DIGEST_LENGTH, sig_request, pubkey_request); - if (r) { - return ERR_FAIL; - } + r = verify_item(ledger, item, KEE_LEDGER_STATE_REQUEST, sig_request, pubkey_request); +// c = 960; +// r = kee_ledger_item_serialize(item, ((char*)b)+DIGEST_LENGTH, &c, KEE_LEDGER_STATE_REQUEST); +// if (r) { +// return ERR_FAIL; +// } +// r = kee_ledger_digest(ledger, b); +// if (r) { +// return ERR_FAIL; +// } +// r = verify_item_data(ledger, b, c + DIGEST_LENGTH, sig_request, pubkey_request); +// if (r) { +// return ERR_FAIL; +// } + } + if (r) { + return ERR_FAIL; } item = item->prev_item; if (item == NULL) { @@ -1174,3 +1190,15 @@ enum kee_ledger_state_e kee_ledger_item_state(struct kee_ledger_item_t *item) { return state; } + +/// \todo consider optional verify with item signature +/// \todo don't get confused; ledger alice is ALWAYS the requester, but when SIGNING alice is always the current keystore private key holder - consider renaming the latter to carol/dave... +enum kee_initiator_e kee_ledger_item_initiator(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, struct gpg_store *gpg) { + item->initiator = NOONE; + if (!memcmp(ledger->pubkey_alice, gpg->public_key, PUBKEY_LENGTH)) { + item->initiator = ALICE; + } else if (memcmp(ledger->pubkey_bob, zero_content, PUBKEY_LENGTH)) { + item->initiator = BOB; + } + return item->initiator; +} diff --git a/src/ledger.h b/src/ledger.h @@ -10,7 +10,7 @@ #include "digest.h" enum kee_initiator_e { - UNKNOWN, + NOONE, ALICE, BOB, }; @@ -54,26 +54,25 @@ struct kee_ledger_t { struct kee_ledger_cache_t *cache; }; -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); void kee_ledger_free(struct kee_ledger_t *ledger); -void kee_ledger_item_free(struct kee_ledger_item_t *item); void kee_ledger_resolve(struct kee_ledger_t *ledger, Cadiz *cadiz); void kee_ledger_reset_cache(struct kee_ledger_t *ledger); -//int kee_ledger_sign(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, struct gpg_store *gpg, char *out, size_t *out_len, const char *passphrase); int kee_ledger_sign(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, struct gpg_store *gpg, const char *passphrase); -enum kee_ledger_state_e kee_ledger_item_state(struct kee_ledger_item_t *item); - -void kee_ledger_item_init(struct kee_ledger_item_t *item); -int kee_ledger_item_serialize(struct kee_ledger_item_t *item, char *out, size_t *out_len, enum kee_ledger_state_e mode); int kee_ledger_serialize_open(struct kee_ledger_t *ledger, char *out, size_t *out_len); int kee_ledger_parse_open(struct kee_ledger_t *ledger, const char *in, size_t in_len); int kee_ledger_put(struct kee_ledger_t *ledger, struct db_ctx *db); int kee_ledger_item_put(struct kee_ledger_t *ledger, struct db_ctx *db, int idx); int kee_ledger_verify(struct kee_ledger_t *ledger, int *err_idx); +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); +void kee_ledger_item_init(struct kee_ledger_item_t *item); +int kee_ledger_item_serialize(struct kee_ledger_item_t *item, char *out, size_t *out_len, enum kee_ledger_state_e mode); +void kee_ledger_item_free(struct kee_ledger_item_t *item); +enum kee_ledger_state_e kee_ledger_item_state(struct kee_ledger_item_t *item); +enum kee_initiator_e kee_ledger_item_initiator(struct kee_ledger_t *ledger, struct kee_ledger_item_t *item, struct gpg_store *gpg); #endif diff --git a/src/tests/ledger.c b/src/tests/ledger.c @@ -188,6 +188,60 @@ int test_verify() { return 0; } +int test_initiator() { + int r; + struct kee_test_t t; + struct kee_ledger_item_t *item; + enum kee_initiator_e initiator; + + r = kee_test_generate(&t); + if (r) { + return 1; + } + + item = t.ledger.last_item; + + r = kee_test_sign_request(&t); + if (r) { + return 1; + } + r = kee_test_sign_response(&t); + if (r) { + return 1; + } + + item->initiator = NOONE; + initiator = kee_ledger_item_initiator(&t.ledger, item, &t.gpg); + if (initiator != ALICE) { + return 1; + } + + kee_test_free(&t); + r = kee_test_generate(&t); + if (r) { + return 1; + } + + kee_test_swap_identities(&t); + r = kee_test_sign_request(&t); + if (r) { + return 1; + } + r = kee_test_sign_response(&t); + if (r) { + return 1; + } + + item = t.ledger.last_item; + item->initiator = NOONE; + initiator = kee_ledger_item_initiator(&t.ledger, item, &t.gpg); + if (initiator != BOB) { + return 1; + } + + return 0; +} + int main() { int i; int r; @@ -213,6 +267,11 @@ int main() { return i; } i++; + r = test_initiator(); + if (r) { + return i; + } + i++; r = test_pair(); if (r) { return i; diff --git a/src/tests/testutil.c b/src/tests/testutil.c @@ -33,6 +33,7 @@ int kee_test_db(struct kee_test_t *t) { int kee_test_sign_request(struct kee_test_t *t) { int r; + t->ledger.last_item->initiator = ALICE; r = kee_ledger_sign(&t->ledger, t->ledger.last_item, &t->gpg, "1234"); if (r) { return 1; @@ -41,10 +42,19 @@ int kee_test_sign_request(struct kee_test_t *t) { return 0; } +//int kee_test_swap_keys(struct kee_test_t *t) { +// if (t->gpg.k == t->alice) { +// t->gpg.k = t->bob; +// } else { +// t->gpg.k = t->alice; +// } +//} +// int kee_test_sign_response(struct kee_test_t *t) { int r; struct kee_ledger_item_t item_swap; + t->ledger.last_item->response = 1; t->gpg.k = t->bob; r = gpg_key_load(&t->gpg, "1234", KEE_GPG_FIND_FINGERPRINT, t->bob_fingerprint); if (r) { @@ -75,6 +85,29 @@ int kee_test_sign_response(struct kee_test_t *t) { return 0; } +void kee_test_swap_identities(struct kee_test_t *t) { + char swap[128]; + struct kee_ledger_t *ledger; + struct kee_ledger_item_t *item; + + ledger = &t->ledger; + item = ledger->last_item; + + memcpy(swap, ledger->pubkey_alice, PUBKEY_LENGTH); + memcpy(ledger->pubkey_alice, ledger->pubkey_bob, PUBKEY_LENGTH); + memcpy(ledger->pubkey_bob, swap, PUBKEY_LENGTH); + +// memcpy(swap, item->alice_signature, SIGNATURE_LENGTH); +// memcpy(item->alice_signature, item->bob_signature, SIGNATURE_LENGTH); +// memcpy(item->bob_signature, swap, SIGNATURE_LENGTH); + + if (item->initiator == ALICE) { + item->initiator = BOB; + } else if (item->initiator == BOB) { + item->initiator = ALICE; + } + +} int kee_test_generate(struct kee_test_t *t) { int r; @@ -158,9 +191,7 @@ int kee_test_generate(struct kee_test_t *t) { if (r) { return 1; } - item->initiator = ALICE; - item->response = 1; - + content_item = *t->content_item; r = calculate_digest_algo(content_test_item, strlen(content_test_item), content_item->key, GCRY_MD_SHA512); if (r) { @@ -196,6 +227,7 @@ void kee_test_free(struct kee_test_t *t) { free(*p); p++; } + kee_ledger_free(&t->ledger); } size_t kee_test_get_ledger_data(struct kee_test_t *t, char **out) { diff --git a/src/tests/testutil.h b/src/tests/testutil.h @@ -35,5 +35,6 @@ size_t kee_test_get_ledger_item_data(struct kee_test_t *t, int idx, char **out); int kee_test_db(struct kee_test_t *t); int kee_test_sign_request(struct kee_test_t *t); int kee_test_sign_response(struct kee_test_t *t); +//void kee_test_swap_identities(struct kee_test_t *t); #endif