libqaeda

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit 30729151cf711d97ebf65201c124be2594a67cd1
parent 5af518a9176615113a5d55accb9f7f785789fd5d
Author: lash <dev@holbrook.no>
Date:   Sat,  5 Apr 2025 01:50:28 +0100

WIP fix leaks in serialization

Diffstat:
Msrc/cli/main.c | 11++++++++++-
Msrc/crypto/gcrypt.c | 9++++++++-
Msrc/lq/base.c | 3++-
Msrc/lq/cert.c | 9++++-----
Msrc/lq/err.c | 3++-
Msrc/lq/err.h | 3+++
Msrc/lq/msg.c | 37++++++++++++++++++++++++++++++++-----
Msrc/lq/msg.h | 6++++++
Msrc/test/test_cert.c | 44+++++++++++++++++++++++++++++++-------------
9 files changed, 98 insertions(+), 27 deletions(-)

diff --git a/src/cli/main.c b/src/cli/main.c @@ -86,6 +86,8 @@ int main(int argc, char **argv) { LQCert *cert; LQMsg *req; LQMsg *res; + char out[LQ_BLOCKSIZE]; + size_t out_len; r = lq_ui_init(); if (r) { @@ -136,7 +138,14 @@ int main(int argc, char **argv) { return 1; } - r = lq_certificate_verify(cert, pubk_alice, NULL); + r = lq_certificate_verify(cert); + if (r != ERR_OK) { + lq_ui_free(); + return 1; + } + + out_len = LQ_BLOCKSIZE; + r = lq_certificate_serialize(cert, out, &out_len, NULL); if (r != ERR_OK) { lq_ui_free(); return 1; diff --git a/src/crypto/gcrypt.c b/src/crypto/gcrypt.c @@ -14,6 +14,7 @@ #include "lq/config.h" #include "lq/err.h" #include "lq/store.h" +#include "lq/base.h" #include "debug.h" #define CHACHA20_KEY_LENGTH_BYTES 32 @@ -28,6 +29,8 @@ enum gpg_find_mode_e { GPG_FIND_FINGERPRINT, ///< Load only the key matching the fingerprint. }; +extern char zeros[65]; + /** * gcrypt implementation of the crypto interface. * @@ -961,10 +964,14 @@ LQSig* lq_privatekey_sign(LQPrivKey *pk, const char *data, size_t data_len, cons LQSig* lq_signature_from_bytes(const char *sig_data, size_t sig_len, LQPubKey *pubkey) { LQSig *sig; + if (!lq_cmp(sig_data, zeros, LQ_SIGN_LEN)) { + return NULL; + } + sig = lq_alloc(sizeof(LQSig)); lq_zero(sig, sizeof(LQSig)); sig->impl = lq_alloc(sizeof(LQ_SIGN_LEN)); - lq_cpy(sig->impl, sig_data, sig_len); + lq_cpy(sig->impl, sig_data, LQ_SIGN_LEN); return sig; } diff --git a/src/lq/base.c b/src/lq/base.c @@ -2,11 +2,12 @@ #include "config.h" +char zeros[65]; + int lq_init() { char err[1024]; int r; - lq_err_init(); return lq_config_init(); } diff --git a/src/lq/cert.c b/src/lq/cert.c @@ -11,7 +11,7 @@ #include "debug.h" -static char zeros[65]; +extern char zeros[65]; static LQPubKey nokey = { .pk = 0, .impl = zeros, @@ -360,18 +360,17 @@ int lq_certificate_deserialize(LQCert **cert, char *in, size_t in_len, LQResolve p = lq_certificate_new(NULL); lq_certificate_set_domain(p, tmp); - c = 4096; + c = LQ_BLOCKSIZE; r = asn1_read_value(item, "request", tmp, &c); if (r != ASN1_SUCCESS) { return ERR_READ; } - r = lq_msg_deserialize(&p->request, tmp, c, resolve); if (r != ERR_OK) { return r; } - c = 4096; + c = LQ_BLOCKSIZE; r = asn1_read_value(item, "request_sig", tmp, &c); if (r != ASN1_SUCCESS) { return ERR_READ; @@ -380,7 +379,7 @@ int lq_certificate_deserialize(LQCert **cert, char *in, size_t in_len, LQResolve p->request_sig = lq_signature_from_bytes(tmp, c, NULL); } - c = 4096; + c = LQ_BLOCKSIZE; r = asn1_read_value(item, "response", tmp, &c); if (r != ASN1_SUCCESS) { return ERR_READ; diff --git a/src/lq/err.c b/src/lq/err.c @@ -4,10 +4,11 @@ #ifdef RERR -static char *_rerr[3] = { +static char *_rerr[4] = { "", "Invalid request", "Invalid response", + "Not resolved", }; static char *_rerr_crypto[12] = { diff --git a/src/lq/err.h b/src/lq/err.h @@ -1,6 +1,8 @@ #ifndef LIBQAEDA_ERR_H_ #define LIBQAEDA_ERR_H_ +#define LQ_ERRSIZE 1024 + // provides ERR_OK = 0, ERR_FAIL = 1, ERR_UNIMPLEMENTED = 2 #include <rerr.h> @@ -10,6 +12,7 @@ enum err_e { ERR_NONSENSE = 0x101, ///< Available data does not make sense in context ERR_REQUEST = 0x102, ///< Error related to certificate request messages ERR_RESPONSE = 0x103, ///< Error related to certificate response messages + ERR_RESOLVE = 0x104, ///< Error related to resolving message hashes RERR_PFX_CRYPTO = 0x200, ERR_NOCRYPTO = 0x201, diff --git a/src/lq/msg.c b/src/lq/msg.c @@ -12,7 +12,8 @@ #include "lq/store.h" #include "debug.h" -static char zeros[LQ_PUBKEY_LEN]; + +extern char zeros[65]; static LQPubKey nokey = { .pk = NULL, .impl = zeros, @@ -111,6 +112,7 @@ void lq_msg_free(LQMsg *msg) { } int lq_msg_serialize(LQMsg *msg, char *out, size_t *out_len, LQResolve *resolve) { + char resolved; size_t c; int r; size_t mx; @@ -122,6 +124,7 @@ int lq_msg_serialize(LQMsg *msg, char *out, size_t *out_len, LQResolve *resolve) asn1_node node; char *keydata; + resolved = LQ_MSG_DIGESTONLY; mx = *out_len; *out_len = 0; lq_set(&node, 0, sizeof(node)); @@ -147,6 +150,11 @@ int lq_msg_serialize(LQMsg *msg, char *out, size_t *out_len, LQResolve *resolve) return r; } resolve_active = resolve_active->next; + resolved = LQ_MSG_RESOLVED; + } + + if (resolved & LQ_MSG_DIGESTONLY) { + debug(LLOG_DEBUG, "msg", "no resolver"); } r = asn1_write_value(node, "Qaeda.Msg.data", tmp, c); @@ -201,13 +209,15 @@ int lq_msg_serialize(LQMsg *msg, char *out, size_t *out_len, LQResolve *resolve) int lq_msg_deserialize(LQMsg **msg, const char *in, size_t in_len, LQResolve *resolve) { int r; size_t c; - char err[1024]; + char resolved; + char err[LQ_ERRSIZE]; char z[LQ_DIGEST_LEN]; - char tmp[1024]; + char tmp[LQ_BLOCKSIZE]; asn1_node node; asn1_node item; LQResolve *resolve_active; + resolved = LQ_MSG_DIGESTONLY; lq_zero(&node, sizeof(node)); lq_zero(&item, sizeof(item)); r = asn1_array2tree(defs_asn1_tab, &node, err); @@ -230,17 +240,33 @@ int lq_msg_deserialize(LQMsg **msg, const char *in, size_t in_len, LQResolve *re if (r != ASN1_SUCCESS) { return ERR_READ; } - c = 1024; + c = LQ_BLOCKSIZE; resolve_active = resolve; while (resolve_active != NULL) { r = resolve_active->store->get(LQ_CONTENT_MSG, resolve_active->store, z, LQ_DIGEST_LEN, tmp, &c); if (r != ERR_OK) { return r; } + resolved = LQ_MSG_RESOLVED; resolve_active = resolve_active->next; } + if (resolved & LQ_MSG_DIGESTONLY) { + lq_cpy(tmp, z, LQ_DIGEST_LEN); + c = LQ_DIGEST_LEN; + } else { + if (!(resolved & LQ_MSG_RESOLVED)) { + return ERR_RESOLVE; + } + } *msg = lq_msg_new((const char*)tmp, c); + (*msg)->state = resolved; + (*msg)->data = lq_alloc(c); + if ((*msg)->data == NULL) { + return ERR_MEM; + } + (*msg)->len = c; + lq_cpy((*msg)->data, tmp, c); /// \todo document timestamp size c = 8; @@ -255,11 +281,12 @@ int lq_msg_deserialize(LQMsg **msg, const char *in, size_t in_len, LQResolve *re lq_cpy(&((*msg)->time.tv_sec), tmp, 4); lq_cpy(&((*msg)->time.tv_nsec), ((char*)tmp)+4, 4); - c = 65; + c = LQ_PUBKEY_LEN; r = asn1_read_value(item, "pubkey", tmp, (int*)&c); if (r != ASN1_SUCCESS) { return ERR_READ; } + (*msg)->pubkey = lq_publickey_new(tmp); return ERR_OK; } diff --git a/src/lq/msg.h b/src/lq/msg.h @@ -7,6 +7,11 @@ #include "lq/crypto.h" #include "lq/store.h" +enum lq_msgstate_e { + LQ_MSG_DIGESTONLY = 1, + LQ_MSG_RESOLVED = 2, +}; + /** * \struct LQMsg * @@ -15,6 +20,7 @@ * \see lq_msg_t */ struct lq_msg_t { + char state; ///< Message resolution state char *data; ///< Arbitrary data constituting the message. size_t len; ///< Length of arbitrary data. struct timespec time; ///< Nanosecond timestamp of when the message was created. diff --git a/src/test/test_cert.c b/src/test/test_cert.c @@ -97,25 +97,28 @@ START_TEST(check_cert_sig_res) { } END_TEST -START_TEST(check_cert_symmetric_nomsg) { +START_TEST(check_cert_symmetric_ser_nomsg) { int r; size_t c; LQCert *cert; - char buf[4096]; + char buf[LQ_BLOCKSIZE]; cert = lq_certificate_new(NULL); - c = 4096; + ck_assert_ptr_nonnull(cert); + c = LQ_BLOCKSIZE; r = lq_certificate_serialize(cert, buf, &c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); + cert = lq_certificate_new(NULL); + ck_assert_ptr_nonnull(cert); r = lq_certificate_deserialize(&cert, buf, c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); } END_TEST -START_TEST(check_cert_symmetric_req_nosig) { +START_TEST(check_cert_symmetric_ser_req_nosig) { int r; size_t c; LQCert *cert; @@ -123,20 +126,26 @@ START_TEST(check_cert_symmetric_req_nosig) { char buf[4096]; req = lq_msg_new(data, strlen(data) + 1); + ck_assert_ptr_nonnull(req); + cert = lq_certificate_new(NULL); + ck_assert_ptr_nonnull(cert); + r = lq_certificate_request(cert, req, NULL); - c = 4096; + c = LQ_BLOCKSIZE; r = lq_certificate_serialize(cert, buf, &c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); + cert = lq_certificate_new(NULL); + ck_assert_ptr_nonnull(cert); r = lq_certificate_deserialize(&cert, buf, c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); } END_TEST -START_TEST(check_cert_symmetric_req_sig) { +START_TEST(check_cert_symmetric_ser_req_sig) { int r; size_t c; LQCert *cert; @@ -145,18 +154,25 @@ START_TEST(check_cert_symmetric_req_sig) { char buf[4096]; pk = lq_privatekey_new(passphrase, 32); + ck_assert_ptr_nonnull(pk); + r = lq_privatekey_unlock(pk, passphrase, 32); + ck_assert_int_eq(r, 0); req = lq_msg_new(data, strlen(data) + 1); + ck_assert_ptr_nonnull(req); + cert = lq_certificate_new(NULL); - lq_privatekey_unlock(pk, passphrase, 32); + ck_assert_ptr_nonnull(cert); r = lq_certificate_request(cert, req, pk); ck_assert_int_eq(r, 0); - c = 4096; + c = LQ_BLOCKSIZE; r = lq_certificate_serialize(cert, buf, &c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); + cert = lq_certificate_new(NULL); + ck_assert_ptr_nonnull(cert); r = lq_certificate_deserialize(&cert, buf, c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); @@ -164,7 +180,7 @@ START_TEST(check_cert_symmetric_req_sig) { } END_TEST -START_TEST(check_cert_symmetric_rsp_onesig) { +START_TEST(check_cert_symmetric_ser_rsp_onesig) { int r; size_t c; LQCert *cert; @@ -186,6 +202,7 @@ START_TEST(check_cert_symmetric_rsp_onesig) { ck_assert_int_eq(r, 0); lq_certificate_free(cert); + cert = lq_certificate_new(NULL); r = lq_certificate_deserialize(&cert, buf, c, NULL); ck_assert_int_eq(r, 0); r = lq_certificate_respond(cert, res, pk); @@ -195,7 +212,7 @@ START_TEST(check_cert_symmetric_rsp_onesig) { } END_TEST -START_TEST(check_cert_symmetric_rsp_bothsig) { +START_TEST(check_cert_symmetric_ser_rsp_bothsig) { int r; size_t c; LQCert *cert; @@ -226,6 +243,7 @@ START_TEST(check_cert_symmetric_rsp_bothsig) { ck_assert_int_eq(r, 0); lq_certificate_free(cert); + cert = lq_certificate_new(NULL); r = lq_certificate_deserialize(&cert, buf, c, NULL); ck_assert_int_eq(r, 0); lq_certificate_free(cert); @@ -238,14 +256,14 @@ Suite * common_suite(void) { s = suite_create("cert"); tc = tcase_create("sign"); - tcase_add_test(tc, check_cert_sig_req); - tcase_add_test(tc, check_cert_sig_res); +// tcase_add_test(tc, check_cert_sig_req); +// tcase_add_test(tc, check_cert_sig_res); suite_add_tcase(s, tc); tc = tcase_create("serialize"); // tcase_add_test(tc, check_cert_symmetric_ser_nomsg); // tcase_add_test(tc, check_cert_symmetric_ser_req_nosig); -// tcase_add_test(tc, check_cert_symmetric_ser_req_sig); + tcase_add_test(tc, check_cert_symmetric_ser_req_sig); // tcase_add_test(tc, check_cert_symmetric_ser_rsp_onesig); // tcase_add_test(tc, check_cert_symmetric_ser_rsp_bothsig); suite_add_tcase(s, tc);